In the CI/CD Pipeline, I want to indicate for different gitlab-runner to run the job when the source branch is being merged to target branch. If source branch is being merged to dev
or test
branches I want one runner to run the job, but if source branch is being merged into master
branch I want another gitlab-runner to run this job.
What is the best way to achieve this goal ?
My idea was to use rules: keyword in the .gitlab-ci.yml
file and create something similar to this:
some_job:
rules:
- if: '$CI_COMMIT_REF_NAME == "master"'
tags:
- master-runner
- if: '$CI_COMMIT_REF_NAME == "dev"'
tags:
- dev-runner
- if: '$CI_COMMIT_REF_NAME == "test"'
tags:
- dev-runner
Would this work or is this not allowed ?
If this is not a correct way to do that, what would be the correct alternatives for this to be done ?
This won’t work because tags are not allowed here.
You can use a hidden job and extend it in next jobs that needs to be conditioned.
For example :
.some_job:
script:
- echo "job"
# Do whatever
master_job:
tags:
- master-runner
rules:
- if: $CI_COMMIT_REF_NAME == "master"
extends: .some_job
dev_job:
tags:
- dev-runner
rules:
- if: $CI_COMMIT_REF_NAME == "dev"
- if: $CI_COMMIT_REF_NAME == "test"
extends: .some_job
Also, if you want to use it for the target branch in a Merge Request, you should use $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
instead of $CI_COMMIT_REF_NAME
. See Predefined variables for Merge Requests.
It depends on what you want to do in the job, but generally, I would say that it’s better to split up the different cases into their own jobs. Merging to dev
or master
could for example also result in a deployment to staging or production server and therefor needs different configurations passed in the jobs.
To use different gitlab-runners for different cases, you would use the tags
parameter. It can’t be used as in your example though, since it is not an allowed child to the rules
parameter.
To only run a job when committing to a specific branch, as when merging to dev
, you can use a rule
to check - if: $CI_COMMIT_BRANCH == "dev"
.
It is also good practice to run the full chain of previous jobs when merging in case not all jobs was triggered while pushing to the merge request. This can be handled by having a dedicated stage
such as deploy
. Together, it could look like this:
stages:
- test
- build
- deploy
...
deploy-dev:
stage: deploy
rules:
- if: $CI_COMMIT_BRANCH == "dev"
...
deploy-master:
stage: deploy
rules:
- if: $CI_COMMIT_BRANCH == "master"
...
You can use workflow:rules
to set variables based on the branch running the pipeline. Then you can use that variable in the tags
section of your job to determine the runner it goes to. The following example will send the master branch to the runner tagged master-runner
and all other jobs to the runner tagged dev-runner
workflow:
rules:
- if: $CI_COMMIT_REF_NAME == 'master'
variables:
RUNNER: master-runner
- if: $CI_COMMIT_REF_NAME
variables:
RUNNER: dev-runner
some-job:
...
tags:
- $RUNNER
Beware that workflow rules determine when a pipeline, as a whole, will run. In this example, it should always run since the second condition just evaluates the existence of a predefined gitlab pipeline variable that should exist in any type of pipeline. There are cases when you use workflow rules that result in a pipeline not being created.