gitlab CI/CD rules:changes negate glob - gitlab

I have a build step in Gitlab CI/CD that I would like to skip if the only changing file is the readme file. My understanding is each entry listed under rules:changes is additive.
Additionally, the repository is set up as a "monorepo", in that there are different sub repositories listed under the packages directory.
Is there a way to specify under the rules section that there must be at least one changed file within packages/foo/, besides a change to packages/foo/readme.md?

rules:changes: takes glob patterns. And yes, your understanding is correct: by nature, glob patterns are inclusive only, so you cannot use add exclusionary parameters to a glob pattern or "negate" specific items that would otherwise match. Adding additional items to the changes: is also additive.
You can, however use negative-matching to include non-matching files (e.g., !(foo|bar|baz)). This should work for your use case.
So, a rule like this should work how you want:
rules:
- changes:
- "packages/foo/**/!(readme.md)"
Edit:
However, ruby's fnmatch doesn't support the ! metacharacter, so instead you can use the pattern:
packages/foo/**/{[^r]*,r,r[^e]*,re,re[^a]*,rea,rea[^d]*,read,read[^m]*,readm,readm[^e]*,readme,readme[^.]*,readme.,readme.[^m]*,readme.m,readme.m[^d]*,readme.md?*}
reference
Which should have the same effect.
rules:
- changes:
# same as "packages/foo/**/!(readme.md)"
# SEE: https://stackoverflow.com/a/69906355/5747944
- 'packages/foo/**/{[^r]*,r,r[^e]*,re,re[^a]*,rea,rea[^d]*,read,read[^m]*,readm,readm[^e]*,readme,readme[^.]*,readme.,readme.[^m]*,readme.m,readme.m[^d]*,readme.md?*}'
Tested in irb:
irb(main):011:0> pattern = './packages/foo/**/{[^r]*,r,r[^e]*,re,re[^a]*,rea,rea[^d]*,read,read[^m]*,readm,readm[^e]*,readme,readme[^.]*,readme.,readme.[^m]*,readme.m,readme.m[^d]*,readme.md?*}'
irb(main):012:0> File.fnmatch(pattern, './packages/foo/readme.md', File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB)
=> false
irb(main):013:0> File.fnmatch(pattern, './packages/foo/anything-else', File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB)
=> true

Related

How exactly do I set the protected branches regex format to limit what can be pushed to the repo?

I'm trying to figure out the regex pattern usage in GitLab in order to
Prevent any branch that does not follow the naming convention from be pushed up
Specify for example only these name formats can be used and at least 1 must be used: ^(bug)?(release)?(feature)?/.*\n
Has anyone done this with GitLab and can assist?
Tried the 'Settings > Repository > Protected branches > Protect a branch wildcard' to try and do this but it does not appear to work. I get 0 matches
Protected branch rule patterns do not support regex. Wildcard (*) is the only supported metacharacter. If you want a similar effect to you have in your regex ^(bug|release|feature).*, you will need to make multiple protected branch rules.
For example, you could make three rules:
bug*
feature*
release*

Dynamic test tag pattern execution in karate [duplicate]

I'm wondering if you can use wildcard characters with tags to get all tagged scenarios/features that match a certain pattern.
For example, I've used 17 unique tags on many scenarios throughout many of my feature files. The pattern is "#jira=CIS-" followed by 4 numbers, like #jira=CIS-1234 and #jira=CIS-5678.
I'm hoping I can use a wildcard character or something that will find all of the matches for me.
I want to be able to exclude them from being run, when I run all of my features/scenarios.
I've tried the follow:
--tags ~#jira
--tags ~#jira*
--tags ~#jira=*
--tags ~#jira=
Unfortunately none have given my the results I wanted. I was only able to exclude them when I used the exact tag, ex. ~#jira=CIS-1234. It's not a good solution to have to add each single one (of the 17 different tags) to the command line. These tags can change frequently, with new ones being added and old ones being removed, plus it would make for one real long command.
Yes. First read this - there is this un-documented expression-language (based on JS) for advanced tag selction based on the #key=val1,val2 form: https://stackoverflow.com/a/67219165/143475
So you should be able to do this:
valuesFor('#jira').isPresent
And even (here s will be a string, on which you can even do JS regex if you know how):
valuesFor('#jira').isEach(s => s.startsWith('CIS-'))
Would be great to get your confirmation and then this thread itself can help others and we can add it to the docs at some point.

