TECHSTEP

ITインフラ関連の記事を公開してます。

GitLab workflowを理解してパイプライン全体の挙動を制御する

今回はGitLabの workflow というキーワードを紹介します。

docs.gitlab.com

docs.gitlab.com

背景

GitLab CI/CDは多くのキーワードを利用できますが、 workflow はその一つです。 workflow はCI/CDパイプライン全体の挙動を制御するもので、どのような条件時にパイプラインを起動するか、といった挙動を制御します。

workflow は以下のキーワードが利用可能です。また各キーワードは組み合わせることもできます。

  • workflow:auto_cancel:on_new_commit
  • workflow:auto_cancel:on_job_failure
  • workflow:name
  • workflow:rules
  • workflow:rules:variables
  • workflow:rules:auto_cancel

workflow:auto_cancel:on_new_commit

workflow:auto_cancel はパイプラインを停止する設定を定義するキーワードです。

このうちworkflow:auto_cancelon_new_commitAuto-cancel redundant pipelineの挙動を制御するキーワードです。 Auto-cancel redundant pipelineは、あるパイプラインが保留・起動中に同じブランチ由来のパイプラインが起動したとき、保留・起動中のパイプラインを停止する機能です。

workflow:auto_cancel:on_new_commit は新しいコミットがブランチにpushされたときの挙動を制御します。入力可能な設定値は以下の3つです。

  • conservative: interruptible: false を設定したJobが開始されていない場合にパイプラインをキャンセルします。なにも設定されていない場合のデフォルト設定がこちらです。
  • interruptible: interruptible: true を設定したJobのみをキャンセルします。
  • none: Jobの自動キャンセルをしません。

GitLabのドキュメントでは以下ような例を紹介しています。この場合、すでにパイプラインが起動中に新しいコミットが発生すると job1 だけがキャンセルされます。

workflow:
  auto_cancel:
    on_new_commit: interruptible

job1:
  interruptible: true
  script: sleep 60

job2:
  interruptible: false
  script: sleep 60

workflow:auto_cancel:on_job_failure

workflow:auto_cancel:on_job_failure は、パイプライン中のいずれかのJobが失敗したときにパイプライン全体を停止するか否かを制御するキーワードです。入力可能な設定値は以下の2つです。

  • all: 1つでもJobが失敗したらすぐにパイプライン及び起動中のJobを停止します。
  • none: Jobが失敗してもほかのJobは停止しません。

GitLabのドキュメントでは以下のような例を紹介しています。この場合 job2 が失敗すると起動中だった job1 は停止し、次のStageで起動する予定だった job3 は起動せずに終了します。

stages: [stage_a, stage_b]

workflow:
  auto_cancel:
    on_job_failure: all

job1:
  stage: stage_a
  script: sleep 60

job2:
  stage: stage_a
  script:
    - sleep 30
    - exit 1

job3:
  stage: stage_b
  script:
    - sleep 30

workflow:name

workflow:name は名前の通りworkflowの名称を定義します。入力可能な値には、文字列の他CI/CD変数、およびそれらを組み合わせることも可能です。

例えば以下の場合、workflowの名称は Pipeline for branch: <コミットブランチ名> となります。

workflow:
  name: 'Pipeline for branch: $CI_COMMIT_BRANCH'

workflow:rules

rules はいつ、どのような条件でworkflow/jobを起動するか制御するキーワードです。workflow:rules はworkflow全体の起動条件を定義する機能があり、以下の入力値を設定可能です。

  • rules:if: CI/CD変数などを使い、特定のステータスやイベントに合致したときに起動します。
  • rules:changes: 指定したファイルが変更したときに起動します。
  • rules:exists: 指定したファイルが存在するときに起動します。
  • when: 条件に合致した場合に起動します。なおworkflowではalways neverのどちらかしか設定できません。
  • variables: 変数を設定します。

※参考:

techblog.ap-com.co.jp

GitLabのドキュメントでは以下のような例を紹介しています。

この場合は以下の3つの挙動を定義しています。

  • コミットタイトルが-draftで終わる場合はパイプラインを起動しません。
  • パイプラインのトリガーがMerge requestイベントの場合は起動します。
  • コミットブランチがProjectのデフォルトのブランチの場合は起動します。
workflow:
  rules:
    - if: $CI_COMMIT_TITLE =~ /-draft$/
      when: never
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

workflow:rules:variables

workflow:rules:variablesrulesvariablesを組み合わせることで、ある条件下ではこちらの値を使う、という制御ができます。条件が一致したときはパイプライン内の全てのJobで変数が使われます。また設定した変数が既に設定されている場合、workflow:rules:variablesで設定した値に上書きされます。

GitLabでは以下の例を紹介しており、ブランチ名に応じて変数を変更することができます。

variables:
  DEPLOY_VARIABLE: "default-deploy"

workflow:
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
      variables:
        DEPLOY_VARIABLE: "deploy-production"  # DEPLOY_VARIABLEを上書きする
    - if: $CI_COMMIT_REF_NAME =~ /feature/
      variables:
        IS_A_FEATURE: "true"                  # 新しい変数を設定
    - when: always                            # 上の条件にマッチしない場合でもパイプラインは起動する

job1:
  variables:
    DEPLOY_VARIABLE: "job1-default-deploy"
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
      variables:                                   # JobレベルでDEPLOY_VARIABLEを上書きする
        DEPLOY_VARIABLE: "job1-deploy-production"
    - when: on_success                             # 他の条件でもJobを起動する
  script:
    - echo "Run script with $DEPLOY_VARIABLE as an argument"
    - echo "Run another script if $IS_A_FEATURE exists"

job2:
  script:
    - echo "Run script with $DEPLOY_VARIABLE as an argument"
    - echo "Run another script if $IS_A_FEATURE exists"

workflow:rules:auto_cancel

workflow:rules:auto_cancelは前述のworkflow:auto_cancel:on_new_commit workflow:auto_cancel:on_job_failure の挙動を設定するキーワードです。これは rulesauto_cancel を組み合わせることで、ある条件の場合は auto_cancelの挙動を変更するよう設定できます。

GitLabでは以下の例を紹介しており、Protected branchへのコミットの場合はauto_cancelをオフにし、全てのJobを起動し続けるよう設定しています。

workflow:
  auto_cancel:
    on_new_commit: interruptible
    on_job_failure: all
  rules:
    - if: $CI_COMMIT_REF_PROTECTED == 'true'
      auto_cancel:
        on_new_commit: none
        on_job_failure: none
    - when: always                  # 上記以外の場合もパイプラインを起動する

test-job1:
  script: sleep 10
  interruptible: false

test-job2:
  script: sleep 10
  interruptible: true

includeとの組み合わせ

workflowincludeと組み合わせることも可能です。

※参考:

techstep.hatenablog.com

例えばGitLabではBranch-Pipelineというテンプレートを提供しており、このテンプレートは以下のように定義されています。

workflow:
  rules:
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_BRANCH

これを呼び出すことで、Projectのworkflowに対し「ブランチまたはタグをコミットしたときにパイプラインを起動する」というルールを設定できます。このようにあらかじめテンプレートを用意することで、複数のworkflowで繰り返し同じ設定を記載する手間を省略できます。