Merge request pipelines and merge trains

GitLab CI/CD · Expert · 14 min

Busy repositories break main when individually green MRs conflict; the right pipeline type prevents that.

GitLab can create several kinds of pipeline for the same commit, and the difference matters:

  • Branch pipelines run on the pushed commit, with CI_PIPELINE_SOURCE == push. They can access protected variables only on protected branches.
  • Merge request pipelines (merge_request_event) run on the MR's source branch commit when it is opened or updated. Jobs need rules that match this source. They expose CI_MERGE_REQUEST_* variables such as the IID and target branch.
  • Merged results pipelines run on a temporary commit that merges the source into the current target branch, so tests see the code as it would be after merging.
  • Merge trains queue MRs. Each MR's pipeline runs on the target branch plus every MR ahead of it in the train. If one fails, it is removed and the ones behind it restart. When each pipeline passes, its MR merges in order, so main stays green even with many concurrent merges.

Without workflow:rules a push to a branch with an open MR can create both a branch pipeline and an MR pipeline, doubling cost. The $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS never-rule prevents that.

Merged results pipelines and merge trains are Premium features and require the project setting to be enabled; interruptible: true lets superseded pipelines be cancelled automatically to save runner time.

Example

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

default:
  interruptible: true            # cancel superseded pipelines

test:
  script:
    - echo "MR !$CI_MERGE_REQUEST_IID into $CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
    - make test
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

deploy:
  interruptible: false           # never cancel a deploy midway
  script: [./deploy.sh]
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Remember

  • Branch, MR, merged results and merge train pipelines test different commits
  • Merge trains test each MR on top of the ones queued ahead of it
  • workflow:rules prevents duplicate branch + MR pipelines

Watch out for

  • Writing rules only for branch pipelines, so jobs silently vanish from MR pipelines.

Check yourself

  1. Two MRs each pass their own pipeline but break main when both merge. What prevents this?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.gitlab.com/ci/pipelines/merge_trains/