Prowの真骨頂であるTideでPRの自動マージを導入する。


前回のエントリ「ProwではじめるChatOps on GitHub。」からProwを完全理解した!と言ってはいけない。Prowの真骨頂はTideにあると思う。

Enable kustomize in kubectl by Liujingfang1 · Pull Request #70875 · kubernetes/kubernetes · GitHub

上記のProwが有効になったPRのフローの最後を見てほしい。BotアカウントがPRをマージしているのだ。この仕組みはProwのTideが実現してくれる。

Tideは一定の条件を満たした上でPRをマージしてくれる。マージを行うアカウントはProwに設定したGitHubのアクセストークンになるのでBotアカウントになる。一定の条件は下記のようなyamlでセットアップを行う。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
tide:
  merge_method:
    kubeflow/community: squash

  target_url: https://prow.k8s.io/tide.html

  queries:
  - repos:
    - kubeflow/community
    - kubeflow/examples
    labels:
    - lgtm
    - approved
    missingLabels:
    - do-not-merge
    - do-not-merge/hold
    - do-not-merge/work-in-progress
    - needs-ok-to-test
    - needs-rebase

上記のqueriesに含まれるreposやlabelsの条件を満たせばTideがPRをマージしてくれる。

このエントリでは

このエントリでは、Tideのセットアップの方法とPRフローに必要そうなProwプラグインのセットアップ方法をまとめていく。

Triggerプラグインを有効にする

Triggerプラグインは /ok-to-test, /test xxxx, /retestなどのキーワード入力からProwJobsを実行するプラグインである。(Prow Plugin Catalogのtriggerを参照)

Triggerプラグインのセットアップ手順をまとめていく。次のようなconfig.yamlを用意する。

1
2
3
4
5
6
7
8
9
presubmits:
  soushin/bazel-multiprojects:
  - name: unit-test
    always_run: false
    skip_report: false
    spec:
      containers:
      - image: alpine
        command: ["/bin/printenv"]

上記のコンフィグレーションにより /test unit-testというキーワードが有効になった。Prowはキーワードとレポジトリ(soushin/bazel-multiprojects)がマッチすればPodを起動してalpineイメージから /bin/printenvのコマンドを実行する。e2eテストが実行できるコンテナイメージを用意すればGitHubのコメントからe2eテストが実行できるようになる。ここらへんはプロジェクトに応じてしっかりとした準備と検討が必要なところだ。

always_runやskip_reportはプロジェクトに応じてセットアップする。詳細はjobs.mdにまとまっているので参照してほしい。

上記のconfig.yamlを用意したらConfigMapに反映する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
(test-infra) $ cat config.yaml
presubmits:
  soushin/bazel-multiprojects:
  - name: unit-tests
    always_run: false
    skip_report: false
    spec:
      containers:
      - image: alpine
        command: ["/bin/printenv"]
(test-infra) $ kubectl create configmap config \
  --from-file=config.yaml=config.yaml --dry-run -o yaml \
  | kubectl replace configmap config -f -

またplugin.yamlにはTriggerプラグインを有効にした上でConfigMapに反映する。

1
2
3
4
5
6
7
8
(test-infra) $ cat plugins.yaml
plugins:
  soushin/bazel-multiprojects:
  - size
  - trigger
(test-infra) $ kubectl create configmap plugins \
  --from-file=plugins.yaml=plugins.yaml --dry-run -o yaml  \
  | kubectl replace configmap plugins -f -

これでProwのhookポッドにTriggerプラグインとTrigger対象のProwJobs(unit-tests)が有効になった。

Triggerを実行する

任意のPRを作成して /test unit-testsを入力した後にCheckにProwJobsが加わっている。

もしProwJobs(unit-tests)がエラーになればBotアカウントがお知らせしてくれる。

エラーになればコードを修正して /retestを入力して全てのテストを実行する。Prowは登録されているProwJobsを実行して結果をGitHubに返す。

Triggerの流れを整理

Triggerプラグインを有効にしたProwは次のような流れになる。

上記のChatOpsのフローを交えてPRマージまで進める。

LGTM, Holdプラグインを有効にする

Tideを有効にする前にLGTM, Holdプラグインを確認していきたい。(Prow Plugin Catalogのlgtm, holdを参照)

このプラグインは/lgtm,/holdのキーワードを入力するとそれぞれlgtm,do-not-merge/holdのラベルを付与してくれるプラグインである。これを有効にしてTideの設定値であるlabelと組み合わせる。

次のようにlgtmholdを有効にしてConfigMapに反映する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(test-infra) $ cat plugins.yaml
plugins:
  soushin/bazel-multiprojects:
  - size
  - trigger
  - lgtm
  - hold
(test-infra) $ kubectl create configmap plugins \
  --from-file=plugins.yaml=plugins.yaml --dry-run -o yaml  \
  | kubectl replace configmap plugins -f -

/hold/hold canceldo-not-merge/holdラベルの付与と取外しを行い/lgtmlgtmラベルを付与している。

※ 1人でエントリをまとめていたので/lgtm/hold cancelをBotアカウントが行ってしまっているが本来はコントリビューターが行うことになる。

Tideを有効にする

PRマージを行うまでに必要なテスト(Trigger)とラベル付与(LGTM, Hold)を有効にするプラグインをまとめきた。これでTideを有効にしたPRフローの準備ができた。

Tideはconfig.yamlに次のようなコンフィグレーションを追加して有効にした。

1
2
3
4
5
6
7
8
tide:
  queries:
  - repos:
    - soushin/bazel-multiprojects
    labels:
    - lgtm
    missingLabels:
    - do-not-merge/hold

PRマージの対象のレポジトリと必要なラベルと必要ないラベルの設定が有効になっている。

これまでと同様にconfig.yamlをConfigMapに反映する。

1
2
3
(test-infra) $ kubectl create configmap config \
  --from-file=config.yaml=config.yaml --dry-run -o yaml \
  | kubectl replace configmap config -f -

Tideが有効になったPRフローを確認する

Tideが有効になったPRにはChecksにtideが追加されている。

lgtmのラベルが必要なのでラベルを付与するとProwが自動でPRをマージしくれる。

まとめ