GitLab CI/CD設定ファイルの最適化
GitLab CI/CD設定ファイルの複雑さや重複した設定を減らすには、次のような方法があります:
-
アンカー (
&) 、エイリアス (*) 、マップマージ (<<) のような YAML 固有の機能。YAMLの様々な機能についてもっと読む -
extendsキーワード はより柔軟で読みやすくなっています。可能であればextendsを使うべきです。
アンカー
YAML には ‘アンカー’ と呼ばれる機能があります。
プロパティを複製もしくは継承するためにアンカーを使います。ジョブのテンプレートを提供するために隠しジョブでアンカーを使います。キーが重複している場合、最新のキーが優先され、他のキーより優先されます。
特定の場合 (スクリプトのための YAML アンカー を参照)、YAML アンカーを使用して、別の場所で定義された複数のコンポーネントを持つ配列を作ることができます。たとえば
.default_scripts: &default_scripts
- ./default-script1.sh
- ./default-script2.sh
job1:
script:
- *default_scripts
- ./job-script.sh
include キーワードを使う場合、複数のファイルにまたがって YAML アンカーを使うことはできません。アンカーは定義されたファイルでのみ有効です。異なる YAML ファイルの設定を再利用するには、!reference タグ またはextends キーワード を使います。
次の例はアンカーとマップのマージを使っています。この例では、.job_template の設定を継承する2つのジョブ、test1 とtest2 が作成され、それぞれ独自のカスタムscript が定義されています:
.job_template: &job_configuration # Hidden yaml configuration that defines an anchor named 'job_configuration'
image: ruby:2.6
services:
- postgres
- redis
test1:
<<: *job_configuration # Add the contents of the 'job_configuration' alias
script:
- test1 project
test2:
<<: *job_configuration # Add the contents of the 'job_configuration' alias
script:
- test2 project
& はアンカーの名前を設定し (job_configuration)、<< は「指定されたハッシュを現在のハッシュにマージする」ことを意味し、* は指定されたアンカーを含みます (job_configuration 再び)。この例の拡張版は
.job_template:
image: ruby:2.6
services:
- postgres
- redis
test1:
image: ruby:2.6
services:
- postgres
- redis
script:
- test1 project
test2:
image: ruby:2.6
services:
- postgres
- redis
script:
- test2 project
アンカーを使って2つのサービスセットを定義することができます。例えば、test:postgres とtest:mysql は、.job_template で定義されたscript を共有しますが、.postgres_services と.mysql_servicesで定義されたservices は、異なるものを使用します:
.job_template: &job_configuration
script:
- test project
tags:
- dev
.postgres_services:
services: &postgres_configuration
- postgres
- ruby
.mysql_services:
services: &mysql_configuration
- mysql
- ruby
test:postgres:
<<: *job_configuration
services: *postgres_configuration
tags:
- postgres
test:mysql:
<<: *job_configuration
services: *mysql_configuration
拡張バージョンは次のとおりです:
.job_template:
script:
- test project
tags:
- dev
.postgres_services:
services:
- postgres
- ruby
.mysql_services:
services:
- mysql
- ruby
test:postgres:
script:
- test project
services:
- postgres
- ruby
tags:
- postgres
test:mysql:
script:
- test project
services:
- mysql
- ruby
tags:
- dev
隠されたジョブがテンプレートとして便利に使われていることがわかります。tags: [postgres] はtags: [dev] を上書きします。
スクリプトのためのYAMLアンカー
GitLab 12.5で導入されました。
YAMLアンカーを script,before_script,after_script で使うことで、複数のジョブで定義済みのコマンドを使うことができます:
.some-script-before: &some-script-before
- echo "Execute this script first"
.some-script: &some-script
- echo "Execute this script second"
- echo "Execute this script too"
.some-script-after: &some-script-after
- echo "Execute this script last"
job1:
before_script:
- *some-script-before
script:
- *some-script
- echo "Execute something, for this job only"
after_script:
- *some-script-after
job2:
script:
- *some-script-before
- *some-script
- echo "Execute something else, for this job only"
- *some-script-after
設定セクションを再利用するにはextends を使います。
複数のジョブで設定を再利用するためにextends キーワード を使うことができます。これはYAML アンカーに似ていますが、よりシンプルで、 extends をincludesと一緒に使うことができます。
extends は複数レベルの継承をサポートします。複雑さが増すので3つ以上のレベルを使うことは避けるべきですが、11個まで使うことができます。以下の例では、2つのレベルの継承を行っています:
.tests:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
.rspec:
extends: .tests
script: rake rspec
rspec 1:
variables:
RSPEC_SUITE: '1'
extends: .rspec
rspec 2:
variables:
RSPEC_SUITE: '2'
extends: .rspec
spinach:
extends: .tests
script: rake spinach
からキーを除外します。extends
拡張コンテンツからキーを除外するには、そのキーをnull に割り当てる必要があります:
.base:
script: test
variables:
VAR1: base var 1
test1:
extends: .base
variables:
VAR1: test1 var 1
VAR2: test2 var 2
test2:
extends: .base
variables:
VAR2: test2 var 2
test3:
extends: .base
variables: {}
test4:
extends: .base
variables: null
マージ設定:
test1:
script: test
variables:
VAR1: test1 var 1
VAR2: test2 var 2
test2:
script: test
variables:
VAR1: base var 1
VAR2: test2 var 2
test3:
script: test
variables:
VAR1: base var 1
test4:
script: test
variables: null
extends 、include 。
異なる設定ファイルの設定を再利用するには、extends とinclude を組み合わせてください。
次の例では、script がincluded.yml ファイルで定義されています。次に、.gitlab-ci.yml ファイルで、extends はscript の内容を参照します:
-
included.yml:.template: script: - echo Hello! -
.gitlab-ci.yml:include: included.yml useTemplate: image: alpine extends: .template
マージの詳細
extends を使ってハッシュをマージすることはできますが、配列をマージすることはできません。マージに使われるアルゴリズムは “最も近いスコープが勝つ “です。キーが重複している場合、GitLabはキーを元に逆ディープマージを行います。最後のメンバーからのキーは、常に他のレベルで定義されたものを上書きします。例えば
.only-important:
variables:
URL: "http://my-url.internal"
IMPORTANT_VAR: "the details"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_BRANCH == "stable"
tags:
- production
script:
- echo "Hello world!"
.in-docker:
variables:
URL: "http://docker-url.internal"
tags:
- docker
image: alpine
rspec:
variables:
GITLAB: "is-awesome"
extends:
- .only-important
- .in-docker
script:
- rake rspec
結果はこのようになりますrspec ジョブ:
rspec:
variables:
URL: "http://docker-url.internal"
IMPORTANT_VAR: "the details"
GITLAB: "is-awesome"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_BRANCH == "stable"
tags:
- docker
image: alpine
script:
- rake rspec
この例では:
-
variablesのセクションはマージされますが、URL: "http://docker-url.internal"はURL: "http://my-url.internal"を上書きします。 -
tags: ['docker']はtags: ['production']を上書きします。 -
scriptはマージしませんが、script: ['rake rspec']はscript: ['echo "Hello world!"']を上書きします。配列をマージするためにYAML アンカーを使うことができます。
!reference タグ
!reference カスタムYAMLタグを使って他のジョブセクションからキーワード設定を選択し、現在のセクションで再利用 !referenceします。!reference YAMLアンカーとは異なり、 !referenceタグを使ってインクルードされた設定ファイルから設定を再利用することもできます。
次の例では、2つの異なる場所からscript とafter_script がtest ジョブで再利用されています:
-
setup.yml:.setup: script: - echo creating environment -
.gitlab-ci.yml:include: - local: setup.yml .teardown: after_script: - echo deleting environment test: script: - !reference [.setup, script] - echo running my own command after_script: - !reference [.teardown, after_script]
次の例では、test-vars-1 は.vars のすべての変数を再利用し、test-vars-2 は特定の変数を選択し、新しいMY_VAR 変数として再利用します。
.vars:
variables:
URL: "http://my-url.internal"
IMPORTANT_VAR: "the details"
test-vars-1:
variables: !reference [.vars, variables]
script:
- printenv
test-vars-2:
variables:
MY_VAR: !reference [.vars, variables, IMPORTANT_VAR]
script:
- printenv
script 、before_script 、!reference のタグを入れ子にします。after_script
GitLab 14.8で導入されました。
script,before_script,after_script セクションでは、!reference タグを 10 レベルまでネストできます。より複雑なスクリプトを作るときに、ネストしたタグを使って再利用可能なセクションを定義します。例えば
.snippets:
one:
- echo "ONE!"
two:
- !reference [.snippets, one]
- echo "TWO!"
three:
- !reference [.snippets, two]
- echo "THREE!"
nested-references:
script:
- !reference [.snippets, three]
この例では、nested-references ジョブは 3 つのecho コマンドをすべて実行します。
!reference タグをサポートするように IDE を設定します。
パイプラインエディターは !reference タグをサポートします。しかし、カスタムYAMLタグのスキーマルールは!reference デフォルトではエディターによって無効なものとして扱われるかもしれません !reference。タグを受け入れる!reference ようにエディタを設定 !referenceできます。たとえば
-
VS Code では、
settings.jsonファイルのcustomTagsを解析するようにvscode-yamlを設定できます:"yaml.customTags": [ "!reference sequence" ] -
Sublime Text では、
LSP-yamlパッケージを使用している場合、LSP-yamlユーザー設定でcustomTagsを設定できます:{ "settings": { "yaml.customTags": ["!reference sequence"] } }