4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GitLab CIのtrigger機能を試す

Last updated at Posted at 2023-01-31

GitLabでパイプラインの分割を調べると、includeと一緒にtriggerもよく出てくる。
どう使えるんだろう、と思って調べた時のメモ。
triggerは複数のプロジェクトのパイプラインを実行するMulti-project piplinesと親子関係を持たせたパイプラインを実行するParent-child pipelinesというものそれぞれで利用できるが、ここでは親子パイプラインに絞ってメモを残している。
全体的にかなり荒い点はご了承を。

trigger概要

triggerを使うとパイプラインに親子関係を持たせることが出来る。
オフィシャルドキュメントはこのあたり

親子関係と言ってもしっくり来ないが、ざっくり言うとパイプラインを独立・並行して複数本走らせることが出来る、と考えておけば良さそう。
自分の頭の中のイメージは以下のような感じ(汚いが。。。)。

1675156338468.png

A,B,C,Dはそれぞれパイプラインのstage相当と考えるとよい。
普通のパイプラインは.gitlab-ci.ymlに書ききってしまうが、includeを使うケースだと外に出すことが出来る(参考:昔の記事)。
triggerは更に中で独立したパイプラインを作って.gitlab-ci.ymlのパイプラインとは独立して動かす感じになる。

オフィシャルドキュメントの親子パイプラインの説明では以下のようなものもあった。(DeepLでの翻訳)

マルチプロジェクトパイプラインと同様に、パイプラインは、同じプロジェクト内で、同時に実行される一連の子パイプラインをトリガーすることができます。

  • 子パイプラインは、ステージシーケンスに従って各ジョブを実行しますが、親パイプラインの無関係なジョブの終了を待つことなく、自由にステージを進めることができます。
  • 構成は、より小さな子パイプラインの構成に分割され、理解しやすくなっています。これにより、構成全体を理解するための認知的負荷が軽減されます。
  • インポートは子パイプラインレベルで行われるため、衝突の可能性が低くなります。
  • 各パイプラインは関連するステップのみを持ち、何が起こっているのか理解しやすくなります。
    子パイプラインは、GitLabの他のCI/CD機能とうまく連動する。
  • only: changes は、特定のファイルが変更されたときだけパイプラインを起動します。これは、モノレポ構成などで有効です。
    .gitlab-ci.ymlにある親パイプラインと子パイプラインは通常のパイプラインとして動作するので、トリガーに関する独自の動作や順序を持たせることができる。
    これらはすべてinclude:機能で動作するので、子パイプラインの設定を構成することができます。

上記には単一リポジトリに複数の種類のコードを入れる(例えばFrontendとBackendを同じリポジトリに突っ込む)、いわゆるモノレポ構成だと使えるとの記述がある。
これはBackendの修正でFrontend向けのCI/CDを動かしたくない、といったようなニーズがある場合、triggerでBackendとFrontendのパイプラインをそれぞれincludeし、only: changesでパスを指定してFrontend向け修正契機で動いたのかBackend向け修正契機で動いたのかを検知して特定のパイプラインだけ動かす、といったことが出来ることを指している。
この辺りの詳細はモノレポでのCI/CDパイプラインの定義方法を考える(GitLab)というブログが非常に分かりやすいのでそちらを参考にするとよいと思う。(今回触るにあたり、非常に参考にさせていただいた)

triggerの仕様

ここでの説明はオフィシャルの説明をざっくり意訳したものとなる。
triggerのジョブ内で使えるkeyword(同じ高さで書けるkeyword)には制限があり、以下の利用可能となっている。

  • allow_failure
  • extends
  • needs (ただしneeds:projectは不可)
  • onlyexcept
  • rules
  • stage
  • trigger
  • variables
  • when (on_success, on_failure, alwaysのいずれかのみ).

またtriggerで実行できるパイプラインはtrigger:projectでGitLab内プロジェクトを指定するか、trigger:includeincludeを使って引っ張ってくる。

triggerで使える他のkeywordとしてはtrigger:strategytrigger:forwardがある。

trigger:strategy

通常、親のパイプラインは子の結果を待たずに終了するが、triggerの中でstrategy: dependを指定すると子のパイプラインの結果を待って終了する。
後ろの方で実際に使った結果を載せているので、詳細はそちらを参照してほしい。

trigger:forward

環境変数の引き継ぎを指定する。
デフォルトでは以下のようになっている。

  • GitLab内の環境変数:子に引き継がれない
  • variablesの環境変数:子に引き継がれる

fowardの中でpipeline_variables: trueを指定すると、GitLab内で設定した環境変数を引き継ぐことが出来るようになる。また、yaml_variables: falseを指定するとvariablesで定義した環境変数が引き継ぎを拒否できる。
参考までに、オフィシャルの説明のサンプルを翻訳したものを以下に示す。

