Gitlab master branch pipeline is not running after merge - gitlab-ci

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.

Related

How to trigger a job only when files in root changed?

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.

Gitlab CI job running on new tag despite rules say run only on master

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.

How to prevent jobs from running when pushing tags and when branch is a specific one with rules

I'm a bit confused with the Gitlab I syntax.
I have some jobs that I don't want to trigger when I simply push tags like
git tag -a 1.0.0 -m "Added version 1.0.0"
git push --tags
The following works correctly, as this job is not being triggered for above scenario
build:
stage: build
script:
- dotnet restore --no-cache --force
- dotnet build --configuration Release --no-restore
artifacts:
paths:
- test
expire_in: 8 hour
rules:
- if: $CI_COMMIT_TAG
when: never
- when: always
Now I also have jobs with a rule to run conditionally depending on whether the commit branch is stable (i.e: main) or not.
Like this one
package_beta:
stage: publish
variables:
PACKAGE_UNSTABLE_SUFFIX: beta
before_script:
- mkdir $PACKAGE_OUTPUT_DIR
script:
- dotnet pack *.sln --configuration Release --output $PACKAGE_OUTPUT_DIR --version-suffix $PACKAGE_UNSTABLE_SUFFIX --include-source --include-symbols
rules:
- if: $CI_COMMIT_BRANCH != "main"
artifacts:
paths:
- $PACKAGE_OUTPUT_DIR/
expire_in: 8 hour
The above also works well. The problem is when I want to have several conditions in rules, like: I want my job to run only when branch is not main AND ALSO when the push is not a tag commit. How to do that with rules?
Here is the problem.
This does not work. It will actually run the job even when the branch is main.
rules:
- if: $CI_COMMIT_BRANCH != "main"
- if: $CI_COMMIT_TAG
when: never
This does not work either
rules:
- if: $CI_COMMIT_BRANCH != "main"
- if: $CI_COMMIT_TAG
when: never
- when: always

Gitlab CI rules with changes run on dev and master branch

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

GitLab CI: only trigger only merge request & specific branch

I realised that gitlab CI does not seem to allow multiple refs. It will only take the first.
E.g., for the instructions below, the merge_requests will be ignored, and will trigger whenever the develop branch is updated directly.
face-build:
stage: build
image: docker:19.03.8
services:
- docker:19.03.8-dind
script:
- sh some-scripts.sh
only:
refs:
- /^develop$/
- merge_requests
If I swap the merge_requests to be before /^develop$/ it will be triggered for all merge requests.
Is there anyway to set both to be valid?
If you are using GitLab 12.3 or later, try rules:if clause instead of only:
face-build:
stage: build
image: docker:19.03.8
services:
- docker:19.03.8-dind
script:
- sh some-scripts.sh
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^develop$/'
when: always
Please check Rules attributes so you can choose the most appropriat value for when (on_success, always, delayed or never).