LoginSignup
3
3

More than 1 year has passed since last update.

GitLab CIのinclude機能を試す

Posted at

GitLab CIには外部のYAMLファイルを取り込む方法としてincludeというキーワードが用意されている。これを使うとどのような感じで.gitlab-ci.ymlが分割出来るかを調べた時のメモ。

includeとは

.gitlab-ci.ymlとは別にパイプラインを記述しておいて、それを引っ張ってくる機能である。これにより.gitlab-ci.ymlを分割できるため、以下の効果が期待できる。

  • 可読性の向上
  • 設定の外出しによるメンテナビリティ向上

includeには4種類の外部ファイルの引っ張り方が用意されている。

方法 説明
local 同一プロジェクト内の別ファイルをinclude
file 同一GitLab内の別プロジェクト内のファイルをinclude
remote リモートで公開されているファイルのURLを指定してinclude
template GitLabが提供しているテンプレートをinclude

事前準備

検証用にGitLab上に以下の空のプロジェクトを作成し、ほぼ何もしない.gilab-ci.yamlを作成する。ディレクトリ構造は以下となる。

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

作成した.gitlab-ci.ymlは以下となる。

/.gitlab-ci.yml
stages:
  - build

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

このパイプライン(build stage)の実行結果は以下。

Executing "step_script" stage of the job script
$ echo "dummy"
dummy
Job succeeded

local

localは同一プロジェクト内の別ファイルをincludeする。
この機能の確認のために、最初に別ファイルを格納するディレクトリを作成する。

mkdir .gitlab-ci

次に適当なジョブを記載したファイル(.gitlab-ci/included.yml)を作成する。

cat << EOF > .gitlab-ci/included.yml
test:
  stage: build
  script:
    - echo "included"
EOF

事前準備の際に作成した/.gitlab-ci.ymlで上記の.gitlab-ci/included.ymlを呼び出すように修正する。

/.gitlab-ci.yml
stages:
  - build

include:
  - local: .gitlab-ci/included.yml

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

これをコミットすると、2つのジョブが平行して実行される。
.gitlab-ci/included.ymlで実装したtestジョブの出力結果は以下となった。

Executing "step_script" stage of the job script
$ echo "included"
included
Job succeeded

ちなみに公式のサンプルにも説明があるが、localremoteに関しては省略可能であるため以下のようにも書ける。

include:
  - .gitlab-ci/included.yml

ネストも出来るようなので、こちらも試してみる。デフォルトの設定値を定義したユースケースを想定し、config-defaults.ymlを作成する

cat << EOF > .gitlab-ci/config-defaults.yml
variables:
  DEFAULT_VAL_A: "default_val_a"
  DEFAULT_VAL_B: "default_val_a"
EOF

.gitlab-ci/included.ymlを以下のように修正する。

/.gitlab-ci/included.yml
include: .gitlab-ci/config-defaults.yml
test:
  stage: build
  script:
    - echo "included"

.gitlab-ci.ymlを以下のように修正する。

/.gitlab-ci.yml
variables:
  DEFAULT_VAL_B: "b"
stages:
  - build

include:
  - local: .gitlab-ci/included.yml

build-job:
  stage: build
  script:
    - echo "$DEFAULT_VAL_A"
    - echo "$DEFAULT_VAL_B"

これをpushした時のbuild-jobの結果は以下となった。

Executing "step_script" stage of the job script
$ echo "$DEFAULT_VAL_A"
default_val_a
$ echo "$DEFAULT_VAL_B"
b
Job succeeded

ネスト先の.gitlab-ci/config-defaults.ymlから値が引っ張れることと、値が上書き出来ることが確認できた。

file

fileは同一のGitLab内の別プロジェクトからファイルを引っ張ってくる。
file:と同列にproject:ref:も指定し、プロジェクト名およびGit Refを指定する。refはデフォルトでHEADになっており、スキップすることも可能。
ここでは同一GitLab内にmyapp/common-gitlab-ciを作成し、includeするYAMLを配置する。
git cloneしたディレクトリで以下を実行して作成する。

mkdir .gitlab-ci
cat << EOF > ./.gitlab-ci/common.yaml
common:
  stage: build
  script:
    - echo "common"
EOF

次に最初に作成したプロジェクトのincluded.ymlを以下のように修正する

/.gitlab-ci/included.yml
include:
  - .gitlab-ci/config-defaults.yml
  - project: myapp/common-gitlab-ci
    file: .gitlab-ci/common.yaml
