CI設定内部
ワークフロールール
GitLab プロジェクトのパイプラインは、GitLab CI/CD のworkflow:rules キーワード 機能を使って作成します。
パイプラインは常に以下のシナリオのために作成されます:
- 
mainブランチ(スケジュール、プッシュ、マージなど)。
- マージリクエスト
- タグ
- 安定、auto-deploy、セキュリティブランチ。
パイプラインの作成は、以下の CI/CD 変数の影響も受けます:
- 
$FORCE_GITLAB_CIが設定されている場合、パイプラインが作成されます。使用は推奨されません。$FORCE_GITLAB_CIを参照してください。
- 
$GITLAB_INTERNALが設定されていない場合、パイプラインは作成されません。
それ以外の場合、パイプラインは作成されません (たとえば、MR のないブランチをプッシュする場合など)。
これらのワークフロールールのソースオブトゥルースは、.gitlab-ci.yml で定義されています。
避ける$FORCE_GITLAB_CI
パイプラインは非常に複雑で、どのようなパイプラインをトリガーしたいのかを明確に理解する必要があります。どのジョブを実行すべきで、どのジョブを実行すべきでないかを知る必要があります。
パイプラインを強制的にトリガーするために$FORCE_GITLAB_CI を使用した場合、どのようなパイプラインなのかがよくわかりません。その結果、必要なジョブが実行されなかったり、どうでもいいジョブがたくさん実行されたりします。
より詳細な背景については、以下を参照してください:予期せぬ実行を避けるために、包括的な変更は避けましょう
以下は、私たちが今現在これを使用している場所のリストです。$FORCE_GITLAB_CI.
デフォルトの画像
デフォルトの画像は.gitlab-ci.yml で定義されています。
Ruby、Go、Git、Git LFS、Chrome、Node、Yarn、PostgreSQL、Graphics Magickが含まれています。
パイプラインで使用されるイメージはgitlab-org/gitlab-build-images プロジェクトで設定され、冗長性のためにgitlab/gitlab-build-images にプッシュミラーされています。
現在のビルドイメージのバージョンは、“Used by GitLab section “にあります。
デフォルト変数
定義済みのCI/CD変数に加えて、各パイプラインには.gitlab-ci.ymlで定義されたデフォルト変数が含まれています。
ステージ
現在のステージは以下の通りです:
- 
sync:このステージはgitlab-org/gitlabからgitlab-org/gitlab-fossへの変更の同期に使用されます。
- 
prepare:このステージには、後続ステージのジョブが必要とするアーティファクトを準備するジョブが含まれます。
- 
build-images:このステージには、後続ステージやダウンストリームパイプラインのジョブが必要とするDockerイメージを準備するジョブが含まれます。
- 
fixtures:このステージには、フロントエンドのテストに必要なフィクスチャを準備するジョブが含まれます。
- 
lint:このステージはリントと静的解析のジョブを含みます。
- 
test:このステージにはほとんどのテストとDB/マイグレーションジョブが含まれます。
- 
post-test:このステージには、レポーターを作成したり、testステージのジョブからデータを収集したりするジョブが含まれます (カバレッジ、Knapsack メタデータなど)。
- 
review:このステージには、CNG イメージをビルドし、デプロイし、レビューアプリに対してエンドツーエンドのテストを実行するジョブが含まれます (詳細はレビューアプリを参照してください)。Docs レビューアプリのジョブも含まれます。
- 
qa:このステージには、ステージreviewでデプロイされたレビューアプリに対して QA タスクを実行するジョブが含まれます。
- 
post-qa:このステージには、レポートを作成したり、qaステージのジョブからデータを収集したりするジョブが含まれます (レビューアプリのパフォーマンスレポートなど)。
- 
pages:このステージには、様々なレポートをGitLab Pagesとしてデプロイするジョブが含まれます(例えば、coverage-ruby、webpack-report(https://gitlab-org.gitlab.io/gitlab/webpack-report/で見つかりましたが、デプロイにイシューがあります)。
- 
notify:このステージには、様々な失敗をSlackに通知するジョブが含まれます。
依存関係プロキシ
ジョブの中にはDocker Hubのイメージを使用しているものがあります。この場合、依存プロキシからイメージを取得するために、イメージパスのプレフィックスとして${GITLAB_DEPENDENCY_PROXY_ADDRESS} を使用します。デフォルトでは、この変数は${GITLAB_DEPENDENCY_PROXY}の値から設定されます。
${GITLAB_DEPENDENCY_PROXY} はgitlab-org で${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/として定義されているグループ CI/CD 変数です。と定義されています:
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine:edge
gitlab-org グループ内のプロジェクトは依存プロキシからプルしますが、他の個人ネームスペースやグループに存在するフォークは、${GITLAB_DEPENDENCY_PROXY} が定義されていない限りDocker Hubにフォールバックします。
プロジェクトアクセストークンユーザーによってパイプラインが開始された場合の回避策
パイプラインがプロジェクトアクセストークンユーザー(例えば、メインプロジェクトで使用されるGitalyバージョンを自動的に更新するrelease-tools approver bot ユーザー)によって開始されると、依存プロキシにアクセスできず、Preparing the "docker+machine" executor ステップでジョブが失敗します。これを回避するために、${GITLAB_DEPENDENCY_PROXY_ADDRESS} 変数をオーバーライドする特別なワークフロールールを用意し、依存プロキシが使用されないようにしています:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $GITLAB_USER_LOGIN =~ /project_\d+_bot\d*/'
  variables:
    GITLAB_DEPENDENCY_PROXY_ADDRESS: ""
.gitlab-ci.yml 変数よりも優先順位が高いため、${GITLAB_DEPENDENCY_PROXY} 変数を直接上書きすることはありません。一般的なジョブ定義
ほとんどのジョブは、.gitlab/ci/global.gitlab-ci.yml で定義された、単一の設定キーワードにスコープされたいくつかのCI定義から拡張されます。
| ジョブの定義 | 説明 | 
|---|---|
| .default-retry | unknown_failure,api_failure,runner_system_failure,job_execution_timeout,stuck_or_timeout_failureのときにジョブの再試行を許可します。 | 
| .default-before_script | データベースの実行が必要なRuby/Railsタスク (たとえばテスト) に適したデフォルトの before_script定義をジョブで使用できるようにします。 | 
| .setup-test-env-cache | ジョブに、後続のRuby/Railsタスクのテスト環境を設定するのに適したデフォルトの cache定義を使えるようにします。 | 
| .ruby-cache | Ruby タスクに適したデフォルトの cache定義をジョブに使わせます。 | 
| .static-analysis-cache | ジョブが静的解析タスクに適したデフォルトの cache定義を使えるようにします。 | 
| .ruby-gems-coverage-cache | ジョブがカバレッジタスクに適したデフォルトの cache定義を使用できるようにします。 | 
| .qa-cache | ジョブがQAタスクに適したデフォルトの cache定義を使用できるようにします。 | 
| .yarn-cache | yarn installを行うフロントエンドジョブに適したデフォルトのcache定義をジョブに使用できるようにします。 | 
| .assets-compile-cache | アセットをコンパイルするフロントエンドジョブに適したデフォルトの cache定義をジョブが使用できるようにします。 | 
| .use-pg13 | ジョブが postgres13、redis、およびredisclusterサービスを使用できるようにします (サービスの特定のバージョンについては.gitlab/ci/global.gitlab-ci.ymlを参照してください)。 | 
| .use-pg13-ee | .use-pg13と同じですが、elasticsearchサービスも使用します (サービスの具体的なバージョンは.gitlab/ci/global.gitlab-ci.ymlを参照)。 | 
| .use-pg14 | ジョブが postgres14、redis、およびredisclusterサービスを使用できるようにします (サービスの具体的なバージョンは.gitlab/ci/global.gitlab-ci.ymlを参照)。 | 
| .use-pg14-ee | .use-pg14と同じですが、elasticsearchサービスも使用します (サービスの具体的なバージョンは.gitlab/ci/global.gitlab-ci.ymlを参照)。 | 
| .use-pg15 | ジョブが postgres15、redis、およびredisclusterサービスを使用できるようにします (サービスの具体的なバージョンは.gitlab/ci/global.gitlab-ci.ymlを参照)。 | 
| .use-pg15-ee | .use-pg15と同じですが、elasticsearchサービスも使用します (サービスの具体的なバージョンは.gitlab/ci/global.gitlab-ci.ymlを参照)。 | 
| .use-kaniko | ジョブが kanikoツールを使って Docker イメージをビルドできるようにします。 | 
| .as-if-foss | FOSS_ONLY='1'CI/CD変数を設定してFOSSプロジェクトをシミュレートします。 | 
| .use-docker-in-docker | ジョブがDockerでDockerを使えるようにします。詳細はCI/CD設定についてのハンドブックを参照してください。 | 
rules,if: 条件とchanges: パターン
rules キーワード を多用しています。
すべてのrules 定義はrules.gitlab-ci.ymlで定義され、extends を介して個々のジョブに含まれます。
rules 定義はif: 条件とchanges: パターンで Composer されます。これらはrules.gitlab-ci.yml でも定義され、YAML アンカーを介してrules 定義に含まれます。
if: 条件
| if:条件 | 説明 | 備考 | 
|---|---|---|
| if-not-canonical-namespace | プロジェクトが正規 ( gitlab-org/とgitlab-cn/) またはセキュリティ (gitlab-org/security) 名前空間にない場合にマッチします。 | フォーク用のジョブを作成する場合 ( when: on_successまたはwhen: manualを使用)、またはフォーク用のジョブを作成しない場合 (when: neverを使用) に使用します。 | 
| if-not-ee | プロジェクトがEEでない場合(つまり、プロジェクト名が gitlabまたはgitlab-eeでない場合)にマッチします。 | FOSSプロジェクトでのみジョブを作成する場合( when: on_successまたはwhen: manualを使用)、プロジェクトがEEの場合はジョブを作成しない場合(when: neverを使用)に使用します。 | 
| if-not-foss | プロジェクトがFOSSでない場合(つまり、プロジェクト名が gitlab-foss、gitlab-ce、gitlabhqでない場合)にマッチします。 | EEプロジェクトでのみジョブを作成する場合( when: on_successまたはwhen: manualを使用)、プロジェクトがFOSSの場合はジョブを作成しない場合(when: neverを使用)に使用します。 | 
| if-default-refs | パイプラインが master、main、/^[\d-]+-stable(-ee)?$/(安定ブランチ)、/^\d+-\d+-auto-deploy-\d+$/(自動デプロイブランチ)、/^security\//(セキュリティブランチ)、マージリクエスト、タグの場合にマッチします。 | このデフォルト設定のブランチでは、ジョブは作成されないことに注意してください。 | 
| if-master-refs | 現在のブランチが masterまたはmainの場合にマッチします。 | |
| if-master-push | 現在のブランチが masterまたはmainで、パイプラインソースがpushの場合にマッチします。 | |
| if-master-schedule-maintenance | 現在のブランチが masterまたはmainで、パイプラインが 2 時間ごとのスケジュールで実行されている場合にマッチします。 | |
| if-master-schedule-nightly | 現在のブランチが masterまたはmainで、パイプラインが夜間スケジュールで実行されている場合にマッチします。 | |
| if-auto-deploy-branches | 現在のブランチが自動デプロイされている場合にマッチします。 | |
| if-master-or-tag | パイプラインが masterブランチかmainブランチ、またはタグのものである場合にマッチします。 | |
| if-merge-request | パイプラインがマージリクエストの場合にマッチします。 | |
| if-merge-request-title-as-if-foss | パイプラインがマージリクエストで、MR のラベルが ~"pipeline:run-as-if-foss" の場合にマッチします。 | |
| if-merge-request-title-update-caches | パイプラインがマージリクエストで、MR のラベルが ~"pipeline:update-cache" の場合にマッチします。 | |
| if-merge-request-labels-run-all-rspec | パイプラインがマージリクエストで、MR のラベルが ~"pipeline:run-all-rspec" の場合に一致します。 | |
| if-security-merge-request | パイプラインがセキュリティマージリクエストの場合にマッチします。 | |
| if-security-schedule | パイプラインがセキュリティスケジュールパイプラインの場合にマッチします。 | |
| if-nightly-master-schedule | パイプラインが $NIGHTLYが設定されたmasterスケジュールパイプラインの場合にマッチします。 | |
| if-dot-com-gitlab-org-schedule | GitLab.com の gitlab-orgグループのスケジュールされたパイプラインにジョブの作成を制限します。 | |
| if-dot-com-gitlab-org-master | GitLab.comの gitlab-orgグループに対して、ジョブの作成をmasterまたはmainブランチに制限します。 | |
| if-dot-com-gitlab-org-merge-request | GitLab.com の gitlab-orgグループに対して、ジョブの作成をマージリクエストに制限します。 | |
| if-dot-com-gitlab-org-and-security-tag | GitLab.com の gitlab-orgとgitlab-org/securityグループに対して、ジョブの作成をタグに制限します。 | |
| if-dot-com-gitlab-org-and-security-merge-request | GitLab.com の gitlab-orgとgitlab-org/securityグループに対して、ジョブの作成をマージリクエストに制限します。 | |
| if-dot-com-gitlab-org-and-security-tag | GitLab.com の gitlab-orgとgitlab-org/securityグループに対して、ジョブ作成をタグに制限。 | |
| if-dot-com-ee-schedule | GitLab.com の gitlab-org/gitlabプロジェクトのスケジュールされたパイプラインにジョブを制限します。 | 
changes: パターン
| changes:パターン | 説明 | 
|---|---|
| ci-patterns | CI設定関連の変更にのみジョブを作成します。 | 
| ci-build-images-patterns | build-imagesステージに関連する CI 設定関連の変更にのみジョブを作成します。 | 
| ci-review-patterns | reviewステージに関連する CI 設定関連の変更にのみジョブを作成します。 | 
| ci-qa-patterns | qaステージに関連する CI 設定関連の変更にのみジョブを作成します。 | 
| yaml-lint-patterns | YAML関連の変更に対してのみジョブを作成します。 | 
| docs-patterns | docs関連の変更にのみジョブを作成します。 | 
| frontend-dependency-patterns | フロントエンドの依存関係が更新されたときのみジョブを作成します (たとえば、 package.json、yarn.lock)。 | 
| frontend-patterns-for-as-if-foss | FOSSに影響を与えるフロントエンド関連の変更に対してのみジョブを作成します。 | 
| backend-patterns | バックエンド関連の変更にのみジョブを作成します。 | 
| db-patterns | DB関連の変更にのみジョブを作成します。 | 
| backstage-patterns | バックステージ関連の変更 (つまり、Danger、フィクスチャ、RuboCop、specs) に対してのみジョブを作成します。 | 
| code-patterns | コード関連の変更にのみジョブを作成します。 | 
| qa-patterns | QA関連の変更にのみジョブを作成してください。 | 
| code-backstage-patterns | code-patternsとbackstage-patternsの組み合わせ。 | 
| code-qa-patterns | code-patternsとqa-patternsの組み合わせ。 | 
| code-backstage-qa-patterns | code-patterns、backstage-patterns、qa-patternsの組み合わせ。 | 
| static-analysis-patterns | ジョブの作成は、Static Analytics設定関連の変更に限定してください。 | 
ベストプラクティス
extends: 、<<: *xyz (YAMLアンカー)、あるいは!reference
キーポイント
- 
ハッシュを拡張する必要がある場合はextends
- 
配列を拡張する必要がある場合は、!referenceを使うか、最後の手段としてYAML anchorsを使う必要があります。
- より複雑な場合 (たとえば、配列の内部でハッシュを拡張する、ハッシュの内部で配列を拡張する…) には、!referenceまたはYAML anchors
extends とYAML anchors は何ができますか?
extends
- ハッシュのディープマージ
- 配列に対するマージはありません。上書きします。
YAML アンカー
- ハッシュのディープマージはできませんが、ハッシュを拡張するために使用することはできます (以下の例を参照ください)。
- 配列のマージは行いませんが、配列を拡張するために使用することはできます (以下の例を参照ください)。
すばらしい例
この例では、複雑な YAML データ構造を!reference とYAML anchors で拡張する方法を示します:
.strict-ee-only-rules:
  # `rules` is an array of hashes
  rules:
    - if: '$CI_PROJECT_NAME !~ /^gitlab(-ee)?$/ '
      when: never
# `if-security-merge-request` is a hash
.if-security-merge-request: &if-security-merge-request
  if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security"'
# `code-qa-patterns` is an array
.code-qa-patterns: &code-qa-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
.qa:rules:as-if-foss:
  rules:
    # We extend the `rules` array with an array of hashes directly
    - !reference [".strict-ee-only-rules", rules]
    # We extend a single array entry with a hash
    - <<: *if-security-merge-request
      # `changes` is an array, so we pass it an entire array
      changes: *code-qa-patterns
qa:selectors-as-if-foss:
  # We include the rules from .qa:rules:as-if-foss in this job
  extends:
    - .qa:rules:as-if-foss
.fast-no-clone-job ジョブの拡張
正規プロジェクトのブランチをダウンロードするのに20秒から30秒かかります。
GitLab API を使ってダウンロードできる限られた数のファイルしか必要としないジョブもあります。
以下のパターンをジョブに追加することで、ジョブgit clone/git fetch をスキップすることができます。
シナリオ 1: ジョブにbefore_script が定義されていない場合。
これはジョブが拡張する親セクションにもあてはまります。
.fast-no-clone-job を拡張するだけです:
を拡張するだけです:
  # Note: No `extends:` is present in the job
  a-job:
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "No need for a git clone!"
After:
  # Note: No `extends:` is present in the job
  a-job:
    extends:
      - .fast-no-clone-job
    variables:
      FILES_TO_DOWNLOAD: >
        scripts/rspec_helpers.sh
        scripts/slack
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "No need for a git clone!"
シナリオ2:before_script ブロックがジョブ(もしくはジョブが拡張するジョブ)内ですでに定義されている場合
このシナリオでは、あなたは
- 最初のシナリオと同様に、.fast-no-clone-jobを拡張します(これにより、FILES_TO_DOWNLOAD変数が他の変数とマージされます)。
- 
.fast-no-clone-jobのbefore_scriptセクションが、このジョブで使用するbefore_scriptで参照されていることを確認してください。
を拡張するだけです:
  .base-job:
    before_script:
      echo "Hello from .base-job"
  a-job:
    extends:
      - .base-job
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "No need for a git clone!"
After:
  .base-job:
    before_script:
      echo "Hello from .base-job"
  a-job:
    extends:
      - .base-job
      - .fast-no-clone-job
    variables:
      FILES_TO_DOWNLOAD: >
        scripts/rspec_helpers.sh
        scripts/slack
    before_script:
      - !reference [".fast-no-clone-job", before_script]
      - !reference [".base-job", before_script]
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "No need for a git clone!"
注意点
- このパターンは、リポジトリへのアクセスをgitに依存しているスクリプトでは動作しません。なぜなら、クローンやフェッチなしではリポジトリを持っていないからです。
- このパターンを使用するジョブはcurlを利用できる必要があります。
- ジョブ内でbundle installを実行する必要がある場合 (BUNDLE_ONLYを使用する場合でも)、必要です:- 
gitlab-org/gitlabプロジェクトに格納されている gems をダウンロードします。- そのためにはdownload_local_gemsshell コマンドを使用します。
 
- そのためには
- 
Gemfile、Gemfile.lock、Gemfile.checksum(該当する場合)を含めます。
 
- 
このパターンはどこで使われていますか?
- 今のところ、私たちはこのパターンを以下のようなジョブに使っており、これらは非公開リポジトリをブロックしません:
- 
review-build-cng-envのためです:- GITALY_SERVER_VERSION
- GITLAB_ELASTICSEARCH_INDEXER_VERSION
- GITLAB_KAS_VERSION
- GITLAB_METRICS_EXPORTER_VERSION
- GITLAB_PAGES_VERSION
- GITLAB_SHELL_VERSION
- scripts/trigger-build.rb
- VERSION
 
- 
review-deployのためです:- GITALY_SERVER_VERSION
- GITLAB_SHELL_VERSION
- scripts/review_apps/review-apps.sh
- scripts/review_apps/seed-dast-test-data.sh
- VERSION
 
- 
rspec:coverageのためです:- config/bundler_setup.rb
- Gemfile
- Gemfile.checksum
- Gemfile.lock
- scripts/merge-simplecov
- spec/simplecov_env_core.rb
- spec/simplecov_env.rb
 
 
- 
さらに、このパターンが使用されると、scripts/utils.sh が常にAPIからダウンロードされます(このファイルには、.fast-no-clone-job のコードが含まれています)。
ランナーのタグ
GitLab.com では、非特権ランナーと特権ランナーの両方が利用できます。gitlab-org グループのプロジェクトとそのフォークでは、以下のタグのうち一つだけをジョブに追加してください:
- 
gitlab-org:ジョブは特権ランナーと非特権ランナーをランダムに使用します。
- 
gitlab-org-docker:ジョブは特権ランナーを使用する必要があります。Docker-in-Dockerのサポートが必要な場合は、gitlab-org-dockergitlab-orgの代わりにgitlab-org-docker使用してgitlab-org-dockerください。
gitlab-org-docker タグは、上記の.use-docker-in-docker ジョブ定義によって追加されます。
フォークとの互換性を確保するために、gitlab-org とgitlab-org-docker の両方を同時に使用することは避けてください。gitlab-org とgitlab-org-docker の両方のタグを持つインスタンスランナーはいません。gitlab-org プロジェクトのフォークの場合、マッチする Runner がないため、両方のタグが指定されると、ジョブはスタックします。
詳しくはGitLab Repositories handbook ページをご覧ください。
