マージリクエストパイプライン

GitLab 11.6で導入されました

基本的な設定では、GitLabは変更がブランチにプッシュされるたびにパイプラインを実行します。

マージリクエストの作成時や更新時にのみジョブを実行させたい場合は、マージリクエストパイプラインを使用できます。

UIでは、これらのパイプラインはdetached状態で表示され、それ以外の場合は他のパイプラインと同じように表示されます。

開発者権限を持つユーザは誰でも、マージリクエストパイプラインを実行できます。

Merge request page

Note: パイプラインが成功したときにマージする機能を使用すると、マージリクエストパイプラインが他の通常のパイプラインよりも優先されます。

前提条件

マージリクエストのパイプラインを有効にする。

マージリクエストパイプラインを設定する

マージリクエストパイプラインを設定するには、CI/CD設定ファイルを設定する必要があります。この設定をするためには、いくつかの方法があります。

rulesを使用して、マージリクエストパイプラインを実行する

rulesを使用する場合は、基本的な設定が正しいことを確認するために、workflow:ruleのテンプレートから始めることをお勧めします。ルールの使用方法やカスタマイズ方法については、リンク先で説明しています。

onlyまたはexceptを使用して、マージリクエストパイプラインを実行する

only/exceptは今後も使用可能ですが、次の欠点があります。

この方法を使用する場合、ジョブごとにonly: - merge_requestsを指定しなければなりません。この例では、パイプラインマージリクエストで実行するよう構成されたtestジョブが含まれています。

buildおよびdeployジョブにはonly: - merge_requestsパラメータが指定されていないので、マージリクエストでは実行されません。

build:
  stage: build
  script: ./build
  only:
    - master

test:
  stage: test
  script: ./test
  only:
    - merge_requests

deploy:
  stage: deploy
  script: ./deploy
  only:
    - master

特定のジョブを除外する

only: [merge_requests]パラメータが指定された場合、このパラメータを持つジョブ_のみ_がマージリクエスト時に実行され、それ以外のジョブは実行されません。

しかし、この動作を反転させて、1つか2つを_除いた_すべてのジョブを実行させることができます。

次のようなパイプラインで、ジョブABCを考えてみます。

  • すべてのパイプラインで、常にABを実行するようにします。
  • Cを、マージリクエストの場合だけ実行するようにします。

そのために、.gitlab-ci.ymlファイルを以下のように設定します。

.only-default: &only-default
  only:
    - master
    - merge_requests
    - tags

A:
  <<: *only-default
  script:
    - ...

B:
  <<: *only-default
  script:
    - ...

C:
  script:
    - ...
  only:
    - merge_requests

上記の設定では、以下のように動作します。

  • ABは、すべてのケースで実行するためのonly:ルールが指定されているので、常に実行されます。
  • Cは、マージリクエストに対してのみ実行するように指定されているため、マージリクエストのパイプライン以外では実行されません。

この方法により、すべてのジョブにonly:ルールを追加することで常に実行させる必要がなくなります。このフォーマットを使用してレビューアプリを設定することで、リソースの節約に役立ちます。

特定のブランチを除外する

マージリクエストパイプラインでonly/exceptを使用する場合は特別な扱いが必要です。通常のブランチ参照(例えばrefs/heads/my-feature-branch)とは異なり、マージリクエストの参照はrefs/merge-requests/:id/headのような特別なGit参照を使用します。このため、以下の設定では期待通りには動作しません

# Does not exclude a branch named "docs-my-fix"!
test:
  only: [merge_requests]
  except: [/^docs-/]

代わりに、定義済みの環境変数$CI_COMMIT_REF_NAMEonly:variablesと組み合わせて使用することで、この動作を実現できます。

test:
  only: [merge_requests]
  except:
    variables:
      - $CI_COMMIT_REF_NAME =~ /^docs-/

マージ結果パイプライン

マージ結果パイプラインに関するドキュメントを参照してください。

マージトレイン

マージトレインのドキュメントを参照してください。

フォークされたプロジェクトからのマージリクエストに関する重要な注意事項

現在の動作は変更される可能性があることに注意してください。通常のコントリビューションフローでは、外部コントリビューターは以下の手順に従います。

  1. 親プロジェクトをフォークします。
  2. フォークされたプロジェクトから、親プロジェクトのmasterブランチをターゲットとするマージリクエストを作成します。
  3. マージリクエストに対してパイプラインが実行されます。
  4. 親プロジェクトの管理者がパイプラインの結果をチェックし、最新のパイプラインが成功していればターゲットブランチにマージします。

現在、これらのパイプラインは親プロジェクトではなく、フォークされたプロジェクトで作成されています。これは、パイプラインの結果が完全には信頼できないことを意味します。外部のコントリビューターがフォークしたプロジェクトのGitLab Runnerを使用するため、パイプラインの結果を技術的には偽装できるためです。

GitLabが、これらのパイプラインを親プロジェクトで作成することを許可しない理由はいくつかありますが、最大の理由のひとつはセキュリティ上の懸念です。外部のユーザーが.gitlab-ci.ymlを変更することで、親プロジェクトからマスクした変数を盗み出せる可能性があります。この変数は、ある種のクレデンシャル情報の可能性があります。これは起きてはならないことです。

私たちは、フォークされたプロジェクトから作成されたマージリクエストパイプラインを実行する安全な解決策を議論しています。詳しくはパーミッション拡張に関する課題を参照してください。

追加された定義済み変数

マージリクエストパイプラインを使用することで、GitLabはパイプラインジョブに追加の定義済み変数を公開します。これらの変数には関連するマージリクエストの情報が含まれているので、GitLabのマージリクエストAPIとジョブを統合するのに便利です。

利用可能な変数一覧は、リファレンスシートに記載されています。 変数名は、CI_MERGE_REQUEST_というプリフィックスで始まります。

トラブルシューティング

マージリクエストにプッシュすると2つのパイプラインが作成されます

rulesを使用しているときにパイプラインが重複している場合は、ruelsonly/exceptの間の重要な違いを見てみましょう。

only/exceptを使用しているときに2つのパイプラインが表示されている場合は、上記のonly/exceptの使用に関する注意事項を参照してください(または、rulesへの移行を検討してください)。

無効なCI設定ファイルをプッシュすると2つのパイプラインが作成されます

無効なCI設定ファイルを持つブランチをプッシュすると、2つの失敗したパイプラインが作成されます。1つは失敗したマージリクエストパイプライン、もう1つは失敗したブランチパイプラインですが、どちらも同じ無効なCI設定によって引き起こされます。

まれに、パイプラインが重複して作成されることがあります。

詳しくはこの課題をご覧ください。