正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

GitLab CI/CD設定ファイルを最適化する

  • プラン: Free、Premium、Ultimate
  • 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated

次の機能やキーワードを使用すると、GitLab CI/CD設定ファイルにおける複雑さや重複した設定を軽減できます:

  • アンカー(&、エイリアス(*)、マップのマージ(<<)などのYAML固有の機能。さまざまなYAMLの機能について、詳細をご覧ください。
  • より柔軟で読みやすいextendsキーワード。可能な場合はextendsの使用が推奨されます。

複数の類似したジョブを作成するものの、異なる変数の値を使用するには、`parallel:matrixを使用します。

アンカー

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キーワードを使用します。

次の例では、アンカーとマップのマージを使用します。test1test2の2つのジョブを作成します。これらのジョブは.job_template設定を継承し、それぞれに独自のカスタム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:postgrestest: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アンカー

YAMLアンカーscriptbefore_scriptafter_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アンカーと似ていますが、よりシンプルで、extendsincludesとともに使用できます。

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

extendsincludeを組み合わせて使用する

異なる設定ファイルから設定を再利用するには、extendsincludeを組み合わせます。

次の例では、included.ymlファイルでscriptが定義されています。次に、.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タグ

カスタムYAMLタグ!referenceを使用して、その他のジョブセクションからキーワード設定を選択し、現在のセクションで再利用できます。YAMLアンカーとは異なり、!referenceタグを使用してインクルードされた設定ファイルから設定を再利用することもできます。

次の例では、2つの異なる場所にあるscriptafter_scripttestジョブ内で再利用しています:

  • configs.yml:

    .setup:
      script:
        - echo creating environment
  • .gitlab-ci.yml:

    include:
      - local: configs.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

!referenceタグをparallel:matrixキーワードとともに使用する場合、既知のイシューが存在します。

CI/CD入力!referenceタグでは使用できません。!referenceタグは入力補間の前に評価されるためです。

scriptbefore_scriptafter_script内で!referenceタグをネストする

scriptbefore_scriptafter_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タグをサポートしています。ただし、!referenceのようなカスタムYAMLタグのスキーマルールは、デフォルトではエディタによって無効と見なされる場合があります。一部のエディタでは、!referenceタグを受け入れるように設定できます。例は次のとおりです:

  • VS Codeでは、settings.jsonファイル内で、customTagsを解析するようにvscode-yamlを設定できます:

    "yaml.customTags": [
       "!reference sequence"
    ]
  • Sublime TextでLSP-yamlパッケージを使用している場合は、LSP-yamlユーザー設定でcustomTagsを設定できます:

    {
      "settings": {
        "yaml.customTags": ["!reference sequence"]
      }
    }