ジョブを実行するタイミングの選択

新しいパイプラインが開始されると、GitLabはパイプラインの設定をチェックし、そのパイプラインで実行すべきジョブを決定します。変数の状態やパイプラインの種類などに応じて実行するジョブを設定することができます。

特定のパイプラインにジョブを含めるか除外するかを設定するには、rules を使います。

needs を使用して、依存する先のジョブが実行を終了したらすぐに実行するようにジョブを設定します。

ジョブが実行されるタイミングはrules

GitLab 12.3 で導入されました

rules を使ってパイプラインにジョブを含めたり除外したりできます。

ルールは最初にマッチするまで順番に評価されます。一致するジョブが見つかると、設定に応じてそのジョブはパイプラインに含まれるか除外されます。詳細はrules リファレンスを参照してください。

今後のキーワードの改良については、誰でも提案や要望を追加できるrules](https://gitlab.com/groups/gitlab-org/-/epics/2783) の改良のための[エピックで議論されています。

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により、ジョブはパイプラインに追加されます。
caution
when 節を最終ルールとして使用する場合 (when: never を含まない)、2 つのパイプラインを同時に開始することができます。プッシュパイプラインとマージリクエストパイプラインの両方が、同じイベント(オープンなマージリクエストのソースブランチへのプッシュ)によってトリガーされる可能性があります。詳細はパイプラインの重複を防ぐ方法を参照してください。

スケジュールされたパイプラインのジョブの実行

パイプラインがスケジュールされたときにのみ実行されるジョブを設定するには、rules キーワードを使用します。

この例では、make world はスケジュールされたパイプラインで実行され、make build はブランチおよびタグパイプラインで実行されます:

job:on-schedule:
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
  script:
    - make world

job:
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
  script:
    - 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 と比較します。このルールはブランチ内のファイルに変更があった場合にのみマッチし、ジョブが実行されます。

複雑なルール

ifchangesexists のように、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: true

Dockerfile ファイルまたは/docker/scripts 内のファイルが変更され、 $VAR == “文字列値” の場合、ジョブは手動で実行され、失敗してもかまいません。

&&||括弧を使うと、より複雑な変数式を構築できます。GitLab 13.3 で導入されました

job1:
  script:
    - echo This rule uses parentheses.
  rules:
    - if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
caution
GitLab 13.3以前では、](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) と&& の両方を使うルールは予期しないオペレーション順序で評価されることがありました。

パイプラインの重複を避ける

ジョブがrules を使用している場合、ブランチへのコミットのプッシュのような単一のアクションが複数のパイプラインをトリガーする可能性があります。複数のタイプのパイプラインのルールを明示的に設定しなくても、誤ってトリガーしてしまうことはありません。

パイプラインの重複を引き起こす可能性のある設定によっては、パイプラインの警告が表示されます。GitLab 13.3 で導入されました

使用例:

job:
  script: echo "This job creates double pipelines!"
  rules:
    - if: $CUSTOM_VARIABLE == "false"
      when: never
    - when: always

このジョブは$CUSTOM_VARIABLE が false のときは実行されませんが、プッシュ (ブランチ) パイプラインとマージリクエストパイプラインの両方を含む、他のすべてのパイプラインでは実行れます。この設定では、マージリクエストのソースブランチにプッシュするたびにパイプラインが重複します。

パイプラインの重複を避けるには、次のようにします:

  • workflow を使用して、実行できるパイプラインのタイプを指定します。
  • 非常に特殊な場合にのみジョブを実行するようにルールを書き直し、最後のwhen ルールは避けてください:

     job:
       script: echo "This job does NOT create double pipelines!"
       rules:
         - if: $CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"
    

