How to use regex in gitlab-ci if rules? - regex

I would be very happy if someone could help me with the following issue.
I would like to run specific scripts only for tags starting with a given tag name.
The following rule works well for the tag 'wind-index' but what I need is a regex as I would like it to work also for tags such as 'wind-index_0.1'
rules:
- if: $CI_COMMIT_TAG == "wind-index"
when: always
I was expecting this to work but without success....
rules:
- if: $CI_COMMIT_TAG == \^wind-index\
when: always
I've tried all possible combinations with simple quotes, double quotes or \^wind-index.*\, none are working.
Any suggestion, help is more than welcome :-)

You need
/ as regex delimiters
== is equality comparison operator, you need a regex matching operator, =~.
You can use
rules:
- if: $CI_COMMIT_TAG =~ /^wind-index/
when: always

That should do the trick:
- if: $CI_COMMIT_TAG =~ /^wind-index/

Related

Regular expression help to get the opposite in a gitlab CI pipeline

I have below regular expression that check whether we do not have --deploy in a commit message
deploy_review:
<<: *deploy_review_base
except:
refs:
- tags
- master
variables:
- $CI_COMMIT_BRANCH != "review" && $CI_COMMIT_MESSAGE !~ /^.*--deploy/
Now I want to check the opposite of this, that is I want to check where this string --deploy is present in a commit message. Opposite of above expression. is there a way to achieve this ?
Appreciate any help on this
Thanks,
To invert the matching logic, just use =~ instead of !~.
Though your current logic (using !~) checks that the regex pattern does not match. =~ is used to check if the regex pattern does match. You should double check your regex pattern works as expected.

Get multiple lines using regex with Ansible

I have been trying to modify some files with Ansible but I do not have the right regex.
The goal is to modify a set of files and change everything between <Factory /> and </Factory> as "not register". As an example
I want to change this:
<Factory />
Replacement set
Madrid
</Factory>
to this:
<Factory />
Not register
<Factory />
What I have is the following:
hosts: all
tasks:
- name: replace factory registration
ansible.builtin.replace:
path: /home/clientDatabase.xml
regex: {'(?<=<Factory />.*?(?=</Factory>)', multiline = True}
replace: 'Not register'
I have tried several expressions and this is the closest I have got. It works perfectly on notepad++ if you set the regular expression on and check the .match newline box but it does not do anything in ansible.
What I understand is from (?<=) to (?=) get me everything in between (.*) that is 0 or once (?), check on multiple lines to get the whole structure (multiline = True).
I have also tried \R for return carrier and break line, the ^ and $ ones but from all the tries I had it does not work and I am getting out of ideas.
Could someone give me any hints here?
Here are some resources I think helped me the most:
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html
https://w3.unpocodetodo.info/utiles/regex.php
Update:
Finally, I follow your suggestion, using [^<]*? match everything except the "<" character and it worked perfectly. The parenthesis was a mispell, sorry
The final result is:
hosts: all
tasks:
- name: replace factory registration
ansible.builtin.replace:
path: /home/clientDatabase.xml
regex: '(?<=<Factory />)[^<]*?'
replace: 'Not register'
What I understand is from <Factory /> replace all content up to the first <. With this statement not multiline, nor dotall flag need to be use.
I suggest the following regex which allows words, spaces and newline between the tags <Factory /> and </Factory>.
Please note that the string is on 2 lines because it contains a newline as part of the pattern.
(?<=<Factory \/>)[\w\s
]*(?=<\/Factory>)
this could also be written
(?<=<Factory \/>)[\w\s\n\r]*(?=<\/Factory>)

Pattern Matching for rules parameter Gitlab CI

