Be an Engineer.

社会人からWEBエンジニアになった人間の備忘録的勉強記録

bulldozerを導入する

突然ですが、bulldozerが本当に便利なので、その紹介と導入手順について書いていきます。

github.com

bulldozerとは

bulldozerはパランティアテクノロジーズが開発したもので、GitHubで使ういわゆるauto-merge botの実装です。bulldozerの機能をおおまかにピックアップすると以下のような機能を持ちます。

  1. ステータスチェックが通過したpull requestを自動的にmergeする
  2. pull requestを自動的にベースブランチの最新状態に更新してくれる

bulldozerは GitHub App として動くアプリケーションですが、GitHub Marketplace に公開されているものではないので自前でプライベートなGitHub Appとしてホストする必要があります。GitHub Appとして動くということはつまりpull requestにおける各種アクティビティをhookを受け取り観測できる状態になります。この動きを踏まえて、↑で言っていた動作について少し詳しく説明します。

1. ステータスチェックが通過したpull requestを自動的にmergeする

以下の条件にクリアしていると、bulldozerは自動でそのpull requestのベースブランチへmergeをします。

  • Required Status Checkに全てpassしている
  • 設定ファイル bulldozer.yml に指定したラベル or コメントがそのpull requestに付けられている

具体的に言うと、私の場合はリポジトリの設定的に以下を全て満たす状況になっているとbulldozerが自動的にmergeしてくれます。

  1. pull requestにapproveが付いていること
  2. testやlint系のCIが全て通っていること
  3. pull requestに ready-to-merge ラベルが付いていること
  4. pull requestに do-not-merge ラベルが付いていないこと(do-not-mergeをmergeしてはいけないラベルに設定している)

2. pull requestを自動的にベースブランチの最新状態に更新してくれる

Branch protectionで「Require branches to be up to date before merging」の設定を有効にしている場合は、pull requestがベースブランチの最新のcommitを履歴として持っていないと、status checkに落ちてしまいます。そこでbulldozerは存在する全てのpull requestを対象に、自動でそれぞれ最新のベースブランチをheadブランチにmergeし、自動的にpull requestを最新の状態を保ってくれます。

~~~

これらの機能があることで、以下のような嬉しさが生まれることになります。

bulldozer導入前

レビューが完了してmerge可能だけどもCIが完了してなくてmergeできず、後でCIが全部終わってるか確認しに戻ってきてmergeする(あるいはCIが終わってなくてまた後で確認しに戻ってきて...を繰り返すことも) => CI待ちで手間が増える

※ 厳密にはCIの完了を待たなくてもup-to-dateの確認はできる

bulldozer導入後

レビューを終えてapproveな状態だったら特定のラベルorコメントを付けるだけでCIが完了し次第自動的にmergeされる、という状況が作れる。 => CIを待つ必要がなくなる

更に自動的に目的の環境にデプロイされるフローが整備できていれば、レビュー完了時点からその変更が対象の環境に反映されるまで手動のオペレーションが無くなり自動化されたCI/CDが実現できます。

(個人的に特にbulldozerがあって嬉しいと思うのはDependabotRenovateが複数のpull requestを短期間で作成したときです。それらのpull requestたちにapprove + ラベルを付けていくだけで放っておいたら全てmergeされていたという状態にできますし、auto-mergeと違ってちゃんと目を通したいところには通せる作業フローにできる点でメリットを感じます。)

bulldozer導入手順

こうした便利機能を持つbulldozerですが、上にも書いた通りbulldozerは自前でプライベートなGitHub Appとしてアプリケーションをホストする必要があります(個人的にはここだけが惜しいポイントだなと)。そこで実際に導入する手順を説明していきます。※ bulldozerのREADMEにわりとしっかりめに書いてくれているのでこちらを見るのが基本です

カンタンに作業手順の項目を掻い摘んだ流れだと以下のようなものになります。

  1. bulldozerのDockerイメージを使ってサーバーを立てる
  2. GitHub Appとしてインストールする

1. bulldozerのDockerイメージを使ってサーバーを立てる

ありがたいことにbulldozerはDockerイメージを公開してくれているので、このDockerイメージを使って任意の方法でサーバーをたてます。どこにどういう形でサーバーを立てようとも、最終的にGitHubからwebhookのターゲットとして到達可能なURLが得られているとOKです。(筆者の場合はGCPのCloud Runを使って立てました。)

設定ファイルのパスに注意