プッシュ(ブランチ)パイプラインかマージリクエストパイプラインのどちらかを避けるようにジョブルールを変更することで、パイプラインの重複を避けることもできます。しかし、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/exceptrules の異なるデフォルトのふるまいはトラブルシューティングが難しいイシューを引き起こす可能性があります:

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つのジョブ (job-with-no-rules) を実行し、マージリクエストパイプラインはもう1つのジョブ (job-with-rules) を実行します。ルールのないジョブのデフォルトはexcept: merge_requestsで、マージリクエスト以外のすべてのケースでjob-with-no-rules が実行されます。

の一般的なif 節は次のとおりです。rules

only/except キーワード と同様の動作については、$CI_PIPELINE_SOURCE 変数の値をチェックできます:

説明
api パイプラインAPIで起動されたパイプラインの場合。
chat GitLab ChatOps コマンドを使用して作成したパイプラインの場合。
externalGitLab以外のCIサービスを利用する場合。
external_pull_request_eventGitHub 上の外部プルリクエストが作成または更新されたとき。 詳細は外部プルリクエスト用のパイプラインを参照してください。
merge_request_eventマージリクエストが作成または更新されたときに作成されるパイプライン用。 マージリクエストパイプラインマージ結果パイプラインマージトレインを有効にするために必要です。
parent_pipeline rules を持つ親/子パイプラインによってトリガされるパイプライン用。親パイプラインによってトリガされるように、子パイプライン設定でこのパイプラインソースを使用します。
pipeline CI_JOB_TOKEN](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-by-using-the-api)またはtrigger キーワードを使用した API を使用して[で作成されたマルチプロジェクトパイプラインの場合。
pushブランチやタグを含む、git push イベントをトリガーとするパイプラインの場合。
schedule スケジュールパイプラインの場合。
trigger トリガートークンを使用して作成されたパイプラインの場合。
webGitLab UI のパイプライン 実行ボタンで作成したパイプラインの場合。
webide WebIDEを使用して作成したパイプラインの場合。

以下の例では、ジョブを手動ジョブとしてスケジュールパイプラインまたはプッシュパイプライン(ブランチまたはタグへ)で、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.*/:コミットブランチがデフォルトブランチで、コミットメッセージタイトルが正規表現にマッチする場合。たとえば、マージコミットのデフォルトコミットメッセージはMerge branch で始まります。
  • if: $CUSTOM_VARIABLE !~ /regex-expression/カスタム変数CUSTOM_VARIABLE が正規表現にマッチしない場合。
  • if: $CUSTOM_VARIABLE == "value1":カスタム変数のCUSTOM_VARIABLEvalue1と完全に一致する場合。

変数rules:changes

ジョブをパイプラインに追加するタイミングを決定するために、rules:changes 式で CI/CD 変数を使用できます:

docker build:
  variables:
    DOCKERFILES_DIR: 'path/to/files'
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - changes:
        - $DOCKERFILES_DIR/*

変数とパスの両方に$ 文字を使用できます。例えば、$DOCKERFILES_DIR 変数が存在する場合、その値が使用されます。存在しない場合、$ はパスの一部として解釈されます。

異なるジョブでのルールの再利用

GitLab 14.3で導入されました

異なるジョブでルールを再利用するには!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."

ジョブの実行時にonlyexcept

note
only およびexcept は積極的に開発されていません。 rulesは、パイプラインにジョブを追加するタイミングを制御するのに適したキーワードです。

ジョブをパイプラインに追加するタイミングを制御するには、onlyexcept を使用できます。

  • only を使用して、ジョブが実行されるタイミングを定義します。
  • ジョブが実行されないタイミングを定義するには、except を使用します。

only:refs /except:refs の例

only またはexcept を使用できます:

  • 特定のキーワード。完全なリストはonly/except 構文リファレンス を参照してください。
  • ブランチ名。特定のキーワードと全く同じブランチ名は避けてください。例えば、tags (タグパイプライン) tags というキーワードで実行するように設定されたジョブは、tags.NET という名前のブランチでも実行さ tagsれます。
  • 正規表現パターンでブランチ名の範囲を指定します。

以下の例ではrefs を省略していますが、これはonly またはexceptrefs なしで使用した場合、only:refs /except/refs と同じになるためです。

使用例:

job:
  # use special keywords
  only:
    - tags
    - triggers
    - schedules

この例では、job

親リポジトリに対してのみジョブを実行し、フォークに対しては実行しないようにします:

job:
  only:
    - branches@gitlab-org/gitlab
  except:
    - main@gitlab-org/gitlab
    - /^release/.*$/@gitlab-org/gitlab

この例では、mainrelease/ で始まるブランチを除く、gitlab-org/gitlab 上のすべてのブランチに対してjob を実行します。

only: variables /except: variables の例

except:variables を使って、コミットメッセージに基づいてジョブを除外することができます:

end-to-end:
  script: rake test:end-to-end
  except:
    variables:
      - $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/

&&||括弧を使うと、より複雑な変数式を構築できます:

job1:
  script:
    - echo This rule uses parentheses.
  only:
    variables:
      - ($CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE

複数のエントリがonly:variables で指定されている場合、そのうちの少なくとも 1 つがtrue と評価されたときにジョブが実行されます。複数の条件を同時に満たす必要がある場合は、1 つのエントリで&& を使用できます。

only:changes /except:changes の例

リポジトリのルートディレクトリにある.md という拡張子を持つファイルに変更が検出された場合、ジョブをスキップすることができます:

build:
  script: npm run build
  except:
    changes:
      - "*.md"

複数のファイルを変更しても、.md で終わるファイルが 1 つだけの場合、build ジョブはスキップされます。ジョブはどのファイルに対しても実行されません。

changes を使用する設定によっては、ジョブやパイプラインが予期せず実行されることがあります。

マージリクエストパイプラインでonly:changes を使用してください。

マージリクエストパイプラインでは、マージリクエストで変更されたファイルに基づいて作成されるジョブを定義することができます。

GitLabがソースブランチの正しいベースSHAを見つけられるように、このキーワードをonly: [merge_requests] 。ファイルの差分はそれ以降のコミットから正しく計算され、マージリクエストのすべての変更はパイプラインで正しくテストされます。

使用例:

docker build service one:
  script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
  only:
    refs:
      - merge_requests
    changes:
      - Dockerfile
      - service-one/**/*

このシナリオでは、マージリクエストがservice-one ディレクトリかDockerfile のファイルを変更した場合、GitLab はdocker build service one ジョブを作成します。

使用例:

docker build service one:
  script: docker build -t my-service-one-image:$CI_COMMIT_REF_SLUG .
  only:
    changes:
      - Dockerfile
      - service-one/**/*

この例では、service-one/**/* のファイルが変更されたため、パイプラインが失敗する可能性があります。

service-one/**/* に変更はありませんが、.NET ファイルに変更がある場合、後のコミットはDockerfile パスする Dockerfileことができます。Dockerfile ジョブがテストするのは、. Dockerfile

GitLab はパスした最新のパイプラインをチェックします。マージリクエストがマージ可能であれば、以前のパイプラインが修正されていない変更のために失敗したことは問題ではありません。

この設定を使う場合は、最新のパイプラインが以前のパイプラインの失敗を適切に修正していることを確認してください。

複数のキーワードをonly またはexcept

複数のキーワードをonly またはexcept で使用すると、キーワードは1つの結合式として評価されます。つまり

  • only は、すべてのキーが少なくとも 1 つの条件に一致する場合、ジョブを含めます。
  • except は、一致する条件が1つでもあるキーがあれば、そのジョブを除外します。

only を使用すると、個々のキーはAND で論理的に結合されます。 以下の条件が真の場合、ジョブはパイプラインに追加されます:

  • (any listed refs are true) AND (any listed variables are true) AND (any listed changes are true) AND (any chosen Kubernetes status matches)

以下の例では、test のジョブは、以下のすべてが真の場合にのみ作成されます:

  • パイプラインがスケジュールされて いるか、 main のために実行されています。
  • variables キーワードがマッチいている。
  • プロジェクトのkubernetes サービスがアクティビティである。
test:
  script: npm run test
  only:
    refs:
      - main
      - schedules
    variables:
      - $CI_COMMIT_MESSAGE =~ /run-end-to-end-tests/
    kubernetes: active

except を使用すると、個々のキーはOR で論理的に結合されます。 以下の場合、ジョブは追加されません

  • (any listed refs are true) OR (any listed variables are true) OR (any listed changes are true) OR (a chosen Kubernetes status matches)

以下の例では、test のジョブは、以下のいずれかが真の場合は作成されません

  • パイプラインはmain ブランチで実行されます。
  • リポジトリのルートディレクトリにあるREADME.md ファイルが変更されている。
test:
  script: npm run test
  except:
    refs:
      - main
    changes:
      - "README.md"

手動で実行するジョブの作成

ユーザーがジョブを開始しない限り、ジョブが実行されないようにすることができます。これは手動ジョブと呼ばれます。本番環境へのデプロイなどのために手動ジョブを使いたいと思うかもしれません。

ジョブを手動として指定するには、.gitlab-ci.yml ファイルのジョブにwhen: manual を追加します。

デフォルトでは、手動ジョブはパイプラインの開始時にスキップされたものとして表示されます。

保護されたブランチを使用することで、手動デプロイが権限のないユーザーによって実行されないように、より厳密に保護することができます。

手動ジョブの種類

手動ジョブにはオプションとブロックがあります。

オプションの手動ジョブの場合:

  • allow_failuretrue で、when: manual があり、rulesがないジョブ、またはrulesの内部でwhen: manual が定義されているジョブのデフォルト設定です。
  • ステータスはパイプライン全体のステータスに貢献しません。パイプラインは、手動ジョブがすべて失敗しても成功することがあります。

手動ジョブのブロックでは:

  • allow_failure false これは、rulesの内部でwhen: manual が定義されているジョブのデフォルト設定です。
  • パイプラインはジョブが定義されたステージで停止します。パイプラインの実行を継続させるには、手動ジョブを実行してください。
  • を持つプロジェクトのマージリクエストは成功しなければなりません。 パイプラインは成功する必要があります。ブロックされたパイプラインではマージできません。
  • パイプラインはブロックされたステータスを表示します。

strategy: depend を使用してトリガされたパイプラインで手動ジョブを使用する場合、手動ジョブのタイプはパイプラインの実行中にトリガジョブのステータスに影響します。

手動ジョブの実行

手動ジョブを実行するには、割り当てられたブランチにマージする権限が必要です:

  1. パイプライン、ジョブ、環境、またはデプロイメントビューに移動します。
  2. 手動ジョブの横で、再生({play}) を選択します。

手動ジョブを実行する際に、カスタムCI/CD変数を追加することもできます。

手動ジョブの保護

保護された環境を使用して、手動ジョブの実行を許可されたユーザーのリストを定義します。保護された環境に関連付けられたユーザーのみに手動ジョブのトリガーを許可することができます:

  • 環境にデプロイできるユーザーをより正確に制限します。
  • 承認者が「承認」するまでパイプラインをブロックします。

手動ジョブを保護するには:

  1. ジョブにenvironment を追加します。使用例:

    deploy_prod:
      stage: deploy
      script:
        - echo "Deploy to production server"
      environment:
        name: production
        url: https://example.com
      when: manual
      rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    
  2. 保護された環境の設定で、環境 ( この例ではproduction ) を選択し、手動ジョブをトリガーする権限を持つユーザー、ロール、グループをAllowed to Deployリストに追加します。このリストに含まれる人だけがこの手動ジョブをトリガーすることができ、GitLab管理者は常に保護された環境を使用することができます。

手動ジョブをブロックする保護された環境を使用して、後のパイプラインステージを承認することを許可されたユーザーのリストを持つことができます。allow_failure: false を保護された手動ジョブに追加すると、パイプラインの次のステージは、手動ジョブが作成者によってトリガーされた後にのみ実行されます。

遅延後のジョブの実行

GitLab 11.4で導入されました

待ち時間の後にスクリプトを実行する場合や、ジョブがすぐにpending の状態になるのを避けたい場合はwhen: delayed を使ってください。

start_in キーワードで start_in期間を設定できます。start_in の値は start_in、単位が指定されていない限り、経過時間を秒単位で表します。最小値は1秒で、最大値は1週間です。有効な値の例を以下に示します:

  • '5' (単位を指定しない値はシングルクォートで囲む必要があります)
  • 5 seconds
  • 30 minutes
  • 1 day
  • 1 week

ステージに遅延ジョブが含まれる場合、遅延ジョブが終了するまでパイプラインは進行しません。このキーワードを使用して、異なるステージ間に遅延を挿入できます。

遅延ジョブのタイマーは、前のステージが完了した直後に開始します。他のタイプのジョブ同様、遅延ジョブのタイマーは前のステージが通過しない限り開始しません。

次の例では、timed rollout 10% という名前のジョブを作成し、前のステージが完了した30分後に実行します:

timed rollout 10%:
  stage: deploy
  script: echo 'Rolling out 10% ...'
  when: delayed
  start_in: 30 minutes
  environment: production

遅延ジョブのアクティブタイマーを停止するには、Unschedule({time-out})を選択します。このジョブは自動的に実行されるようにスケジュールできなくなります。しかし、ジョブを手動で実行することはできます。

遅延ジョブを手動で開始するには、Unschedule({time-out})を選択して遅延タイマーを停止し、Play({play})を選択します。すぐに GitLab Runner がジョブを開始します。

大規模ジョブの並列化

大きなジョブを複数の小さなジョブに分割して並列実行するには、.gitlab-ci.yml ファイルでparallel キーワードを使用します。

言語やテストスイートによって、並列化の方法は異なります。たとえば、Ruby のテストを並列実行するにはSemaphore Test Boostersと RSpec を使います:

# Gemfile
source 'https://rubygems.org'

gem 'rspec'
gem 'semaphore_test_boosters'
test:
  parallel: 3
  script:
    - bundle
    - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL

その後、新しいパイプラインビルドのジョブタブに移動すると、RSpecジョブが3つの別々のジョブに分割されていることが確認できます。

caution
Test Boosters は使用統計を作成者にレポーターします。

並列ジョブの1次元行列を実行

GitLab 13.5 で導入されました

並列ジョブの一次元マトリックスを作成できます:

deploystacks:
  stage: deploy
  script:
    - bin/deploy
  parallel:
    matrix:
      - PROVIDER: [aws, ovh, gcp, vultr]
  environment: production/$PROVIDER

多次元マトリックスを作成することもできます。

並列トリガジョブの行列の実行

GitLab 13.10で導入されました

一つのパイプラインでトリガージョブを複数回並列に実行することができます。

deploystacks:
  stage: deploy
  trigger:
    include: path/to/child-pipeline.yml
  parallel:
    matrix:
      - PROVIDER: aws
        STACK: [monitoring, app1]
      - PROVIDER: ovh
        STACK: [monitoring, backup]
      - PROVIDER: [gcp, vultr]
        STACK: [data]

この例では、6つの並列deploystacks トリガージョブを生成し、それぞれPROVIDERSTACK に異なる値を設定し、これらの変数で6つの異なる子パイプラインを作成します。

deploystacks: [aws, monitoring]
deploystacks: [aws, app1]
deploystacks: [ovh, monitoring]
deploystacks: [ovh, backup]
deploystacks: [gcp, data]
deploystacks: [vultr, data]

それぞれの並列マトリックスジョブに異なる Runner タグを選択します。

GitLab 14.1 で導入されました

tags キーワードを使ってparallel: matrix で定義された変数を動的なランナー選択に使うことができます:

deploystacks:
  stage: deploy
  parallel:
    matrix:
      - PROVIDER: aws
        STACK: [monitoring, app1]
      - PROVIDER: gcp
        STACK: [data]
  tags:
    - ${PROVIDER}-${STACK}
  environment: $PROVIDER/$STACK

parallel:matrix ジョブからアーティファクトをフェッチします。

dependencies キーワードを使用すると、parallel:matrix で作成されたジョブからアーティファクトをフェッチできます。dependencies の値としてジョブ名をフォームの文字列として使用します:

<job_name> [<matrix argument 1>, <matrix argument 2>, ... <matrix argument N>]

たとえば、RUBY_VERSION2.7 で、PROVIDERaws のジョブからアーティファクトをフェッチするには、次のようにします:

ruby:
  image: ruby:${RUBY_VERSION}
  parallel:
    matrix:
      - RUBY_VERSION: ["2.5", "2.6", "2.7", "3.0", "3.1"]
        PROVIDER: [aws, gcp]
  script: bundle install

deploy:
  image: ruby:2.7
  stage: deploy
  dependencies:
    - "ruby: [2.7, aws]"
  script: echo hello
  environment: production

dependencies を囲む引用符が必要です。

複数の並列ジョブを持つニーズを使用した並列ジョブの指定

GitLab 16.3 で導入されました

needs:parallel:matrix で定義した変数を複数の並列化ジョブで使用することができます。

使用例:

linux:build:
  stage: build
  script: echo "Building linux..."
  parallel:
    matrix:
      - PROVIDER: aws
        STACK:
          - monitoring
          - app1
          - app2

mac:build:
  stage: build
  script: echo "Building mac..."
  parallel:
    matrix:
      - PROVIDER: [gcp, vultr]
        STACK: [data, processing]

linux:rspec:
  stage: test
  needs:
    - job: linux:build
      parallel:
        matrix:
          - PROVIDER: aws
            STACK: app1
  script: echo "Running rspec on linux..."

mac:rspec:
  stage: test
  needs:
    - job: mac:build
      parallel:
        matrix:
          - PROVIDER: [gcp, vultr]
            STACK: [data]
  script: echo "Running rspec on mac..."

production:
  stage: deploy
  script: echo "Running production..."
  environment: production

この例は複数のジョブを生成します。Parallels ジョブはそれぞれPROVIDERSTACK に異なる値を指定します。

  • 3 つの並列linux:build ジョブ:
    • linux:build: [aws, monitoring]
    • linux:build: [aws, app1]
    • linux:build: [aws, app2]
  • 4 並列mac:build ジョブ:
    • mac:build: [gcp, data]
    • mac:build: [gcp, processing]
    • mac:build: [vultr, data]
    • mac:build: [vultr, processing]
  • linux:rspec ジョブ。
  • production ジョブ。

ジョブには3つの実行経路があります:

  • Linux パス:mac:build の終了を待たずに、linux:build: [aws, app1] の終了と同時にlinux:rspec のジョブが実行されます。
  • MacOSパス:mac:rspec ジョブは、mac:build: [gcp, data]mac:build: [vultr, data] のジョブが終了すると、linux:build の終了を待たずにすぐに実行されます。
  • production のジョブは、前のジョブがすべて終了するとすぐに実行されます。

定義済みの CI/CD 変数を使用して、特定のパイプラインタイプでのみジョブを実行します。

定義済みの CI/CD 変数を使用して、どのパイプラインタイプでジョブを実行するかを選択できます:

次の表は、使用できる変数と、変数が制御できるパイプラインタイプの一覧です:

  • ブランチパイプラインは、Gitpush のイベント(新規コミットやタグなど)に対して実行されます。
  • タグパイプライン。新しい Git タグがブランチにプッシュされたときにのみ実行されます。
  • マージリクエストパイプラインは、マージリクエストに対する変更 (新しいコミットやマージリクエストのパイプラインタブでパイプラインの実行ボタンを選択したときなど) に対して実行されます。
  • スケジュールされたパイプライン
変数ブランチタグマージリクエスト予定
CI_COMMIT_BRANCHはい  はい
CI_COMMIT_TAG はい はい、スケジュールされたパイプラインがタグ上で実行されるように設定されている場合。
CI_PIPELINE_SOURCE = pushはいはい  
CI_PIPELINE_SOURCE = scheduled   はい
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: never

正規表現

@ 記号は ref のリポジトリパスの先頭を @表します。正規表現に@ 含ま @れる文字を含む参照名に@ マッチさ @せるには、16進数の文字コード match\x40 を使用する必要があります。

タグやブランチ名だけが正規表現でマッチできます。リポジトリのパスが与えられている場合は、文字列としてのみマッチします。

タグ名やブランチ名にマッチさせるには、パターンの ref 名部分全体が/ で囲まれた正規表現でなければなりません。たとえば、issue- で始まるタグ名やブランチ名をすべてマッチさせるためにissue-/.*/ を使うことはできませんが、/issue-.*/ を使うことはできます。

正規表現のフラグは、/ を閉じた後に付加する必要があります。パターン・マッチはデフォルトで大文字と小文字を区別します。パターンを大文字小文字を区別しないようにするには、/pattern/i のようにi フラグ修飾子を使用します:

job:
  # use regexp
  only:
    - /^issue-.*$/i
  # use special keyword
  except:
    - branches

正規表現がタグ名またはブランチ名の部分文字列のみにマッチするのを避けるには、アンカー^$ を使用します。たとえば、/^issue-.*$//^issue-/ と同じですが、/issue/ だけはsevere-issuesというブランチにもマッチします。

only /except 正規表現の構文

GitLab 11.9.4で、GitLabはonlyexcept キーワードで使われている正規表現を内部でRE2に変換するようになりました。

RE2では計算の複雑さのために利用できる機能が制限され、負のルックヘッドのようないくつかの機能が利用できなくなりました。Ruby Regexpが提供する機能のサブセットのみがサポートされるようになりました。

GitLab 11.9.7からGitLab 14.9まで、GitLabは安全でない正規表現構文を使えるようにする機能フラグを提供していました。現在はRE2に完全にマイグレーションしており、この機能フラグは使えなくなりました。

CI/CD 変数式

変数式を使って、変更がGitLabにプッシュされた後にパイプラインに作成されるジョブを制御します。変数式は次のように使えます:

例えば、rules:if

job1:
  variables:
    VAR1: "variable1"
  script:
    - echo "Test variable comparison
  rules:
    - if: $VAR1 == "variable1"

変数と文字列の比較

等号演算子==!= を使って変数と文字列を比較することができます。一重引用符でも二重引用符でもかまいません。順番は関係ないので、変数が先でも文字列が先でもかまいません。例えば

  • if: $VARIABLE == "some value"
  • if: $VARIABLE != "some value"
  • if: "some value" == $VARIABLE

つの変数の比較

2つの変数の値を比較することができます。例えば

  • if: $VARIABLE_1 == $VARIABLE_2
  • if: $VARIABLE_1 != $VARIABLE_2

変数が未定義かどうかのチェック

変数が定義されているかどうかを調べるには、null キーワードと比較します。例えば

  • if: $VARIABLE == null
  • if: $VARIABLE != null

変数が空かどうかのチェック

変数が定義されているが空かどうかをチェックすることができます。例えば

  • if: $VARIABLE == ""
  • if: $VARIABLE != ""

変数が存在するかチェック

変数が存在するかどうかをチェックするには、式の中で変数名だけを使用します。変数は空であってはいけません。例えば

  • if: $VARIABLE

変数と正規表現パターンの比較

=~ および!~ 演算子を使用すると、変数の正規表現パターンマッチングを行うことができます。正規表現による変数のパターンマッチングはRE2 正規表現構文を使います。

式はtrue if として評価されます:

  • =~を使用して、マッチする場合。
  • !~を使用して、マッチしない場合。

使用例:

  • if: $VARIABLE =~ /^content.*/
  • if: $VARIABLE !~ /^content.*/

/./ のような1文字の正規表現はサポートされておらず、invalid expression syntax エラーが発生します。

パターン・マッチはデフォルトでは大文字小文字を区別します。パターンの大文字小文字を区別しないようにするには、i フラグ修飾子を使用します。例:/pattern/i.

正規表現パターンを変数に格納します。

  • GitLab 15.0からci_fix_rules_if_comparison_with_regexp_variable というフラグで導入されましたが、デフォルトでは無効になっています。
  • GitLab 15.1では一般的に利用可能で、機能フラグci_fix_rules_if_comparison_with_regexp_variable は削除されました。

=~!~ の右辺の変数は正規表現として評価されます。正規表現はスラッシュ (/) で内部を囲む必要があります。例えば

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'

変数式を&& または||

GitLab 12.0 で導入されました

例えば、&& (and) や|| (or) を使って複数の式を結合することができます:

  • $VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"
  • $VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3
  • $VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3

演算子の優先順位はRuby 2.5の標準に従っているので、&&||の前に評価されます。

変数式を括弧でグループ化します。

括弧を使って式をグループにまとめることができます。括弧は&&|| よりも優先されるので、括弧で囲まれた式は最初に評価され、その結果が残りの式に使われます。

複雑な条件を作成するために括弧を入れ子にすることができ、括弧内の最も内側の式が最初に評価されます。

使用例:

  • ($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)
  • ($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3
  • $CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)

トラブルシューティング

を使用しているときにジョブやパイプラインが予期せず実行されます。changes:

rules: changesonly: changesマージリクエストパイプラインなしで使用しているときに、ジョブやパイプラインが予期せず実行されることがあります。

マージリクエストとの関連付けが明示されていないブランチやタグのパイプラインは、差分を計算するために以前の SHA を使用します。この計算はgit diff HEAD~ と同等であり、以下のような予期せぬ動作を引き起こす可能性があります:

  • 新しいブランチや新しいタグを GitLab にプッシュするとき、changes ルールは常に true と評価されます。
  • 新しいコミットをプッシュするとき、変更されたファイルは直前のコミットをベース SHA として計算されます。

さらに、changes のルールは、スケジュールされたパイプラインでは常に真として評価されます。スケジュールされたパイプラインが実行されるとすべてのファイルが変更されたとみなされるため、changes を使用するスケジュールされたパイプラインには常にジョブが追加される可能性があります。

CI/CD変数のファイルパス

CI/CD変数でファイルパスを使用する場合は注意が必要です。末尾のスラッシュは変数定義では正しく見えますが、script:changes: 、または他のキーワードで展開すると無効になることがあります。例えば

docker_build:
  variables:
    DOCKERFILES_DIR: 'path/to/files/'  # This variable should not have a trailing '/' character
  script: echo "A docker job"
  rules:
    - changes:
        - $DOCKERFILES_DIR/*

DOCKERFILES_DIR 変数がchanges: セクションで展開されると、フルパスはpath/to/files//*になります。二重スラッシュは、使用されているキーワードやランナーのシェルやOSなどの要因によって、予期しない動作を引き起こす可能性があります。

You are not allowed to download code from this project. エラーメッセージ

GitLab 管理者が非公開プロジェクトで保護された手動ジョブを実行すると、パイプラインが失敗することがあります。

CI/CD ジョブは通常、ジョブの開始時にプロジェクトをクローンしますが、これはジョブを実行するユーザーの権限を使います。管理者を含むすべてのユーザーは、非公開プロジェクトのソースをクローンするための直接のメンバーでなければなりません。この動作を変更するイシューが存在します。

保護された手動ジョブを実行するには

  • 非公開プロジェクトの直接メンバーとして管理者を追加(ロールは問いません)
  • プロジェクトの直接メンバーであるユーザーになりすます