I am trying to make use of the rules: parameter to make a job only appear in a pipeline if specified users did the push. I dont want to define the list of users for each job, so I have the following global variable:
variables:
USER_LIST: "user1 user2 user3"
and in the job, I have the following:
rules:
- if '$USER_LIST =~ /$GITLAB_USER_LOGIN/'
when: on_success
- when: never
This does not appear to be working, as I suspect the regex pattern being used is not being replaced by the variable, and using $GITLAB_USER_LOGIN as the search string. If I use an explicit search:
rules:
- if '$USER_LIST =~ /user1/'
when: on_success
- when: never
then the pattern matches just fine.
NOTE: I am aware that GITLAB_USER_LOGIN is a protected variable. I get the same problem with GITLAB_USER_EMAIL too.
So the question is, how can I put a GITLAB predifined variable into a string that will be used for pattern matching?
You are using a variable and not a regular expression in your rule. So you don't need the slashes around the $GITLAB_USER_LOGIN variable. Try something like this:
rules:
- if '$USER_LIST =~ $GITLAB_USER_LOGIN'
I have more or less the same problem setup. The issues mentioned in the comments were addressed in 15.1, see https://docs.gitlab.com/ee/ci/jobs/job_control.html#store-the-regex-pattern-in-a-variable.
Nevertheless '$USER_LIST =~ /$GITLAB_USER_LOGIN/' still doesn't work. Also, if you define a variable like pattern: /$GITLAB_USER_LOGIN/ and use that in the way described in the documentation, it doesn't work.
'$USER_LIST =~ $pattern'
What works, but isn't the solution to your or my problem is defining pattern with a fixed pattern, like pattern: /user1/. Then it works if used like this:
'$USER_LIST =~ $pattern'
But obviously, I want to use the actual user, that tries to create a pipeline.
What works on my instance (15.4) is this:
'$GITLAB_USER_LOGIN =~ $USER_LIST'
I have no idea why, cos in my opinion this is no behaviour suggested by the documentation. I looked around in several places and found no documented examples of this use, but it works.
This job gets created with a delayed start:
variables:
pattern: "user"
string: "this contains user and other stuff"
show-env:
stage: env
tags:
- ops
rules:
- if: $pattern =~ $string
when: delayed
start_in: 15m
- when: always
script:
- env
And if you remove user from string and push it again, it gets executed right away.
And it also works when I define USERLIST in the project ci/cd variables and test that against $GITLAB_USER_LOGIN.
The documentation shows that the content matching regex should look like this:
$VARIABLE =~ /^content.*/
for your code you need to add ^ and .*:
rules:
- if '$USER_LIST =~ /^user1.*/'
when: on_success
- when: never
My workaround is to build an dynamic-child-pipeline where the variable within pattern already evaluated and inserted as constant string.

Need IP Address mask and DNS host name regular expressions?

I need to allow an IP/DNS name from a text box. I am looking for a IP regular expression which work for IP.
Now I am using one regular expression:
/\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/
which was working for 0-255 range. But allowing invalid IP such as : 121.21.05.234.01 which has 5 parts.
I need a regular expression which will work in all scenario's like below:
10.2.22.1 - true
123.123.123.123 - true
123.123.023.12 - true
12.23.12.0 - true
121.21.05.234.01 - false
Please provide me DNS expression also.
Try to anchor your regex with ^ and $, which will make it match the whole string.
Are you looking for a way to specify an occurrence count?
You may achieve this with curly brackets.
An exemple here.
In your case, it would lead to:
/\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\b/
(I added a \ to escape the dot, too)

Why is it selecting this file?

I have the following statement:
Directory.GetFiles(filePath, "A*.pdf")
.Where(file => Regex.IsMatch(Path.GetFileName(file), "[Aa][i-lI-L].*"))
.Skip((pageNum - 1) * pageSize)
.Take(pageSize)
.Select(path => new FileInfo(path))
.ToArray()
My problems is that the above statement also finds the file "Adali.pdf" which it should not - but i cannot figure out why.
The above statement should only select files starting with a, and where the second letter is in the range i-l.
Because it matches Adali taking 3rd and 4th characters (al):
Adali
--
Try using ^ in your regex which allows looking for start of the string (regex cheatsheet):
Regex.IsMatch(..., "^[Aa][i-lI-L].*")
Also I doubt you need asterisk at all.
PS: As a sidenote let me notice that this question doesn't seem to be written that good. You should try debugging this code yourself and particularly you should try checking your regex against your cases without LINQ. I'm sure there is nothing to do here with LINQ (the tag you have in your question), but the issue is about regular expressions (which you didn't mention in tags at all).
You are not anchoring the string. This makes the regex match the al in Adali.pdf.
Change the regex to ^[Aa][i-lI-L].* You can do just ^[Aa][i-lI-L] if you don't need anything besides matching.
You should to do this
var f = Directory.GetFiles(tb_Path.Text, "A*.pdf").Where(file => Regex.IsMatch(Path.GetFileName(file), "[Aa][i-lI-L].pdf")).ToArray();
When you call ".*" Adali accept in Regex