CI/CD コンポーネント(FREE ALL EXPERIMENT)
- GitLab 16.0 で実験的な機能として導入され、
ci_namespace_catalog_experimental
というフラグがあります。デフォルトでは無効になっています。- GitLab.comで有効になり、GitLab 16.2で自己管理。
- 機能フラグ
ci_namespace_catalog_experimental
を GitLab 16.3 で削除しました。
この機能は実験的な機能であり、将来の作業を追跡するためにエピックが存在します。エピックにコメントを残して、あなたのユースケースを教えてください。
コンポーネントリポジトリ
コンポーネントリポジトリは、1つ以上のパイプラインコンポーネントをホストするリポジトリを持つGitLabプロジェクトです。パイプラインコンポーネントは、再利用可能な単一のパイプライン設定単位です。パイプラインコンポーネントを使用して、パイプライン設定全体を構成したり、より大きなパイプラインの一部を構成したりできます。オプションで入力パラメータを受け取ることができます。
コンポーネントリポジトリの作成
コンポーネントリポジトリを作成するには、以下の手順が必要です:
-
README.md
ファイルで新しいプロジェクトを作成します。 -
プロジェクトのルート・ディレクトリ内部に、コンポーネントとして提供したい設定を含む
template.yml
ファイルを作成します。例えばspec: inputs: stage: default: test --- component-job: script: echo job 1 stage: $[[ inputs.stage ]]
ディレクトリ構造
コンポーネントリポジトリは1つ以上のコンポーネントをホストすることができ、必須のファイル構造に従う必要があります。
コンポーネントの設定は、以下のようなディレクトリ構造で保存されます:
-
templates
コンポーネントリポジトリの最上位にあるディレクトリです。すべてのコンポーネント設定ファイルは、このディレクトリの下に保存する必要があります。 -
.yml
で終わるファイルには、コンポーネントの設定が含まれています。 - リポジトリ内のすべてのコンポーネントの詳細を説明する Markdown
README.md
ファイル。
たとえば、プロジェクトに単一のコンポーネントとコンポーネントをテストするパイプラインが含まれている場合、ファイル構造は次のようになります:
├── templates/
│ └── only_template.yml
├── README.md
└── .gitlab-ci.yml
この例のコンポーネントは、プロジェクトがgitlab.com/my-username/my-component/only_template@<version>
のようなパスで参照できます:
- GitLab.com の場合
- 名前
my-component
- という名前の個人ネームスペースでは
my-username
テンプレート・ディレクトリと設定ファイルのサフィックスは、参照されるパスから除外する必要があります。
プロジェクトに複数のコンテナが含まれる場合、ファイル構造は以下のようになります:
├── README.md
├── .gitlab-ci.yml
└── templates/
└── all-scans.yml
└── secret-detection.yml
これらのコンポーネントはこれらのパスで参照されます:
gitlab.com/my-username/my-component/all-scans
gitlab.com/my-username/my-component/secret-detection
設定ファイルの名前がtemplate.yml
の場合、パスのファイル名を省略することができます。例えば、以下のコンポーネントはgitlab.com/my-username/my-component/dast
で参照できます:
├── README.md
├── .gitlab-ci.yml
├── templates/
│ └── dast
│ └── template.yml
任意のディレクトリに保存されたコンポーネント設定 (非推奨)
コンポーネントの設定は、以下のディレクトリ構造で保存できます:
-
template.yml
:コンポーネント設定、コンポーネントごとに1ファイル。コンポーネントが1つだけの場合、このファイルはプロジェクトのルートに置くことができます。複数のコンポーネントがある場合、それぞれのファイルは別々のサブディレクトリになければなりません。 -
README.md
:リポジトリ内のすべてのコンポーネントの詳細を説明するドキュメントファイルです。
例えば、プロジェクトがGitLab.comにあり、my-component
という名前で、my-username
という個人的な名前空間にある場合:
-
単一のコンポーネントとコンポーネントをテストするためのシンプルなパイプラインを含む場合、ファイル構造は次のようになります:
├── template.yml ├── README.md └── .gitlab-ci.yml
このコンポーネントは
gitlab.com/my-username/my-component@<version>
というパスで参照されます。 -
1つのデフォルトコンポーネントと複数のサブコンポーネントを含む場合、ファイル構造は次のようになります:
├── template.yml ├── README.md ├── .gitlab-ci.yml ├── unit/ │ └── template.yml └── integration/ └── template.yml
これらのコンポーネントは、以下のパスで識別されます:
gitlab.com/my-username/my-component
gitlab.com/my-username/my-component/unit
gitlab.com/my-username/my-component/integration
ルートディレクトリにtemplate.yml
を置かないことで、デフォルトコンポーネントを持たないコンポーネントリポジトリを持つことができます。
その他の注意事項
コンポーネントの入れ子はできません。例えば
├── unit/
│ └── template.yml
│ └── another_folder/
│ └── nested_template.yml
コンポーネントのテスト
開発ワークフローの一環としてコンポーネントをテストし、品質が高い水準を維持できるようにすることを強く推奨します。
CI/CDパイプラインでの変更点のテストは、他のプロジェクトと同様に、ルートディレクトリに.gitlab-ci.yml
。
使用例:
include:
# include the component located in the current project from the current SHA
- component: gitlab.com/$CI_PROJECT_PATH@$CI_COMMIT_SHA
inputs:
stage: build
stages: [build, test, release]
# Expect `component-job` is added.
# This is an example of testing that the included component works as expected.
# You can leverage GitLab API endpoints or 3rd party tools to inspect data generated by the component.
ensure-job-added:
stage: test
image: badouralix/curl-jq
script:
- |
route="https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/jobs"
count=`curl --silent --header "PRIVATE-TOKEN: $API_TOKEN" $route | jq 'map(select(.name | contains("component-job"))) | length'`
if [ "$count" != "1" ]; then
exit 1
fi
# If we are tagging a release with a specific convention ("v" + number) and all
# previous checks succeeded, we proceed with creating a release automatically.
create-release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+/
script: echo "Creating release $CI_COMMIT_TAG"
release:
tag_name: $CI_COMMIT_TAG
description: "Release $CI_COMMIT_TAG of components repository $CI_PROJECT_PATH"
変更をコミットしてプッシュした後、パイプラインはコンポーネントをテストし、テストに合格したらリリースします。
コンポーネントのリリース
コンポーネントリポジトリは、CIパイプライン内でrelease
キーワードを使用してリリースされます。
上の例のように、タグ ref に対して実行されるパイプラインですべてのテストがパスした後、コンポーネントリポジトリの新しいバージョンをリリースすることができます。
コンポーネントリポジトリのすべてのリリースバージョンは、指定したリソースのコンポーネントカタログページに表示され、公式リリースの情報をユーザーに提供します。
CI/CD 設定でのコンポーネントの使用
パイプラインコンポーネントは、<fully-qualified-doman-name>/<component-path>@<version>
を含むユニークなアドレスで識別されます:
- 完全修飾ドメイン名(FQDN): FQDNはGitLabホストと一致しなければなりません。
-
特定のバージョン:コンポーネントのバージョンは(優先順位の高いものから順に)指定できます:
- コミット SHA、たとえば
gitlab.com/gitlab-org/dast@e3262fdd0914fa823210cdb79a8c421e2cef79d8
。 - タグ。例:
gitlab.com/gitlab-org/dast@1.0
. -
~latest
これは、常に最新のリリースタグを指す特別なバージョンで、例えばgitlab.com/gitlab-org/dast@~latest
。 - ブランチ名、例えば
gitlab.com/gitlab-org/dast@main
。
- コミット SHA、たとえば
-
コンポーネントパス:プロジェクトのフルパスとコンポーネント YAML ファイル
template.yml
が存在するディレクトリをコンテナで指定します。
たとえば、gitlab.com
のgitlab-org/dast
にあるコンポーネントリポジトリの場合:
- パス
gitlab.com/gitlab-org/dast
はルートディレクトリからtemplate.yml
をロードしようとします。 - パス
gitlab.com/gitlab-org/dast/api-scan
は/api-scan
ディレクトリからtemplate.yml
をロードしようとします。
その他の注意事項
- プロジェクトと同じGitLabインスタンス内のコンポーネントしか参照できません。
- タグとブランチが同じ名前で存在する場合、タグがブランチより優先されます。
- タグが
e3262fdd0914fa823210cdb79a8c421e2cef79d8
のように、存在するコミット SHA と同じ名前の場合、コミット SHA がタグより優先されます。
ベストプラクティス
グローバルキーワードの使用を避ける
グローバルキーワードを使用すると、パイプライン内のすべてのジョブが影響を受けます。コンポーネントでこれらのキーワードを使用すると、メイン.gitlab-ci.yml
で直接定義されているか、含まれるコンポーネントで定義されているかにかかわらず、パイプライン内のすべてのジョブに影響します。
パイプラインの構成をより決定論的にするには、次のいずれかを実行します:
- 各ジョブのデフォルト設定を複製します。
- コンポーネント内部で
extends
機能を使用します。
##
# BAD
default:
image: ruby:3.0
rspec:
script: bundle exec rspec
##
# GOOD
rspec:
image: ruby:3.0
script: bundle exec rspec
ハードコードされた値を入力に置き換えます
CIテンプレートで見られる典型的なハードコードされた値は、stage:
。このようなハードコードされた値は、コンポーネントのユーザーに、このような実装の詳細を知ってパイプラインを適応させることを強いるかもしれません。
例えば、stage: test
があるコンポーネントのジョブに対してハードコードされている場合、そのコンポーネントを使用するパイプラインはtest
のステージを定義しなければなりません。さらに、コンポーネントのユーザーがステージ値をカスタマイズしたい場合、設定をオーバーライドする必要があります:
##
# BAD: In order to use different stage name you need to override all the jobs
# included by the component.
include:
- component: gitlab.com/gitlab-org/ruby-test@1.0
stages: [verify, deploy]
unit-test:
stage: verify
integration-test:
stage: verify
##
# BAD: In order to use the component correctly you need to define the stage
# that is hard-coded in it.
include:
- component: gitlab.com/gitlab-org/ruby-test@1.0
stages: [test, deploy]
これを改善するために、コンポーネントのユーザーがカスタマイズ可能な値を注入できるように、入力パラメータを使用することができます:
##
# GOOD: We don't need to know the implementation details of a component and instead we can
# rely on the inputs.
include:
- component: gitlab.com/gitlab-org/ruby-test@1.0
inputs:
stage: verify
stages: [verify, deploy]
##
# inside the component YAML:
spec:
inputs:
stage:
default: test
---
unit-test:
stage: $[[ inputs.stage ]]
script: echo unit tests
integration-test:
stage: $[[ inputs.stage ]]
script: echo integration tests
変数よりも入力を優先
変数が YAML の評価 (たとえばrules
) でのみ使用され、Runner の実行では使用されない場合、代わりに入力を使用することをお勧めします。入力はコンポーネントのコントラクトで明示的に定義され、変数よりも検証されます。
例えば、必須入力が渡されない場合、コンポーネントが使用されるとすぐにエラーが返されます。対照的に、変数が定義されていない場合、その値は空になります。
##
# BAD: you need to configure an environment variable for a custom value that doesn't need
# to be used on the Runner
unit-test:
image: $MY_COMPONENT_X_IMAGE
script: echo unit tests
integration-test:
image: $MY_COMPONENT_X_IMAGE
script: echo integration tests
##
# Usage:
include:
- component: gitlab.com/gitlab-org/ruby-test@1.0
variables:
MY_COMPONENT_X_IMAGE: ruby:3.2
##
# GOOD: we define a customizable value and accept it as input
spec:
inputs:
image:
default: ruby:3.0
---
unit-test:
image: $[[ inputs.image ]]
script: echo unit tests
integration-test:
image: $[[ inputs.image ]]
script: echo integration tests
##
# Usage:
include:
- component: gitlab.com/gitlab-org/ruby-test@1.0
inputs:
image: ruby:3.2
セマンティック・バージョニングの使用
コンポーネントの新しいバージョンをタグ付けしてリリースする際には、セマンティックバージョニングを使用することをお勧めします。
少なくともMAJOR.MINOR
フォーマットを採用することをお勧めします。
例えば2.1
1.0.0
,1.0.0-alpha
,2.1.3
,3.0.0-rc.1
.