rulesでジョブの実行タイミングを指定する
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated
rulesrulesキーワードを使用して、パイプラインにジョブを含めたり、除外したりできます。
ルールは順番に評価され、最初に一致したものが適用されます。一致が見つかると、そのジョブは設定に応じて、パイプラインに含められるか除外されます。
ルールはジョブの実行前に評価されるため、ジョブスクリプトで作成されたdotenv変数をルール内で使用することはできません。
rulesの例
次の例では、ifを使用して、2つの特定のケースでのみジョブが実行されるように定義しています:
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "schedule"- パイプラインがマージリクエスト用の場合、最初の属性が一致し、ジョブは次の属性を持ってマージリクエストパイプラインに追加されます:
when: manual(手動ジョブ)allow_failure: true(手動ジョブが実行されなくてもパイプラインの実行は継続される)
- パイプラインがマージリクエスト用でない場合、最初の属性は一致せず、2番目の属性が評価されます。
- パイプラインがスケジュールされたパイプラインである場合、2番目のルールが一致し、ジョブがスケジュールされたパイプラインに追加されます。属性が定義されていないため、次の属性で追加されます:
when: on_success(デフォルト)allow_failure: false(デフォルト)
- その他すべての場合では、一致する属性がないため、ジョブは他のパイプラインには追加されません。
または、いくつかのケースでジョブを除外し、それ以外のすべてのケースで実行するようなルールセットを定義することもできます:
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: never
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- when: on_success- パイプラインがマージリクエスト用の場合、ジョブはパイプラインに追加されません。
- パイプラインがスケジュールされたパイプラインの場合、ジョブはパイプラインに追加されません。
- その他すべての場合では、
when: on_successの設定でパイプラインに追加されます。
最後のルールとしてwhen句(when: neverを除く)を使用すると、2つのパイプラインが同時に開始される可能性があります。プッシュパイプラインとマージリクエストパイプラインが、同じイベント(オープンマージリクエストのソースブランチへのプッシュ)によってトリガーされる可能性があるためです。詳細については、重複パイプラインを回避する方法をご覧ください。
スケジュールされたパイプラインでジョブを実行する
パイプラインがスケジュールされている場合にのみ実行されるようにジョブを設定できます。例:
job:on-schedule:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
script:
- make world
job:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
script:
- make buildこの例では、make worldはスケジュールされたパイプラインで実行され、make buildはブランチおよびタグパイプラインで実行されます。
ブランチが空の場合にジョブをスキップする
rules:changes:compare_toを使用して、ブランチが空の場合にジョブをスキップします。これにより、CI/CDリソースを節約できます。この設定では、ブランチをデフォルトブランチと比較し、その結果に応じて処理します:
- ブランチに変更されたファイルがない場合、ジョブは実行されません。
- ブランチに変更されたファイルがある場合、ジョブは実行されます。
デフォルトブランチがmainのプロジェクトの例を次に示します:
job:
script:
- echo "This job only runs for branches that are not empty"
rules:
- if: $CI_COMMIT_BRANCH
changes:
compare_to: 'refs/heads/main'
paths:
- '**/*'このジョブのルールは、現在のブランチにあるすべてのファイルとパス(**/*)をmainブランチと再帰的に比較します。ブランチ内のファイルが変更された場合にのみルールが一致し、ジョブが実行されます。
定義済み変数を使用した一般的なif句
rules:if句は、特にCI_PIPELINE_SOURCEなどの定義済みのCI/CD変数でよく使用されます。
次の例では、スケジュールされたパイプラインまたはプッシュパイプライン(ブランチまたはタグへのプッシュ)において、ジョブを手動ジョブとしてwhen: on_success(デフォルト)で実行します。他のパイプラインタイプにはジョブは追加されません。
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "push"次の例では、マージリクエストパイプラインおよびスケジュールされたパイプラインにおいて、ジョブをwhen: on_successジョブとして実行します。他のパイプラインタイプでは実行されません。
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_PIPELINE_SOURCE == "schedule"その他のよく使用されるif句:
if: $CI_COMMIT_TAG: タグに対する変更がプッシュされた場合。if: $CI_COMMIT_BRANCH: 任意のブランチに変更がプッシュされた場合。if: $CI_COMMIT_BRANCH == "main":mainブランチに変更がプッシュされた場合。if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH: デフォルトブランチに変更がプッシュされた場合。if: $CI_COMMIT_BRANCH =~ /regex-expression/: コミットブランチが正規表現に一致する場合。if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_TITLE =~ /Merge branch.*/: コミットブランチがデフォルトブランチであり、かつコミットメッセージのタイトルが正規表現に一致する場合。if: $CUSTOM_VARIABLE == "value1": カスタム変数CUSTOM_VARIABLEがvalue1と完全に一致する場合。
特定のパイプラインタイプでのみジョブを実行する
rulesで定義済みのCI/CD変数を使用すると、ジョブを実行するパイプラインタイプを選択できます。
次の表は、使用できる変数の一部と、各変数が制御できるパイプラインタイプを示しています:
- ブランチパイプライン: 新しいコミットやタグなど、ブランチへのGit
pushイベントで実行される。 - タグパイプライン: 新しいGitタグがブランチにプッシュされた場合にのみ実行される。
- パイプラインの実行: マージリクエストの変更(新しいコミットやマージリクエストのパイプラインタブでパイプラインを実行するを選択するなど)に応じて実行されます。
- スケジュールされたパイプライン。
| 変数 | ブランチ | タグ | マージリクエスト | スケジュール |
|---|---|---|---|---|
CI_COMMIT_BRANCH | はい | はい | ||
CI_COMMIT_TAG | はい | はい(スケジュールされたパイプラインがタグで実行されるように設定されている場合) | ||
CI_PIPELINE_SOURCE = push | はい | はい | ||
CI_PIPELINE_SOURCE = schedule | はい | |||
CI_PIPELINE_SOURCE = merge_request_event | はい | |||
CI_MERGE_REQUEST_IID | はい |
たとえば、マージリクエストパイプラインやスケジュールされたパイプラインでは実行するが、ブランチパイプラインやタグパイプラインでは実行しないようにジョブを設定する場合は、次のようになります:
job1:
script:
- echo
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_PIPELINE_SOURCE == "push"
when: neverCI_PIPELINE_SOURCE定義済み変数
CI_PIPELINE_SOURCE変数を使用して、以下のパイプラインタイプにジョブを追加するタイミングを制御します:
| 値 | 説明 |
|---|---|
api | パイプラインAPIによってトリガーされたパイプライン。 |
chat | GitLab ChatOpsコマンドを使用して作成されたパイプライン。 |
external | GitLab以外のCIサービスを使用する場合。 |
external_pull_request_event | GitHubの外部プルリクエストが作成または更新された場合。 |
merge_request_event | マージリクエストの作成または更新時に作成されたパイプライン。マージリクエストパイプライン 、マージ結果パイプライン 、マージトレインを有効にする場合、必須。 |
ondemand_dast_scan | DASTオンデマンドスキャンパイプライン。 |
ondemand_dast_validation | DASTオンデマンド検証パイプライン。 |
parent_pipeline | 親/子パイプラインによってトリガーされたパイプライン。親パイプラインからトリガーできるように、子パイプラインの設定でこのパイプラインソースを使用します。 |
pipeline | マルチプロジェクトパイプラインの場合。 |
push | ブランチやタグを含む、Gitプッシュイベントによってトリガーされたパイプライン。 |
schedule | スケジュールされたパイプライン。 |
security_orchestration_policy | スケジュールされたスキャン実行ポリシーパイプライン。 |
trigger | トリガートークンを使用して作成されたパイプライン。 |
web | GitLab 新しいパイプラインを選択して作成されたパイプラインは、プロジェクトのビルド > パイプラインセクションにあります。 |
webide | Web IDEを使用して作成されたパイプライン。 |
これらの値は、パイプラインAPIエンドポイントを使用する際にsourceパラメータとして返される値と同じです。
複合ルール
同じルール内でif、changes、existsなどのrulesキーワードをすべて使用できます。含まれるすべてのキーワードがtrueと評価された場合にのみ、そのルールはtrueと評価されます。
例:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: $VAR == "string value"
changes: # Include the job and set to when:manual if any of the follow paths match a modified file.
- Dockerfile
- docker/scripts/**/*
when: manual
allow_failure: trueDockerfileファイル、または/docker/scripts内のファイルが変更され、$VAR == "string value"場合、そのジョブは手動で実行され、失敗が許可されます。
括弧と&&および||を組み合わせて、より複雑な変数式を構築できます。
job1:
script:
- echo This rule uses parentheses.
rules:
- if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE重複パイプラインを回避する
ジョブでrulesを使用する場合、ブランチへのコミットのプッシュなど、1つのアクションが複数のパイプラインをトリガーする可能性があります。複数のタイプのパイプラインをトリガーするためのルールを明示的に設定していなくても、この問題が起こり得ます。
例:
job:
script: echo "This job creates double pipelines!"
rules:
- if: $CUSTOM_VARIABLE == "false"
when: never
- when: alwaysこのジョブは$CUSTOM_VARIABLEがfalseの場合は実行されませんが、プッシュ(ブランチ)パイプラインとマージリクエストパイプラインの両方を含む、その他both(すべての)パイプラインでは実行されます。この設定では、オープンマージリクエストのソースブランチにプッシュするたびに重複パイプラインが発生します。
重複パイプラインを回避するには、次の方法があります:
workflowを使用して、実行可能なパイプラインのタイプを指定する。非常に限られたケースでのみジョブを実行するようにルールを修正し、最後に
whenルールを配置しない:job: script: echo "This job does NOT create double pipelines!" rules: - if: $CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"
重複パイプラインを回避できるもう1つの方法は、プッシュ(ブランチ)パイプラインまたはマージリクエストパイプラインのいずれかを回避するようにジョブのルールを変更することです。ただし、workflow: rulesを使用せずに- when: alwaysルールを使用した場合も、GitLabは依然としてパイプラインの警告を表示します。
たとえば、次のスクリプトは二重パイプラインをトリガーしませんが、workflow: rulesなしでの使用は推奨されていません:
job:
script: echo "This job does NOT create double pipelines!"
rules:
- if: $CI_PIPELINE_SOURCE == "push"
when: never
- when: always重複パイプラインを防ぐworkflow:rulesを使用しない場合、プッシュパイプラインとマージリクエストパイプラインの両方を同じジョブに含めるべきではありません:
job:
script: echo "This job creates double pipelines!"
rules:
- if: $CI_PIPELINE_SOURCE == "push"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"また、同じパイプラインでonly/exceptジョブとrulesジョブを混在させないでください。YAMLエラーは発生しないかもしれませんが、only/exceptとrulesのデフォルトの動作が異なるため、トラブルシューティングが困難な問題を引き起こす可能性があります:
job-with-no-rules:
script: echo "This job runs in branch pipelines."
job-with-rules:
script: echo "This job runs in merge request pipelines."
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"オープンマージリクエストでブランチにプッシュされたすべての変更について、重複するパイプラインが実行されます。1つのブランチパイプラインが1つのジョブ(job-with-no-rules)を実行し、1つのマージリクエストパイプラインが別のジョブ(job-with-rules)を実行します。ルールなしのジョブはデフォルトでexcept: merge_requestsになるため、job-with-no-rulesはマージリクエストを除くすべてのケースで実行されます。
異なるジョブでルールを再利用する
!referenceタグを使用して、異なるジョブでルールを再利用できます。!referenceルールと、ジョブで定義されている標準のルールを組み合わせることも可能です。例:
.default_rules:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
job1:
rules:
- !reference [.default_rules, rules]
script:
- echo "This job runs for the default branch, but not schedules."
job2:
rules:
- !reference [.default_rules, rules]
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- echo "This job runs for the default branch, but not schedules."
- echo "It also runs for merge requests."CI/CD変数式
rules:ifと変数式を組み合わせて、ジョブをパイプラインに追加するタイミングを制御します。
等価演算子==および!=を使用して、変数を文字列と比較できます。単一引用符と二重引用符のどちらも有効です。変数は比較の左辺に配置する必要があります。例:
if: $VARIABLE == "some value"if: $VARIABLE != "some value"
2つの変数の値を比較できます。例:
if: $VARIABLE_1 == $VARIABLE_2if: $VARIABLE_1 != $VARIABLE_2
変数をnullキーワードと比較して、変数が定義されているかどうかを確認できます。例:
if: $VARIABLE == nullif: $VARIABLE != null
変数が定義されているが空であるかどうかを確認できます。例:
if: $VARIABLE == ""if: $VARIABLE != ""
式で変数名のみを使用して、その変数が定義されており、かつ空でないかどうかを確認できます。例:
if: $VARIABLE
変数式でCI/CD入力を使用することもできます。
変数を正規表現と比較する
=~および!~演算子を使用して、変数値を正規表現とマッチングできます。
式は、次の場合にtrueとして評価されます:
=~を使用して一致が見つかった場合。!~を使用して一致が見つからなかった場合。
例:
if: $VARIABLE =~ /^content.*/if: $VARIABLE !~ /^content.*/
追加の注意点:
/./などの1文字の正規表現はサポートされておらず、invalid expression syntax(無効な式構文)エラーが発生します。- デフォルトでは、パターンマッチングは大文字と小文字を区別します。大文字と小文字を区別しないパターンにするには、
iフラグ修飾子を使用します。例:/pattern/i。 - 正規表現でマッチングできるのは、タグ名またはブランチ名のみです。リポジトリパスが指定された場合、それは常にリテラルとして一致します。
- パターン全体を
/で囲む必要があります。たとえば、issue-/.*/を使用してissue-で始まるすべてのタグ名またはブランチ名に一致させることはできませんが、/issue-.*/は使用可能です。 @記号は、refのリポジトリパスの先頭を示します。正規表現で@文字を含むref名に一致させるには、16進文字コード\x40を使用する必要があります。- 正規表現がタグ名またはブランチ名の部分文字列のみに一致するのを防ぐには、アンカー
^と$を使用します。たとえば、/^issue-.*$/は/^issue-/と同等ですが、/issue/だけではsevere-issuesという名前のブランチにも一致してしまいます。 - 正規表現を使用した変数パターンマッチングでは、RE2正規表現構文を使用します。
正規表現を変数に保存する
=~および!~式の右辺にある変数は、正規表現として評価されます。正規表現はスラッシュ(/)で囲む必要があります。例:
variables:
pattern: '/^ab.*/'
regex-job1:
variables:
teststring: 'abcde'
script: echo "This job will run, because 'abcde' matches the /^ab.*/ pattern."
rules:
- if: '$teststring =~ $pattern'
regex-job2:
variables:
teststring: 'fghij'
script: echo "This job will not run, because 'fghi' does not match the /^ab.*/ pattern."
rules:
- if: '$teststring =~ $pattern'正規表現内の変数は解決されません。例:
variables:
string1: 'regex-job1'
string2: 'regex-job2'
pattern: '/$string2/'
regex-job1:
script: echo "This job will NOT run, because the 'string1' variable inside the regex pattern is not expanded."
rules:
- if: '$CI_JOB_NAME =~ /$string1/'
regex-job2:
script: echo "This job will NOT run, because the 'string2' variable inside the 'pattern' variable is not expanded."
rules:
- if: '$CI_JOB_NAME =~ $pattern'変数式を結合する
複数の式を&&(and)または||(or)を使用して結合できます。次に例を示します:
$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3
括弧を使用して式をグループ化できます。括弧は&&や||よりも優先されるため、括弧内の式が先に評価され、その結果が式の残りの部分に使用されます。演算子の優先順位では、&&``||の前に評価されます。
括弧をネストして複雑な条件式を作成することもでき、最も内側の括弧内の式から順に評価されます。例:
($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)
トラブルシューティング
=~を使用した正規表現マッチングでの予期しない動作
=~演算子を使用する場合は、比較の右辺に常に有効な正規表現が含まれていることを確認してください。
比較の右辺が/文字で囲まれた有効な正規表現でない場合、式は予期しない方法で評価されます。その場合、比較では、左辺が右辺の部分文字列かどうかがチェックされます。たとえば、"23" =~ "1234"はtrueと評価されますが、"23" =~ /1234/はfalseと評価されます。これらの結果は正反対なので注意が必要です。
このような挙動に依存したパイプライン設定は避けてください。