皆様こんにちは。SEの小池と申します。
今までのブログでも時々、GitLabでごく簡単なCI/CDパイプラインを作るような記事を書いてまいりましたが、正直、まだまだ筆者はCI/CDパイプラインを便利に使いこなせていないと思う今日この頃です。
ブログを書いている以上、ある程度キーワードの使い方を知っておきたい・・・そんな筆者の欲望を満たすため、これからは時々、筆者が気になったCI/CDパイプラインのキーワードをピックアップして、それをひたすら解説するだけの記事を書いてまいります。
今回はキーワード workflow の概要と具体例を用いた説明をします。
- 本記事の対象の方
- 今回のブログのゴール
- このブログをお読みいただくにあたっての事前ご連絡事項
- キーワードworkflowの概要
- workflow:rules:とif:を使った変数による判定
- workflow:rules:とchanges:を使ったファイル変更の有無による判定
- workflow:rules:とexists:を使った変数による判定
- workflow:rules:とwhen:を使った否定の条件
- workflow:rules:とvariables:を使った変数の設定・オーバーライド
- 最後に
本記事の対象の方
- GitLabのCI/CDパイプライン全体を実行する/しないの条件設定について情報収集中の方。
- GitLabのパイプラインのキーワードを勉強したいが、何から手を付けていいか迷っていらっしゃる方。
今回のブログのゴール
このブログのゴールはこちらです。
- GitLabのCI/CDパイプラインのキーワード workflow の概要を把握する。
このブログをお読みいただくにあたっての事前ご連絡事項
- 本記事はSelf-Managed版 GitLab Community Edition 15.4.1 における仕様をベースに記載しております。それ以外のエディションやバージョンではこの記事に記載の通りではない可能性がございます。
- 本記事はGitやCI/CDに関する知識ゼロのSEによるなんちゃって記事です。GitLabのディープな使用法についてはGitLabの公式オンラインドキュメント (こちら) をご参照ください。
キーワードworkflow
の概要
workflow
は、そのパイプラインを実行 (作成) するか、しないかの条件を設定するキーワードです。
このキーワードに書いた条件に一致する状況であれば、そのパイプラインは実行 (作成) されます。
逆に、このキーワードに書いた条件に一致しない状況であれば、このパイプラインは実行 (作成) されません。
このキーワードはグローバルキーワードで、stages:
等と同様のレベルで設定します。
このキーワードはジョブレベルには設定できません。
また2022/10/12現在、キーワードworkflow
に設定できる下位キーワードはrules:
のみなので、必然的にworkflow: rules:
で使用することとなります。
参考 : '.gitlab-ci.yml' keyword reference - workflow | GitLab
workflow:rules:
とif:
を使った変数による判定
キーワードworkflow
で条件をworkflow:rules:
とif:
を使って記載すると、 if: に指定した判定式が真 (True) の場合にのみ、CI/CDパイプラインを作成し実行するという条件を指定することができます。
下の例の場合、6行目に- if: $AAA == "aaa"
とあります。つまりこのパイプラインは、変数AAAの値がaaaであった場合のみ作成+実行する設定なっています。
stages: - first workflow: rules: - if: $AAA == "aaa" job1: stage: first script: - echo "これは1つ目のジョブです。"
このworkflow:rules: - if:
を使う場合の注意点として、 if: に指定できる条件は変数の判定のみです。
極端な例でいうと、以下のようにif:
を指定することはできません。(文字列同士の比較なので。)
# ############## 【注意】これはNG例です!!!############## ~略~ workflow: rules: - if: "bbb" == "aaa" ~略~
workflow:rules:
の- if:
で使える変数は主に以下のものがあります。
- キーワード
variables
で定義した変数。 - プロジェクトの設定から事前に設定した変数。
- GitLabの内部的に事前に定義された変数
参考 : '.gitlab-ci.yml' keyword reference - rules: if | GitLab
具体例:コミット先が特定のブランチ名の場合のみ実行する
コミット先ブランチ名がfeature-
で始まる場合のみ実行する条件設定を例に挙げます。
stages: - first workflow: rules: - if: $CI_COMMIT_BRANCH =~ /^feature-.*/ job1: stage: first script: - echo "これは1つ目のジョブです。"
6行目の変数 CI_COMMIT_BRANCH
はGitLabが内部的に自動で設定している変数で、コミット先ブランチ名が自動で代入されます。
次に、5, 6行目でブランチ名がfeature-
で始まる条件を正規表現で指定しています。正規表現を使った判定を行う場合は比較演算子を=~
にし、比較する値はスラッシュ/
で囲みます。これにより、正規表現の条件を指定できます。あとは正規表現で「feature- で始まる」(^feature-.*
) を設定します。
参考 : Choose when to run jobs | GitLab, '.gitlab-ci.yml' keyword reference - workflow: rules | GitLab
workflow:rules:
とchanges:
を使ったファイル変更の有無による判定
キーワードworkflow
で条件をworkflow:rules:
とchanges:
を使って記載すると、 changes: に指定したファイルに変更があった場合にのみ、CI/CDパイプラインを作成し実行するという条件を指定することができます。
下は例では、コミット先ブランチ名がfeature-
で始まり、且つ、ファイルDockerfile
に変更があったときのみCI/CDパイプラインを作成し実行します。
stages: - first workflow: rules: - if: $CI_COMMIT_BRANCH =~ /^feature-.*/ changes: - Dockerfile job1: stage: first script: - echo "これは1つ目のジョブです。"
workflow:rules:
とchanges:
を使う場合の注意点を述べます。
まず、必ずキーワード if: が必要になります。
次に、changes:
で判定する「変更の有無」とは、git pushイベントの有無を意味します。そのため、changes:
はブランチパイプラインや、マージリクエストパイプラインで使用されるように設定してください。それ以外のタグパイプライン、スケジュールパイプライン、手動パイプラインの場合はgit pushイベントが関連づけられていないため、changes:
が常に真 (True) で評価されてしまいます。
最後に、changes:
で特定のファイルをパス指定する場合、そのパスは root からの相対パスで書く必要があります。
参考 : '.gitlab-ci.yml' keyword reference - rules: changes | GitLab
NGな例を挙げます。
下の.gitlab-ci.yml
では、workflow:rules:
のif:
が指定されていないため、GitLab的には構文がNGとなりCI/CDパイプラインは実行されません。
また、ファイルのパス指定が絶対パスになっているのもNGです。実は絶対パスにしてもGitLabの構文チェック上はエラーが出ませんが、そのファイルに変更があっても判定が偽 (False) 、つまり "変更なし" と判断されます。
# ############## 【注意】これはNG例です!!!############## ~略~ workflow: rules: - changes: /docs/install/install.md ~略~
具体例:特定フォルダの特定拡張子のファイルに変更があった場合のみ実行する
workflow:rules:
のchanges:
を使い、以下の条件を両方満たす場合にのみCI/CDパイプラインを作成・実行する設定例を挙げます。
- コミット先ブランチ名が
feature-
で始まる場合。 - フォルダ
/docs/install/
で拡張子が.md
のファイルに変更があった場合。
stages: - first workflow: rules: - if: $CI_COMMIT_BRANCH =~ /^feature-.*/ changes: - docs/install/*.md job1: stage: first script: - echo "これは1つ目のジョブです。"
上の7, 8行目のchanges:
で、フォルダ/docs/install/
で拡張子が.md
のファイルに変更があった場合のみ実行する条件を指定しています。
また、先述の通りworkflow:rules:
のchanges:
を使うには、workflow:rules:
のif:
を指定することが必須です。ですので、6行目にこちらで紹介した例を流用し、コミット先ブランチがfeature-
から始まる場合に限定しました。
workflow:rules:
とexists:
を使った変数による判定
キーワードworkflow
で条件をworkflow:rules:
とexists:
を使って記載すると、 exists: に指定したファイルがリポジトリに存在する場合のみ、CI/CDパイプラインを作成し実行するという条件を指定することができます。
また、このキーワードではglobパターンが使用可能なので、ワイルドカード等も使用可能です。
下の例では、ファイル/docs/install.md
がリポジトリに存在する時のみCI/CDパイプラインを作成し実行します。
stages: - first workflow: rules: - exists: - docs/install.md job1: stage: first script: - echo "これは1つ目のジョブです。"
workflow:rules:
とexists:
を使って条件を指定する場合の注意点として、exists:
でパスを指定する場合は相対パスで記載してください。
NGな例を挙げます。
ファイル/docs/install/install.md
がリポジトリに存在する時のみCI/CDパイプラインを作成し実行したい場合、以下の yml ファイルのように絶対パス/docs/install/install.md
でファイル名を指定すると、たとえリポジトリにそのファイルがあったとしても、このパイプラインは作成・実行されません。
# ############## 【注意】これはNG例です!!!############## ~略~ workflow: rules: - exists: - /docs/install/install.md ~略~
参考 : '.gitlab-ci.yml' keyword reference - rules: exists | GitLab
具体例:特定ファイルが存在しないときのみ実行する
workflow:rules:
のexists:
を使い、ファイル/docs/install.md
が存在しない場合にのみCI/CDパイプラインを作成・実行する設定例を挙げます。
stages: - first workflow: rules: - exists: - docs/install.md when: never - when: always job1: stage: first script: - echo "これは1つ目のジョブです。"
実は、「特定のファイルがない場合」はexists:
単体で設定することができず、いくつかのキーワードとの併用により設定することになります。上の例は下記URLの投稿を参考にし、when:
を使って制御しています。(when:
については後の章で述べます。)
6, 7行目で存在確認をするファイルを相対パスで指定しています。
8行目でハイフンなしでwhen: never
を設定することで、「docs/install.md (相対パス) が存在する場合、このCI/CDパイプラインは作成・実行しない」という条件にしています。
9行目のwhen: always
は「常時実行する」という条件ですが、これは6 ~ 8行目に書いた条件に合致しなかった場合に評価されるため、結果的にこのworkflow:
に設定された条件は「ファイル/docs/install.md
が存在しない場合にのみCI/CDパイプラインを作成・実行する」となっています。
参考 : Provide example how to use rules:exists with not (#244932) · Issues · GitLab.org / GitLab · GitLab
workflow:rules:
とwhen:
を使った否定の条件
キーワードworkflow
で条件をworkflow:rules:
とwhen:
を使って記載すると、そのCI/CDパイプラインを常時作成するか、常時作成しないかを設定できます。
when:
は他の rules: の条件と併用することで、否定の条件も簡単に作成することができます。
下の例では、リポジトリに拡張子.png
のファイルが存在する場合はCI/CDパイプラインを作成・実行せず、それ以外の場合はCI/CDパイプラインを作成・実行します。
stages: - first workflow: rules: - exists: - "**.png" when: never - when: always job1: stage: first script: - echo "これは1つ目のジョブです。"
workflow:rules:
とwhen:
を使って条件を指定する場合の注意点として、設定できる値は always か never のどちらかのみです。
(when:
はworkflow:
の中だけでなくジョブの中でも設定でき、その場合は always や never 以外にも設定可能な値があるのですが、workflow:rules:
内で使用する場合は always か never しか指定できません。)
例えばCI/CDパイプラインの自動作成・実行は一切させずに、GitLabの画面から手動実行したい場合。
以下のようにwhen: manual
を設定するとCI/CDパイプラインの構文エラーとなります。
これも見た感じではいけそうなのですが、GitLab様的にはNGな構文です・・・。
# ############## 【注意】これはNG例です!!!############## ~略~ workflow: rules: - when: manual ~略~
具体例:CI/CDパイプラインを自動作成・実行せずGitLabの画面から手動実行する場合
workflow:rules:
のexists:
を使い、CI/CDパイプラインの自動作成・実行はさせずに、GitLabの画面から手動実行する場合の設定例を挙げます。
stages: - first workflow: rules: - if: $CI_PIPELINE_SOURCE == "web" when: always - when: never job1: stage: first script: - echo "これは1つ目のジョブです。"
6行目の変数CI_PIPELINE_SOURCE
はGitLabの製品で定義済みの変数で、どうやってCI/CDパイプラインがトリガーされたかが自動で代入されます。今回設定しているweb
はGitLabの画面からCI/CDパイプラインの実行ボタンをクリックした場合に代入される値です。したがって、この行のif:
ではCI/CDパイプラインがGitLabの画面から実行されたか否かの判定を行っています。
7行目ではハイフン-
なしでwhen: always
を設定しているので、直前のif:
で指定した「CI/CDパイプラインがGitLabの画面から実行されたか」の判定が真 (True) の場合は、このCI/CDパイプラインを常時実行するという条件設定となっています。
8行目のwhen:
は6行目のif:
が偽 (False) の場合のみ評価されます。設定されている内容はwhen: never
、つまり常時実行しないという設定となります。
結果的にこの.gitlab-ci.yml
はGitLabの画面から手動でCI/CDパイプラインを実行するボタンをクリックした場合のみ作成・実行し、それ以外の場合は作成・実行しないという条件となります。
参考 : Predefined variables reference | GitLab, GitLab run pipeline only manually and not automatically - Stack Overflow
workflow:rules:
とvariables:
を使った変数の設定・オーバーライド
キーワードworkflow
で条件をworkflow:rules:
とvariables:
を使って記載すると、特定の条件を満たす場合にのみ使用する変数を設定することができます。
variables: 内で定義した変数は、そのCI/CDパイプライン全体で使用可能です。
また、先にグローバルレベルのvariables:
で同じ変数を宣言していた場合、workflow: rules: variables:
で設定された値が、グローバルレベルで設定された値オーバーライドします。
以下の例の場合、変数TEST_VARIABLE
を、グローバルレベル (4, 5行目) と workflow: rules: variables:
内 (10, 11行目) の2か所で定義しています。
このCI/CDパイプライン実行時に9行目のif:
の条件を満たす場合、変数TEST_VARIABLE
の値が11行目でオーバーライドされるので、17行目のecho
で出力される値は neko です。
逆に、このCI/CDパイプライン実行時に9行目のif:
の条件を満たさない場合、17行目のecho
で出力される値はグローバルレベル (4, 5行目) で設定された inu です。
stages: - first variables: TEST_VARIABLE: "inu" workflow: rules: - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH variables: TEST_VARIABLE: "neko" - when: always job1: stage: first script: - echo $TEST_VARIABLE
参考 : '.gitlab-ci.yml' keyword reference - workflow: rules:variables | GitLab
具体例:特定の方法でトリガーした時だけ変数の値をオーバーライドする場合
workflow:rules:
のvariables:
を使い、GitLabの画面から手動実行した場合と、スケジュールで実行した場合のみ、グローバルで宣言済みの変数をオーバーライドする例を挙げます。
前に出したymlの例とあまり変わらないです…いいのが思いつかず、すみません。
stages: - first variables: TEST_VARIABLE: "dog" workflow: rules: # Gitlabの画面から手動実行した場合 - if: $CI_PIPELINE_SOURCE == "web" variables: TEST_VARIABLE: "cat" # スケジュール実行した場合 - if: $CI_PIPELINE_SOURCE == "schedule" variables: TEST_VARIABLE: "turtle" # 上記以外 - when: always job1: stage: first script: - echo My pet is a $TEST_VARIABLE.
4,5 行目でグローバルレベルで変数TEST_VARIABLE
を dog に設定します。
10行目でGitLabで定義済みの変数CI_PIPELINE_SOURCE
を使い、CI/CDパイプラインがGitLabの画面からトリガーされたのかを判定し、真 (true) の場合は11,12行目で変数TEST_VARIABLE
の値を cat にオーバーライドします。
14行目でGitLabで定義済みの変数CI_PIPELINE_SOURCE
を使い、CI/CDパイプラインがスケジュール実行されたのかを判定し、真 (true) の場合は15, 16行目で変数TEST_VARIABLE
の値を turtle にオーバーライドします。
18行目は、このCI/CDパイプラインがGitLabの画面 及び スケジュール以外から実行された場合にのみ評価されます。設定された条件はwhen: always
のみであることから、変数のオーバーライドはしません。
結果として23行目のecho
では、GitLabの画面からトリガーした場合は cat、スケジュール実行された場合は turtle、それ以外の場合は dog で表示されます。
参考 : '.gitlab-ci.yml' keyword reference - workflow: rules:variables | GitLab, Predefined variables reference | GitLab
最後に
この度はGitもCI/CDもよくわかっていないど素人SEによるGitLab検証ブログをお読みいただき、誠にありがとうございます。
このブログの目標は以下のとおりでしたが、皆さまはいかがでしたでしょうか。
- GitLabのCI/CDパイプラインのキーワード workflow の概要を把握する。
GitLabと言えばCI/CDは超便利なメイン機能です。
しかしそのキーワードが多すぎて逆に何ができるのか、調べるのが大変・・・という状況になっている方もいらっしゃるかもしれません。というか筆者がそれです。
せめて基本的なキーワードだけでも、どういったものがあるのか把握したいという筆者の勝手な希望により、今後も時々、主要なキーワードをピックアップして使い方を日本語で説明していこうかと思います。
この記事がGitLabを触り始めた方の一助となれば幸いにございます。
GitLabに関するお問い合わせは、以下のフォームからお願い致します。
GitLab製品 お問い合わせ
GitLab操作デモ動画 (基本編) を作ってみました。(音声の録音は自宅でiPhoneのボイスメモ使うという超低クオリティですが…。)
つたない内容ではありますが、ご興味がおありでしたら是非ご視聴いただければと存じます。