Dockerイメージを使ってサーバを立てる際の注意点としては、bulldozerの設定ファイルは /secrets/bulldozer.yml に置く必要があることでしょうか。

この公式イメージのDockerfileを見てみると、

CMD ["server", "--config", "/secrets/bulldozer.yml"]

bulldozer/Dockerfile at 625d3f552cdac6ea32bef52fc17fb8ea358393d2 · palantir/bulldozer · GitHub

という起動コマンドが使われていることから、コンテナとして立てる際は以下のどちらかの方法で起動時に設定が反映されるようにしましょう。

  1. 予め /secrets/bulldozer.yml に置いてビルドしたDockerイメージを使う
  2. コンテナ起動時に設定ファイルを /secrets/bulldozer.yml にマウントして起動する

そもそも設定ファイル?

bulldozerの設定ファイルは以下に説明付きの例があり、この設定がデフォルトの設定として使われます。
bulldozer/bulldozer.example.yml at 625d3f552cdac6ea32bef52fc17fb8ea358393d2 · palantir/bulldozer · GitHub

わりとしっかりめにコメントを書いてくれているので読めばわかるものだと思います。この設定ファイルでトリガーとなるラベルの値やコメントの値を定義することができます。
色々環境に依るところがありますが、設定例として筆者のものを部分的に載せておきます。

server:
  address: "0.0.0.0"
  port: 8080
logging:
  text: false
  level: info
cache:
  max_size: 100MB
github:
  web_url: "https://github.com"
  v3_api_url: "https://api.github.com"
options:
  configuration_path: .bulldozer.yml
  app_name: bulldozer
  default_repository_config:
  ...

必要な環境変数

bulldozerサーバーには以下の3つを環境変数として与える必要があります。
1, 3に関してはGitHub Appとして作成してから取得できる値であるため、ひとまず2の GITHUB_APP_WEBHOOK_SECRET となる値だけ適当に作っておきましょう。

  1. GITHUB_APP_INTEGRATION_IDGitHub App ID)
  2. GITHUB_APP_WEBHOOK_SECRET(Webhook用シークレットとして使われる任意のランダムな文字列)
  3. GITHUB_APP_PRIVATE_KEYGitHub App がアクセストークンを取得するのに必要な秘密鍵

2. GitHub Appとしてインストールする

作成したサーバーを使って、GitHub Appとしてインストールしていきます。

GitHubの公式ドキュメントとしては以下のあたりです。
Installing GitHub Apps - GitHub Docs

Organizationあるいは個人ユーザでも同じ Developer settings セクションにある「GitHub Apps」ページに行くと、「New GitHub App」というボタンがあるのでそこから作成を開始します。

適当に設定していきます。

↑の「Webhook URL」の <your-bulldozer-domain> 等は作成したサーバ環境に応じた値で書き換えてください。
また「Webhook secret」は先ほど作成しておいた値をここで使います。

「permissions」と「Subscribe to events」に関してはREADMEに記載されている通りに設定します。
https://github.com/palantir/bulldozer/tree/625d3f552cdac6ea32bef52fc17fb8ea358393d2#github-app-configuration

これで「Create GitHub App」ボタンを押して作成完了です。

環境変数を更新する

上記で2つの環境変数 GITHUB_APP_INTEGRATION_IDGITHUB_APP_PRIVATE_KEY が設定できていなかったので設定してきます。

GITHUB_APP_INTEGRATION_ID は作成したGitHub Appページの「About」セクションの「App ID」にある値がそれに当たります。

GITHUB_APP_PRIVATE_KEY は同じページの下の方に↓のような private key を生成できるボタンがあるのでそれを押して秘密鍵ファイルを取得します。そしてその秘密鍵の中身の値をこの環境変数に使います。

f:id:shirakiya:20220325031755p:plain

サーバーにこれらの新しく更新した環境変数を反映させて(必要なら再起動などを行う)作業完了です。

おそらくこれでbulldozerが正しく稼働し始めたのではないかと思います。
正常に稼働できているかどうかの確認は、サーバーのアクセスログなどからGitHubのwebhookに対してHTTPステータスコード200を返せているかどうかや、実際にプルリクの操作をしてみるなどでしょうか。

まとめ

本当にbulldozerは便利で、それこそ使ったものにしか伝わりづらいのが残念なのですが個人的にはbulldozerがOrganizationにいることが福利厚生とまで思ってしまうほどです。本当にオススメなのでぜひ導入してみてはいかがでしょうか。