How to run pipeline after merge request approved in Gitlab CI? - gitlab-ci

I want GitLab CI to run a job after a merge request is merged. I don't want it to be run on CREATING a new merge request and also I don't want it to be run whenever target branch is updated. (Since it's possible to commit directly to target branch and the job should not be run in that situation.)
Is that possible?
If yes, I also want to know informations about the merge request which triggered the job.
(Actually I want to update my project management system, when a merge request is merged. Thus I need to know which merge request is merged (or approved).)
Thanks in advance.

I want GitLab CI to run a job after a merge request is merged.
Unfortunately, GitLab does not offer a "merge request merged" trigger.
What you can do, is to make the pipeline run for any push in a certain branch and use branch-protection to make sure pushs can only come from merge requests. To do that:
Set your pipeline to only run e.g. for branch main:
# if you want to use "only":
my_job:
only:
- main
# or alternatively if you want to use rules you can do the same with:
my_job:
rules:
- if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_REF_NAME == "master"'
Enable Branch protection to disable direct pushes to main and only allow MRs:

You can run the pipeline after merge by using Gitlab ci predefined variable $CI_MERGE_REQUEST_APPROVED this will return true after merge has been done and available from gitlab v14.1.
you can add the rule like this in your job.
rules:
- if: $CI_MERGE_REQUEST_APPROVED

Related

Gitlab CI rule for when changes are ONLY selected files

I'm trying to modify an existing gitlab CI pipeline so that the "deploy" stage will not fire if the merge request's list of changed files is unrelated to the actual code being deployed.
deploy:
extends: .standard_template
only:
- master
- main
Right now deploy only occurs only on master or main branches and I'd like to continue that same logic, but I would also like to introduce the additional logic that if the ONLY thing changed is readme.md then don't do the deploy.
I've seen gitlabs support for the changes: rule, that appears to expect a matching subset of the listed files. What I want is to match a full set of readme.md and abort/not start the deploy.
Is this possible with gitlab's syntax? I know I could write additional "jobs" to do my own script: rules do stuff with the git-tree to inspect changes, but then I have to exit 1 to basically cause the pipeline to fail, which leads to a bunch of red failures or incomplete jobs in the build, when what I really want is just to omit this portion.
You can do this with a couple of rules:
deploy:
extends: .standard_template
rules:
- if: $CI_COMMIT_BRANCH != "main" && $CI_COMMIT_BRANCH != "master"
when: never
- changes:
- readme.md
when: never
- when: always
The first rule is the same as your only: main or master clause. If $CI_COMMIT_BRANCH is anything other than main or master, it won't add the job to the pipeline.
The second rule looks to see if there are changes to the readme.md file, but explicitly adds a when condition: never.
The third rule is our default case if the first two don't match.
All together this is, don't run if the branch isn't main/master, don't run if there are changes to the readme, otherwise always run.
Note: You'll likely have to extend this a bit since this doesn't account for Tag pipelines, merge request pipelines, etc., but that's simple to do with some additional rules.

Gitlab CI - Trigger daily pipeline only if new chanes have been commited

The company I work for has a self hosted Gitlab CE server v13.2.1.
For a specific project I've setup the CI jobs to build according to the following workflow :
If a commit has been pushed to the main branch
If a merge request has been created
If a tag has been pushed
Every day at midnight to build the main branch (using scheduled pipelines)
Everything works fine. The only thing I would like to improve is that the nightly builds are performed even if the main branch has not been modified (no new commit).
I had a look to the Gitlab documentation to change my workflow: rules in the .gitlab-ci.yml file but I didn't find anything relevant.
The gitlab runner is installed in a VM and is setup as a shell executor. I was thinking of creating in the home directory a file to store the last commit ID. I'm not a big fan of that solution, because :
it's a ugly fix.
The pipeline will be triggered by Gitlab even if it does nothing. This will pollute the pipeline list.
Is there any way to setup the workflow: section to perform this so the pipeline list won't contain unnecessary pipeline ?

Do not run Git Pipelines when merge TO and FROM default branch

Please help with gitlab-ci.yml the goal is to do not run pipeline when creating a copy branch from product named with auto-* and do not run pipeline when merging back from auto-* to product branch. BUT run pipeline when just commit to auto-* or to product and run pipeline for product when merging to it from non auto-* branches . Tried bellow workflow but does not work... pipeline runs all the time(
In short I do not want to run pipeline when creating for example auto-testing branch from product and do not want to run it when merging auto-testing back to product
By the way pipeline uploads to the same folder for both product and auto-*
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^auto-(.*)$/'
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH =~ /^auto-(.*)$/'
when: never
- if: '$CI_COMMIT_BRANCH == "product" || $CI_COMMIT_BRANCH =~ /^auto-(.*)$/'
Your problem is, that '$CI_PIPELINE_SOURCE == "merge_request_event" only covers pipelines that run within merge requests, not those that run after you merge it. GitLab does not differentiate Merge-Request results from normal pushes, so for those the variable will hold CI_PIPELINE_SOURCE=push.
In fact, there is no built-in way in GitLab to determine where a MR came frome that triggered a pipeline. As explained here you can use a workaround to get this information using the API.
Maybe a solution for you could be to built a pipeline that runs, requests the source branch using the API and immediately stops if the source branch starts with auto-*.

GitLab CI/CD run step only if on correct branch AND it has changes

I want a step in the build process only to run on the master branch, if there where changes to the src folder.
My .gitlab-ci.yml file thus contains:
build:php:
stage: build
image: alpine
interruptible: true
needs: [ "test:php" ]
script:
- do stuff // abreviated for simplicity
rules:
- if: $LANGUAGE_RELEASE
when: never
- if: '$CI_COMMIT_REF_SLUG == "master"' # run for production test branch
- changes:
- src/*
However, the issue here is, that it also runs on the dev branch, when I change anything.
Question: Is the a way to have this step only run, both conditions (the branch and the changes) are met?
When using the rules keyword, the rules:if clause may be used, with the variable $CI_COMMIT_BRANCH.
Thus, something like below to specify master as the only branch to run the job:
build:php:
stage: build
# ...
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
# ...
(Rules are applied in order)
The documentation reference for common if clauses available is here.
Now to combine an if and changes rule, you'll need to use
build:php:
stage: build
# ...
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
changes:
- file1 # single file
- folder/**/* # folder including all files and subfolders
# ...
You can read more about changes used in rules here and read the full changes specification here.
With the initial setup there where two issues:
the changes where seen as a new rule (since they had a - in front)
src/* only takes the src folder in consideration, not sub folders, for that you'll need src/**/*
It is also possible to use the only keyword to specify master as the only branch to run the job. Despite being simple, this is no longer encouraged and it cannot be used together with rules (only/except reference).
Example:
build:php:
stage: build
# ...
only:
- master
# ...
There is no way to run rules:changes on the master branch.
Gitlab docs says:
You should use rules: changes only with branch pipelines or merge
request pipelines. You can use rules: changes with other pipeline
types, but rules: changes always evaluates to true when there is no
Git push event. Tag pipelines, scheduled pipelines, manual pipelines,
and so on do not have a Git push event associated with them.
It means changes gives always true if there is different type than branches or merge_requests

Gitlab run different deploment scripts on merge depending on Labels

How can I run different CI deployment scripts on merge to master depending on the labels attached to the merge request?
I have a repository from which I build different versions of my software. I keep it in one repository as the systems share 90% of the code but there are differences that defitively need code modifications. On merge requests all versions are buildt and a suite of tests is run. Usually I want to deploy on accepting the merge request.
As not always the changes are relevant for all systems I would like to attach labels to the merge request that decide which deployments scripts are run on accepting the merge request. I already tried to automatically decide on the changed code parts but this is not possible as often I expand a shared library but this is only relevant for one of the systems.
I am aware of variables but I don't know how to apply them on merge accept in YML like this
deploy:
stage: deploy
script:
...
only:
- master
Update on strategy:
As CI_MERGE_REQUEST_LABELS is not available with only:master I will try to do a beta deployment depending on merge request labels in only:merge-request. In only:master I will deploy the betas that have changed. This most likely will fit my needs. I will add it as a solution once it works.
I finally solved it this way:
My YML script has three stages:
stages:
- buildtest
- createbeta
- deploy
buildtest:
stage: buildtest
script:
- ... run unit tests
- ... build all systems
- ... run scripted tests on all systems
only:
refs:
- merge_requests
createbeta:
stage: createbeta
script:
- ... run setup and update package creation with parameter $CI_MERGE_REQUEST_LABELS
- ... run update package tests with parameter $CI_MERGE_REQUEST_LABELS
- ... run beta deployment scripts with parameter $CI_MERGE_REQUEST_LABELS (see text)
only:
refs:
- merge_requests
deploy:
stage: deploy
script:
- ... run production deployment scripts (see text)
only:
refs:
- master
The first stages are run on merge request creation.
As changes to shared libraries might affect all systems all builds and tests are run in stage "buildtest".
The scripts in stage "createbeta" check for existance of the merge request label for the corresponding system and are skipped if the system is not involved by the labels.
The script for beta deployment creates a signal file "deploy_me" in the beta folder (important) if it runs
When the request is merged the deployment script runs in stage "deploy". It checks for the existance of the "deploy_me" file and only deploys and informs via mail if the file exists.
This way I can easily decide which system I want to deploy by applying a labes to the merge request. I can thorowly test the new feature with the beta version and make sure that changes do not break the other systems as unittests and system tests are run for all systems.
As the GitLab runner runs in a Windows environment (yes, this makes sense as I work with Delphi) here is the way I find the system label in a Windows cmd file for those who are interested. I use %* as the labels are separated by spaces and treated as individual command line parameters.
echo %* | findstr /i /c:"MyCoolSystem" > nul
if %ERRORLEVEL% EQU 0 goto runit
rem If the label is not supplied with the merge request, do nothing
goto ok
:runit
... content
:ok
Perhaps this helps someone with a similar environment and similar workflow.