example
## MYVARはGitLabのCI/CDで設定する環境変数
variables: # 各ジョブのデフォルトの環境変数 
  VAR: value

# デフォルトの振る舞い
# - VARは子に渡る
# - MYVARは子に渡らない
child1:
  trigger:
    include: .child-pipeline.yml

# CI/CDの環境変数を転送する
# - VARは子に渡る
# - MYVARは子に渡る
child2:
  trigger:
    include: .child-pipeline.yml
    forward:
      pipeline_variables: true

# YAMLのvariablesを転送しない
# - VARは子に渡らない
# - MYVARは子に渡らない
child3:
  trigger:
    include: .child-pipeline.yml
    forward:
      yaml_variables: false

triggerのお試し

検証用なので、Runner用のYAMLのみの以下の構成で検証する。

.
├── README.md
├── .gitlab-ci.yml
└── gitlab-ci
    └── trigger.yml

ファイルは以下の様に作成した。

.gitlab-ci.yml
stages:
  - build

build-job:
  stage: build
  trigger:
    include: gitlab-ci/trigger.yml

include対象はこちら。stageには親には定義されていないものを使っている。

gitlab-ci/trigger.yml
stages:
  - huga

hoge:
  stage: huga
  script:
    - date

実行結果はこちら。UpstreamにProject名が表示され、Parentというのが表示されていることが分かる。

1675128101592.png

なお、.gitlab-ci.ymlを以下のようにtriggerを外すと、Lintでエラーが出る。

.gitlab-ci.yml
stages:
  - build

include:
 - gitlab-ci/trigger.yml

build-job:
  stage: build
  script:
  - echo "dummy"

stage: hugaの定義が.gitlab-ci.ymlにないのでデフォルトのstageを使うよう促される。

1675130295725.png

余談だが、triggerを利用するstageではscriptは利用できない。こちらも文法的にNGとなる。

Triggerの並列実行

triggerで子のパイプラインを生成する際、親のstageは子の完了を待たないため、並列実行のような形になる。それを確認する。
includeで呼び出すパイプラインを以下のように用意する。

gitlab-ci/trigger.yml
stages:
  - huga
hoge:
  stage: huga
  script:
    - date
gitlab-ci/sleep30s.yml
stages:
  - huga
hoge:
  stage: huga
  script:
    - sleep 30
    - date
    - exit 1

sleepさせているのは、最初のstage側でsleep30s.ymlをincludeして、後続のstageが追い抜くことを確認するために入れている。
また、それらを呼び出すように.gitlab-ci.ymlを以下のように修正する。

.gitlab-ci.yml
stages:
  - build

build-job-1:
  stage: build
  trigger:
    include:
     - gitlab-ci/sleep30s.yml

build-job-2:
  stage: build
  trigger:
    include:
     - gitlab-ci/trigger.yml

待たないのであれば、build-job-1の子のパイプラインが30秒sleepしている間にbuild-job-2の実行が終わる。また、build-job-1自体も子のパイプラインを起動した時点で完了する。
これを確認するために、修正をpushしてパイプラインを実行した結果が以下となる。Passedにはなるが、子はまだ完了していない。

1675139092032.png
このように実行中である。

1675139431646.png

また、build-job-1, build-job-2で作成されたパイプラインのジョブのdateの結果を見比べると以下のようになった。

  • build-job-1: Tue Jan 31 04:46:31 UTC 2023
  • build-job-2: Tue Jan 31 04:46:01 UTC 2023

build-job-2が追い抜いていることが分かる。
このように、

  • 子の完了を待たずに親は終了する
  • 子が失敗しても、親側では分からない
  • 子の完了を待たずに次のstageが実行される

といったことがこの結果から言える。
また、includeするファイルにそれぞれhugaというstageを用意しているが、通常同一stage名を含む複数ファイルをincludeするとどれかで上書きされてしまう。しかし、triggerでそれぞれincludeした場合は上書きされることがない。
stage名を意識しなくてもincludeが使える点はtriggerのメリットとも言えそう。

なお、子の完了を待って親に状態を反映するには前述のtrigger:strategyを使えば良い。.gitlab-ci.ymlを以下のように修正する。

.gitlab-ci.yml
stages:
  - build

build-job-1:
  stage: build
  trigger:
    include:
     - gitlab-ci/sleep30s.yml
    strategy: depend

build-job-2:
  stage: build
  trigger:
    include:
     - gitlab-ci/trigger.yml

これをPushすると、以下のような結果が得られる。
1675159676684.png

パイプラインの完了はsleep 30の処理が終わってからとなり、sleep30s.ymlの最後のexit 1で子のジョブが失敗するため、それを引き継いでエラーとなる。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?