概要

GitLab CI/CDでマージリクエスト時に、適切にパイプラインが実行されませんでした。

その問題についてと、修正方法について説明します。

環境

  • GitLab 17.10
  • GitLab Runner 17.10

問題について

GitLabのリポジトリについて、プッシュ時にCI/CDの実行を設定しています。このCI/CDの設定について、マージリクエストを作成したときに、適切にパイプラインが実行されないという問題にぶつかりました。

このパイプラインの設定として、.gitlab-ci.ymlは次のように記述していました。

image: registry.gitlab.com/pages/hugo/hugo_extended:latest

variables:
  HUGO_ENV: production
  GIT_SUBMODULE_STRATEGY: recursive

stages:
  - test
  - deploy

textlint:
  image: node:lts-alpine
  stage: test
  script:
    - npm ci
    - npm run textlint

test:
  stage: test
  script:
    - hugo
  rules:
    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH

pages:
  stage: deploy
  script:
    - ./build.sh
  artifacts:
    paths:
      - public
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH

この.gitlab-ci.ymlでは、Hugoを利用して静的なHTMLサイトをビルドし、GitLab Pagesにアップロードしているものになります。また、textlintを利用して、記事の内容のチェックを行なっています。

上記の設定をしていた際にマージリクエストを行うと、textlintのテストが行われません。branchでのパイプラインでは行われています。

screenshot1.png

原因として考えられるのは、testpagesでのrules:設定の影響です。textlintではrules:を設定していないので、rules:の条件に関わらず必ず実行されるものと思っていましたが、そうではありませんでした。

解決方法

GitLab CI/CDのrules:の設定には、癖があるようです。具体的には、rules:の設定によっては複数のパイプラインが実行されたり、適切なジョブが実行されなかったりするというものです。

今回は、設定が間違っていることから、適切にジョブが実行されなかったものと思われます。

こちらについて、今回は次のように修正しました。

image: registry.gitlab.com/pages/hugo/hugo_extended:latest

variables:
  HUGO_ENV: production
  GIT_SUBMODULE_STRATEGY: recursive

stages:
  - test
  - deploy

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

textlint:
  image: node:lts-alpine
  stage: test
  script:
    - npm ci
    - npm run textlint
  rules:
    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH

test:
  stage: test
  script:
    - hugo
  rules:
    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH

pages:
  stage: deploy
  script:
    - apk add bash imagemagick libwebp libwebp-tools
    - ./build.sh
  artifacts:
    paths:
      - public
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH

修正した項目は、workflow:の追加と、textlintジョブへのrules:の追加です。

workflow:は、全体のパイプラインについて、どのような時に実行するのかを制御する項目です。今回は次のようにしました。

  • if: $CI_PIPELINE_SOURCE == "merge_request_event"
    • マージリクエストのイベント時にパイプラインを実行
  • if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
    • マージリクエストの作成されているブランチについて、when: neverを設定することでパイプラインを実行しない
    • CI_OPEN_MERGE_REQUESTSでマージリクエストが作成されているかを確認しています
  • if: $CI_COMMIT_BRANCH
    • 上記の条件に当てはらない場合で、ブランチのプッシュの場合、パイプラインを実行

これらの条件は、ORで設定するものになります。上から評価されて、当てはまるものがあればそこで判定は終了です。

これで、余計なパイプラインの実行は止められるようになりました。

さらに、textlintジョブにrules:を追加しました。条件は他のrules:のものを記述しており、testpagesの両方のジョブ実行時にtextlintジョブを実行するようにしました。

これで、正常にパイプラインが実行されるようになりました。

さいごに

CI/CDの設定はとても便利ですが設定が難しいという印象です。

今回の設定の重要な部分は、rulesworkflowです。rulesは、昔使われていたonlyexceptを置き換えるものとして追加されました。workflowは、マージリクエストの際など複数のパイプラインが作成される問題への対処として追加されたようです。これらは、昔はなかった設定になります。そのためあまり情報が少ない印象です。

他の方の参考になれば幸いです。