test:
  stage: build
  script:
    - echo "included"

これをpushしてパイプラインを実行すると、build-jobtestcommonの3つのジョブが実行され、commonの結果を見ると外部プロジェクトから引っ張ってこれているのが分かる。

Executing "step_script" stage of the job script
$ echo "common"
common
Job succeeded

これにより、開発リポジトリを変更することなく外部リポジトリのYAMLを修正するだけでパイプラインを変更することが実証できた。
複数プロジェクトでGitLab CIを使う際、共通パラメータなどを格納するのはfileで指定するプロジェクトにしておくと良さそうだ。

remote

remoteは外部公開しているYAMLのURLを直接指定する。検証用に先程作成したプロジェクトmyapp/common-gitlab-ciをPublic設定に変更し、適当なYAMLを追加してrawのURLを指定することで検証しようとしたのだが、GitLab側でPublicに変更出来なかったため、GitHubで同等のプロジェクト(リポジトリ)を作成して代用した。
以下のファイルを作成する。

cat << EOF > ./.gitlab-ci/remote.yml
remote:
  stage: build
  script:
    - echo "remote"
EOF

GitHubにpushした結果、以下でYAMLが取得できるようになった。
https://raw.githubusercontent.com/imurata/common-gitlab-ci/main/.gitlab-ci/remote.yml

これをincluded.ymlで呼び出すよう、以下のようにremote行を追加する。

/.gitlab-ci/included.yml
include:
  - .gitlab-ci/config-defaults.yml
  - project: myapp/common-gitlab-ci
    file: .gitlab-ci/common.yaml
  - remote: https://raw.githubusercontent.com/imurata/common-gitlab-ci/main/.gitlab-ci/remote.yml
test:
  stage: build
  script:
    - echo "included"

なお、前述のようにremote:は省略することも可能だが、ここでは可読性を重視して省略していない。
パイプラインを実行した結果、remoteのジョブが増え、以下の結果を得た。

Executing "step_script" stage of the job script
$ echo "remote"
remote
Job succeeded

YAMLを共通化したいが同一のGitLabにプロジェクトを置けないようなケースではremoteが利用できそうだ。

template

templateはGitLabが持っているテンプレートを呼び出すことが出来る。
ここではBash.gitlab-ci.ymlを試しに呼び出してみる。
Bash.gitlab-ci.ymlが内部で呼び出しているstageはbuildtestdeployなので、/.gitlab-ci.yml側でもそれらを使うように変更する。
修正後の/.gitlab-ci.ymlは以下となる。

/.gitlab-ci.yml
variables:
  DEFAULT_VAL_B: "b"
stages:
  - build
  - test
  - deploy

include:
  - local: .gitlab-ci/included.yml

build-job:
  stage: build
  script:
    - echo "$DEFAULT_VAL_A"
    - echo "$DEFAULT_VAL_B"

またincluded.ymltemplateを使うように修正する。

/.gitlab-ci/included.yml
include:
  - .gitlab-ci/config-defaults.yml
  - project: myapp/common-gitlab-ci
    file: .gitlab-ci/common.yaml
  - remote: https://raw.githubusercontent.com/imurata/common-gitlab-ci/main/.gitlab-ci/remote.yml
  - template: Bash.gitlab-ci.yml
test:
  stage: build
  script:
    - echo "included"

これでパイプラインを実行すると、buildステージ以外にBash.gitlab-ci.ymlで定義していたtestdeployステージが実行され、buildステージではBash.gitlab-ci.ymlが定義していたbuild1ジョブが実行されることが分かる。

templateに関しては元々用意してあるものをどう活用するかというよりは、自作したものをGitLab内でテンプレート化した際に使うものだと思われる。
テンプレートの作成についてはDevelopment guide for GitLab CI/CD templatesが参考になるが、ここでは本旨ではないため触れない。

まとめ

includeを使うことで単なるファイル分割ではなく、リポジトリ外のYAMLを引っ張ってパイプラインを実行することが出来、.gitlab-ci.ymlをプロジェクト単位で管理するリスクを軽減できる見込みを得た。
インフラ部門がGitLab CIによるCI/CDを推進する場合、開発部門がプロジェクト毎にジョブを作り込むよりも、インフラ部門で標準化やコンテナイメージの最新化を図ったYAMLを作成してincludeで開発部門に使ってもらうことで、組織全体がよりセキュアに持っていけるのではないかと思う。

3
3
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
3
3