Difference between different GitLab CI Merge Request rules

Viewed 2212

As several other users, I'm facing issues with duplicate pipelines in GitLab CI/CD. While there is some documentation on how to prevent this scattered around in the GitLab docs, my impression is that the indivdual docs pages and sections are rather inconsistent.

My question is, what are the differences between the following rules? Or, more specifically, are there cases in which these rules are evaluated differently?

Any explanation or hints to docs pages I might have overlooked is highly appreciated.

1 Answers

In order to avoid duplicate pipeline creation and the requirement that you want to switch between Branch-Pipelines and Merge-Request-Pipelines I recommend using these workflow rules

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
      when: never
    - if: '$CI_COMMIT_BRANCH' || '$CI_COMMIT_TAG'

There is another SO-question that asks how to prevent duplicate pipelines here

The Explanation(s):

In the following section I will try to explain your different rules and how GitLab CI will evaluate them during pipeline creation.

The merge_request_event-rule

Using this rule:

if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

will create a pipeline each time a Merge-Request is created/updated, but there will also be a pipeline created for the branch if you do not have another prevention mechanism (rule). As the variable naming also points out, this is about the source of the pipeline trigger, other sources could be schedule, push, trigger etc.

The CI_OPEN_MERGE_REQUESTS variable:

Using a rule like:

if: '$CI_OPEN_MERGE_REQUESTS'

GitLab will create new pipelines if there is an open Merge-Request for this branch. Pipelines because there will be a Merge-Request pipeline (denoted with the detached flag) and a branch pipeline for the branch you pushed changes.

if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'

This rule above will create a pipeline for your branch when, and only when there is an open MR on that branch.

if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never

When using the above combination no pipeline will be created if there are open Merge-Requests on that branch, which might also be undesirable since the CI should run tests for branches and/or Merge-Requests.

But how to be able to have pipelines for MRs and Branches, but prevent duplications in pipeline creation?

- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
  when: never
- if: '$CI_COMMIT_BRANCH' || '$CI_COMMIT_TAG'

With this rule set above GitLab will create pipelines for branches and Merge-Requests (the detached ones), as well as pipelines for git-tags, but it will prevent GitLab from duplicating pipelines. The last rule evaluates to true either when there is a commit to a branch or there is a git-tag.

Further links

  • Official docs on switching between MR- and Branch-Pipelines
  • Docs on how to avoid duplicate pipelines with rules examples
Related