Hello,
Hello, I’m trying to use a pipeline rule where, if a commit contains the word ‘crap’ at the end of the commit message, the pipeline shouldn’t run.
This is what the gitlab-ci looks like:
image: docker:24.0.2-dind
stages:
- build
- test
- compliance
variables:
NGINX_VERSION: 1.24.0-bullseye
build:
stage: build
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker build --build-arg VERSION=$NGINX_VERSION -t $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION .
- docker push $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
test:
stage: test
image: curlimages/curl:8.1.2
services:
- name: $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
alias: nginx
script:
- curl nginx
workflow:
rules:
- if: $CI_COMMIT_MESSAGE =~ /crap$/
when: never
- if: $CI_COMMIT_BRANCH == "main"
I’ve added the following commit message:
git commit -m "some other crap"
and pushed it, but the pipeline still ran. I’m not sure what I’m doing wrong. Any ideas?
I’m using gitlab-ee:16.1.1-ee.0 on Ubuntu 22.04.2
Have you tried removing the rules from the build job?
build:
stage: build
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker build --build-arg VERSION=$NGINX_VERSION -t $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION .
- docker push $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
Thanks for pointing this out, that was silly, indeed But unfortunately it still doesn’t work, the pipeline still runs. This is what the gitlab-ci looks like now:
image: docker:24.0.2-dind
stages:
- build
- test
- compliance
variables:
NGINX_VERSION: 1.24.0-bullseye
build:
stage: build
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker build --build-arg VERSION=$NGINX_VERSION -t $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION .
- docker push $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
test:
stage: test
image: curlimages/curl:8.1.2
services:
- name: $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
alias: nginx
script:
- curl nginx
workflow:
rules:
- if: '$CI_COMMIT_MESSAGE =~ /crap$/'
when: never
- if: '$CI_COMMIT_BRANCH == "main"'
The latest commit message is:
git commit -m "yet another crap"
Maybe it isn’t identifying ‘workflow’ as a keyword or something?
I’ve also tried with this pipeline where the rules are added for each job:
image: docker:24.0.2-dind
stages:
- build
- test
variables:
NGINX_VERSION: 1.24.0-bullseye
build:
stage: build
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker build --build-arg VERSION=$NGINX_VERSION -t $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION .
- docker push $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
rules:
- if: '$CI_COMMIT_MESSAGE =~ /crap$/'
when: never
- if: '$CI_COMMIT_BRANCH == "main"'
test:
stage: test
image: curlimages/curl:8.1.2
services:
- name: $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
alias: nginx
script:
- curl nginx
rules:
- if: '$CI_COMMIT_MESSAGE =~ /crap$/'
when: never
- if: '$CI_COMMIT_BRANCH == "main"'
Pushing commit with message “some crap” still runs.
Try it without encapsulating the rule in '
single quotes.
if: $CI_COMMIT_MESSAGE =~ /crap$/
1 Like
I’ve tried it before too to no avail. Now I’ve tried it again. Updated gitlab-ci:
image: docker:24.0.2-dind
stages:
- build
- test
variables:
NGINX_VERSION: 1.24.0-bullseye
build:
stage: build
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker build --build-arg VERSION=$NGINX_VERSION -t $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION .
- docker push $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
rules:
- if: $CI_COMMIT_MESSAGE =~ /crap$/
when: never
- if: $CI_COMMIT_BRANCH == "main"
test:
stage: test
image: curlimages/curl:8.1.2
services:
- name: $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
alias: nginx
script:
- curl nginx
rules:
- if: $CI_COMMIT_MESSAGE =~ /crap$/
when: never
- if: $CI_COMMIT_BRANCH == "main"
git commit -m "removed some crap"
Same thing unfortunately. The pipeline runs.
Not sure if the regex is correct for the re2 standard mentioned in Choose when to run jobs | GitLab It says it matches on regex101.com but that page supports a wide range of regex testing.
/.*crap$/
might be worth a try.
Enabling debugging could also shed more light. GitLab CI/CD variables | GitLab
Storing the regex pattern in a variable - does it change the behavior?
New gitlab-ci:
image: docker:24.0.2-dind
stages:
- build
- test
variables:
NGINX_VERSION: 1.24.0-bullseye
build:
variables:
CI_DEBUG_TRACE: "true"
stage: build
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- docker build --build-arg VERSION=$NGINX_VERSION -t $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION .
- docker push $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
rules:
- if: $CI_COMMIT_MESSAGE =~ /.*crap$/
when: never
- if: $CI_COMMIT_BRANCH == "main"
test:
variables:
CI_DEBUG_TRACE: "true"
stage: test
image: curlimages/curl:8.1.2
services:
- name: $CI_REGISTRY_IMAGE/nginx:$NGINX_VERSION
alias: nginx
script:
- curl nginx
rules:
- if: $CI_COMMIT_MESSAGE =~ /.*crap$/
when: never
- if: $CI_COMMIT_BRANCH == "main"
I’m not seeing any if conditionals related to the rules. I see this written exactly like this, which looks suspicious:
++ export 'CI_COMMIT_MESSAGE=crap
'
++ CI_COMMIT_MESSAGE='crap
'
This is the result of:
git commit -m "crap"
Later in the debug trace:
export CI_COMMIT_MESSAGE=$'"'"'crap\n'"'"'
So I guess there’s a new line there.
Changing it to:
/.*crap\n$/
Seems to be working. But it looks like a bug to me at first sight. Where does the newline come from? I’m just using git on a mac os and I’m nothing doing anything out of the ordinary other than commit and push.
Later Edit:
This also seems to be working:
/crap\n$/
so without the regex for everything.
Odd, I have never seen that before. (but also never tested for line endings with regex)
Searched for ci_commit_message
, and google auto completed to CI_COMMIT_MESSAGE regex examples in `rules` should not use prefix matching due to trailing new line (#348254) · Issues · GitLab.org / GitLab · GitLab
Seems that the Git CLI always appends a newline when using the -m flag.
2 Likes
Ok, to be honest, I don’t think I’ll ever use this, unless maybe I’d be playing around in dev and maybe switch between various builds/stages, whatever, but even then I’d probably choose some other criteria.
I really just wanted to have a better understanding of the rules and how they’re interpreted, but on this occasion I’ve come across this, so I’ll keep it in mind.
ChatGPT did mention something along these lines, but it said quite the reverse. Funny interpretation though
GitLab uses Ruby-style regular expressions in its if
conditions. In Ruby, the correct syntax to match the end of a string is \z
, not $
So you might want to try changing your rule to - if: $CI_COMMIT_MESSAGE =~ /crap\z/
.
Indeed, this is the documentation I started from, the one linked in the issue:
Documentation for GitLab Community Edition, GitLab Enterprise Edition, Omnibus GitLab, and GitLab Runner.
(probably should be fixed, but yeah, I’m guessing not a lot of people actually use it).
1 Like
Great learning curve I have seen use cases where folks check for context in git commits, and build a custom logic similar to [skip ci]
.
Hi,
with using a specifically crafted commit message, you can define rules in jobs to determine whether to execute them.
rules:
- if $CI_COMMIT_MESSAGE =~ /skip ci/
when: manual
allow_failure: true
Similar to what this blog post explains: https://www.cqse.eu/en/news/blog/skipping-tests-gitlab-ci/
Maybe this is a possible solution in your pipeline steps.
Cheers,
Michael