gitlabgitlab-cirulescommitlint

Gitlab CI Rules: Skip Job for Merge


I use a typical Gitlab-Workflow, where a branch is covered by an Merge-Request and - in case the pipeline runs well - it can be merged into main.

My Issue

I have a job, that checks the commit using commitlint. This works fine, when committing to the merge request's branch or to the main.

Now, I want to skip this job for the merge commit that happens when I press "merge" or when the Merge Request gets merged after the pipeline succeeds.

Reason: That commit 'does not' and 'need not' to follow the commit msg conventions. That's why I don´t want that commit to be checked.

My try so far:

lint:commitMain:
  image: registry.hub.docker.com/library/node:alpine
  tags:
    - docker
  stage: lint
  variables:
    GIT_DEPTH: 0
  before_script:
    - apk add --no-cache git
    - npm install --save-dev @commitlint/config-conventional @commitlint/cli
  script:
    - npx commitlint --from $CI_COMMIT_BEFORE_SHA --to $CI_COMMIT_SHA
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: never
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
      when: on_success
    - when: never

I was hoping that:

    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: never

will skip it but I get:

enter image description here

for the auto-gen commit:

enter image description here

Help appreciated

I'm kind of stuck, because I have currently no glue why and how. So, it would be very kind to get some light into it.

Thanks


Solution

  • It seems you are a bit confused about the pipeline types and when they are triggered. This might be a vexing topic, so don't worry, the understanding will come with more experience.

    The reason why the lint:commitMain job got included in your screenshotted pipeline is actually very simple: that is a branch pipeline, not a MR pipeline. You can tell by the decorations on your first screenshot, and the second screenshot actually shows a finished merge commit on the main branch, not the open MR that would lead to that merge commit being created.

    Another way to differentiate the pipelines can be seen here:

    Pipelines list screenshot

    The top pipeline is a MR pipeline for MR 2943, the bottom one is a branch pipeline for the branch feature-TP-7017_latest_due_date -- these are two different pipelines even though both of them were triggered for the same commit 7454289e.

    Branch pipelines are triggered for any commit into any branch. MR pipelines are triggered for any commit into a source branch of an open MR. As you can see these conditions aren't mutually exclusive, and one commit could in fact trigger 2 pipelines at the same time (this is exactly what my screenshot shows).

    Last thing to note is what happens when the MR is accepted/closed: in this case Gitlab creates a new commit (via merge or ff, depending on the settings) on the target branch, the source branch is (optionally) deleted, and the MR is marked as closed. As you can probably guess, this new merge commit triggers a new branch pipeline on the target branch of the MR which just got accepted. And this is exactly what happens in your situation.

    So, we've established that we're talking about branch pipeline.

    What you want to achieve is to make sure that lint:commitMain job doesn't run after the MR into main has been accepted. In this case this rule:

        - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
          when: never
    

    cannot help you, because the $CI_PIPELINE_SOURCE value is push, not merge_request_event -- it's not a MR pipeline, after all.

    Since you probably want to still run lint:commitMain job when "normal" (non-merge) commits are pushed into main, you need to find a way to differentiate between normal commits pushed into main by people, and merge commits created on main by accepting MRs via Gitlab UI. An easy way would be to check $CI_COMMIT_MESSAGE -- default Gitlab merge commit message says "Merge branch 'source' into 'target'", and you could do something like this

        - if: $CI_COMMIT_MESSAGE =~ "Merge branch '.*' into 'main'"
          when: never
    

    To make sure you understand differences between MR pipelines and branch pipelines I would recommend defining $CI_DEBUG_TRACE variable for your project and comparing the values of Gitlab's predefined $CI_* variables.

    Hope this helps.