gitlab branch common name - pipeline should be run execpt none branch should not be run

I want to run pipeline specific branches in GitLab like the branch names are sprint_100, Sprint-1,SPRINT-202.
How should I give commands in rules?
(/^SPRINT_[0-9]+\.[0-9]+$/)||(/^Sprint_[0-9]+\.[0-9]+$/)||(/^Sprint_[0-9]+\.[0-9]+$/)
I used this, but it doesn't work. Kindly help me to sort it out this. Thank you!
This rules clause should work for your example to run a pipeline only branch names like sprint_100, Sprint-1 or SPRINT-202.
The regex will match case-insensitive on branch names starting with 'sprint' followed by either '-' or '_' and an unlimited amount of digits.
I am no regex expert so this regex can likely be improved.
rules:
- if: '$CI_COMMIT_BRANCH =~ /^SPRINT[-_][0-9]+/i'

What does `only: -master` in gitlab-ci.yml match?

We have a .gitlab-ci.yml file containing lines like
a_task:
only:
- /^production\/mybranch.*$/
which are clearly meant to match the target git ref.
But we also have:
another_task:
only:
- master
My question is: does this "master" match a part of the git ref as well (so that a tag my-master-123 would match, too) or is it a symbolic thing?
The reason why am asking is that there is also:
third_task:
only:
- tags
That would have to be symbolic, right?
Which would mean that the syntax does e.g. not support a branch named tags, right?
Update
Looks like there are special keywords, tags being one of them.
So indeed that would mean that refs with those special names (external, pipelines, tags, triggers, ...) would not be supported.
from the docs:
only and except are two keywords that set a job policy to limit when jobs are >created:
only defines the names of branches and tags the job runs for.
except defines the names of branches and tags the job does not run for.
Matching via regular expressions is supported, as in your first case, but not default. only: master tasks will run for all refs named master.

node glob pattern include all js except in certain folders

I have a project that looks like this
ls foo/
- file0.js
- a/file1.js
- b/file2.js
- c/file3.js
- d/file4.js
How do I write a glob pattern to exclude the c & d folder but get all other javascript files? I have looked here for an example, but cannot get anything to work.
I imagine the solution would look similar to this:
glob('+(**/*.js|!(c|d))', function(err, file) {
return console.log(f);
});
I am wanting back
- file0.js
- a/file1.js
- b/file2.js
For environment where there isn't a second parameter to set the exclude, we can achieve such an exception using the pattern demonstrated in the example bellow:
Pattern
/src/**/!(els)/*.scss
structure
/src/style/kit.scss
/src/style/els/some.scss
/src/style/els/two.scss
result
it will select only /src/style/kit.scss
We can use http://www.globtester.com or https://www.digitalocean.com/community/tools/glob to test quickly online.
update
If we are working with Gulp task runner. Or some other tools or classes that offers a second or multiple parameters for exclusion. Or just multiple globs selectors that support exclusion too. Then We can do as the example bellow for gulp show:
for Gulp
We pass an array instead of just a string (multiple globs selectors, one apply after another to add more files or to exclude)
src(['src/style/**/*.{scss,sass}', '!(src/style/els/**)'])
We can have multiple exclusions
watch(['src/style/**/*.{scss,sass}', '!(src/style/els/**)', '!(src/style/_somefileToExclude.scss)'])
In gulp you can use that, with any method that support an array as globs selectors. src and watch are what i used that for.
Note: If you want to exclude a folder and all it's sub folders we use ** as above and not **/* which will not work. If you need some specific files types (extension) then you can use **/*.scss for example.
There is an ignore option I glazed over in the readme:
glob('**/*.js', { ignore: '{c,d}/**' }, cb)
This will exclude both c + d folders from the match. More here

Resources