gitlab-ci

Push to GitLab triggering multiple pipelines


I have a GitLab repo with CI setup. My .gitlab-ci.yaml looks something like

stages:
  - lint
  - build
  - test

Lint:
  rules:
    - if: $CI_COMMIT_TAG
      when: never
    - when: always
  ...

Build:
  stage: build
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_PIPELINE_SOURCE == "web"
    - if: $CI_COMMIT_BRANCH == "master"
    - if: $CI_COMMIT_TAG
  ...

Test:
  stage: test
  # same rules as Build
  ...

I currently have a merge request open for my branch but, when I push changes, two pipelines get started. One of them includes the lint, build, and test stages while the other only includes the lint stage. Why is that second pipeline being created?


Solution

  • Once you open a merge request for a branch. If you then push to that branch again Gitlab will trigger two pipelines. The first is a push pipeline. this is triggered because you pushed to the branch. The second pipeline is a merge request pipeline and is triggered because there is an open merge request.

    If you look in the pipelines page you will see both pipelines use the same commit ID, one will be against the branch (the push pipeline). The other will be against the MR (the merge pipeline)

    So now we understand why there are two pipelines lets look at how gitlab evaluates if the job should be added to the pipeline. Gitlab documents the behaviour of rules: if as

    If we look at each job and its rules.

    The lint job has 2 rules, if there is a CI_COMMIT_TAG then never run this job. CI_COMMIT_TAGs are only defined in tag pipeline, since these pipelines are a push and a merge pipeline this rule is not true. So it moves to the next which always evaluates to true. So this job will be added to both pipelines.

    In the build job there are 4 rules defined. The first rules checks if the pipelines type is a merge_request_event I.E a merge pipeline then the job is added.

    For the push pipeline this first rule will not be true so it will move on to rule 2. This rule checks if its a web pipeline. A web pipeline is a pipeline triggered from the UI. Since this is a push pipeline, this is also false.

    Rule 3 checks if its on the master branch, this will also be false since this is a feature branch.

    Rule 4 checks if the CI_COMMIT_TAG is set, thats only set on a tag pipeline so will not be set on a push pipeline so this rule is also false.

    Since no rules were matched for the build job in the push pipeline the job is not added. The same applies for the test job. So the result is the merge request will have all 3 jobs, and the push pipeline will only have the lint job.

    If you dont want both pipelines to trigger you can look at https://docs.gitlab.com/ee/ci/jobs/job_rules.html#avoid-duplicate-pipelines