I have a large NodeJS monorepo and I want to trigger a job when the package.json in the root of the monorepo was changed, but not if a package.json in any of the contained child projects changed.
test:
script:
- echo GitLab CI is such a pain sometimes
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
changes:
- ${CI_PROJECT_DIR}/package.json
- ./package.json
- /package.json
when: on_success
- when: never
None of these 3 patterns will trigger the job. Only when I use package.json will it trigger, but then it also triggers for any changed package.json.
I didn't find any mention of what the expected path syntax actually is in the GitLab documentation and trial-and-error is getting me nowhere.
The best approach I could come up with right now is:
test:
script:
- echo GitLab CI is such a pain sometimes
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
changes:
- package.json
when: on_success
- if: '$CI_PIPELINE_SOURCE == "push"'
changes:
- packages/**/package.json
when: never
- when: never
But this also doesn't seem to work reliably. As the documentation says:
Rules are evaluated when the pipeline is created, and evaluated in order until the first match. When a match is found, the job is either included or excluded from the pipeline, depending on the configuration.
So once the first rule matches, because any package.json was changed, the job is included.
Thanks to a very helpful answer in the GitLab forums, I realized that I must have been making a mistake in my repo.
Just providing package.json shouldn't trigger on changes in subfolders. Some other mistake must have caused the pipelines to be triggered.
Related
I have a job in a pipeline as such:
msi_build:
stage: Build
script:
- cd project_name
- ls -a
- wine python setup.py bdist_msi
rules:
- if: '$CI_COMMIT_REF_NAME == $BUILD_BRANCH'
- changes:
- /*.{py, html, css, yml, json}
tags:
- pywine
artifacts:
when: on_success
paths:
- /builds/$CI_PROJECT_PATH/project_name/dist/*.msi
expire_in: 1 yrs
But this also runs when I tag a commit and push it in another branch.
BUILD_BRANCH is master. This won't run when only pushing normal commits to other branches. And it'll run when pushing to master. But for some reason unknown to me, it also runs on tagged commits. What is the cause?
If it matters I used: git push --atomic origin <branch name> <tag> when pushing to another branch.
rules:
- if: '$CI_COMMIT_REF_NAME == $BUILD_BRANCH'
- changes:
- /*.{py, html, css, yml, json}
is not
rules:
- if: '$CI_COMMIT_REF_NAME == $BUILD_BRANCH'
changes:
- /*.{py, html, css, yml, json}
The first one runs when $CI_COMMIT_REF_NAME == $BUILD_BRANCH OR when the files were changed. The second one runs the job when that and that is equal AND the files with extensions were changed. Most probably in the commit the tag is run for the files with those extensions were changed, so the command is run, ignoring the first condition, because it's "or".
It's a good idea to add when: on_success to rules: explicitly, so it's nicely visible.
I have the following the .gitlab-ci.yml:
stages:
- build
workflow:
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables:
ENVIRONMENT_TYPE: 'prod'
- if: $CI_COMMIT_REF_PROTECTED == 'true' && $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH
variables:
ENVIRONMENT_TYPE: 'preprod'
- if: $CI_COMMIT_REF_PROTECTED == 'false'
variables:
ENVIRONMENT_TYPE: 'review'
- if: $CI_MERGE_REQUEST_ID
when: never
Compile:
stage: build
image: node
only:
- branches
script:
- yarn install
- yarn build
and if my branch is feature/xyz, and I push, it runs the pipeline which is wanted. but if I merge, the pipeline won't run on master branch.
I added:
- if: $CI_MERGE_REQUEST_ID
when: never
Because if I push to my normal branch, it will run 2 pipelines rather one (a detached pipeline is introduced).
Can someone pelase help what am I missing?
After more investigations, it turns out that there was nothing wrong with the .gitlab-ci.yml I posted in the question.
It was all perfect.
It turns out that I had AUTO_STOP: 0 environment variable in one of the workflows which was preventing the pipeline from running. (undocumented variable https://docs.gitlab.com/search/?query=AUTO_STOP )
I was able to reproduce this, and I reported this as an issue https://gitlab.com/gitlab-org/gitlab/-/issues/341713. Here is the reproduced merge https://gitlab.com/adham.sabry/pipeline-test/-/merge_requests/5 where the protected branch did not have pipeline to start.
I hope this helps and no one stumbles across this.
The lint:php stage should be run both on the dev as well as the master branch in GitLab. The issue however is, if there's a change in for example api/src/test.php it runs successfully on the dev branch, however when I then merge it in the master branch, the lint:php stage doesn't run any more.
Question: How can I achieve the desired effect of running it on both dev and master if there's a change in the api/src folder?
lint:php:
stage: test
image: php:7.4-fpm-alpine
interruptible: true
allow_failure: true
script:
- cd api && bin/php-cs-fixer fix --dry-run --diff src
rules:
- if: $LANGUAGE_RELEASE
when: never
- changes:
- api/src/*
when: always
- when: never
Note: $LANGUAGE_RELEASE is used by a webhook/api trigger, using https://gitlab.com/api/v4/projects/XXX/trigger/pipeline with the postfields token=XXX&ref=master&variables[LANGUAGE_RELEASE]=1
I am trying to skip a GitLab ci job based on the results of the previous job, however, as a result, the job never runs. I have the impression that rules are evaluated at the beginning of the Pipeline not at the beginning of the Job. Is there any way to make it work?
cache:
paths:
- .images
stages:
- prepare
- build
dirs:
stage: prepare
image:
name: docker.image.me/run:latest
script:
- rm -rf .images/*
- [ $(($RANDOM % 2)) -eq 1 ] && touch .images/DESKTOP
desktop:
stage: build
needs: ["dirs"]
image:
name: docker.image.me/run:latest
rules:
- exists:
- .images/DESKTOP
when: always
script:
- echo "Why is this never launched?"
Dynamically created jobs could be a solution (https://docs.gitlab.com/ee/ci/parent_child_pipelines.html#dynamic-child-pipelines).
You could create a yml-file with a your "desktop"-job in section "script" in your "dirs"-job if ".images/DESKTOP" is created.
Else your created yml-file should be empty.
The created yml-file can be triggered in a seperat job after "dirs"-job.
I'm using for creating dynamic child pipelines jsonnet (https://jsonnet.org/).
The rules evaluation is happening at the beginning of a Gitlab pipeline
Quoting from Gitlab docs https://docs.gitlab.com/ee/ci/yaml/#rules
Rules are evaluated when the pipeline is created, and evaluated in order until the first match. When a match is found, the job is either included or excluded from the pipeline, depending on the configuration.
Here the problem seems to be with the usage of exists keyword
Quoting from Gitlab docs https://docs.gitlab.com/ee/ci/yaml/#rulesexists
Use exists to run a job when certain files exist in the repository
But here it seems that .images/DESKTOP is in Gitlab's runner cache, not in your repository.
cache:
paths:
- .images
The following gitlab ci job will run if the variable $CI_COMMIT_TAG is set OR if the ./versions.txt file has changed.
some-job:
script:
- echo "Do some fancy stuff.";
rules:
- if: $CI_COMMIT_TAG
when: always
- changes:
- ./versions.txt
However, what I need is for this job to run when $CI_COMMIT_TAG is set AND ./versions.txt is changed. I don't want the job to run if only one of these evaluates to true. This was the behaviour in only/changes feature, but the only (and except)-feature is less powerful and deprecated.
Is what I want currently possible with gitlab ci?
From Docs:
In the following example:
We run the job manually if Dockerfile or any file in docker/scripts/ has changed AND $VAR == "string value". Otherwise, the job will not be included in the pipeline.
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: '$VAR == "string value"'
changes: # Will include the job and set to when:manual if any of the follow paths match a modified file.
- Dockerfile
- docker/scripts/*
when: manual
Your code will look something like this.
some-job:
script:
- echo "Do some fancy stuff.";
rules:
- if: $CI_COMMIT_TAG
changes:
- versions.txt
when: manual