PR待ち時間を半減するマージ可否の見える化設定
「レビューお願いします」と書いてPRを出したあと、Slackを眺めながら承認を待つ。数時間後にようやく「LGTM」がついたと思ったら、今度は「CIが通ってないからマージできない」と言われる。またしばらく待機。——この時間、積み重なるとけっこうな損失になる。
実はこの「今マージできるのかできないのか分からない」状態、GitHubの設定だけでかなり改善できる。PRを開いた瞬間に「あと何が足りないか」が一目で分かれば、無駄な待機時間はぐっと減る。
「マージ可否」は機械的に判定できる
GitHubの保護ブランチ(Protected branches)やルールセット(Rulesets)を使うと、PRのマージ条件をコードで定義できる。設定した条件を満たさない限り、物理的にマージボタンが押せなくなる。
具体的に指定できる条件はこんな感じ:
- 必須レビュー数:最低1人(または2人以上)の承認が必要
- CODEOWNERSの承認:特定ファイルの変更は担当者のレビューが必須
- 必須ステータスチェック:指定したCIジョブが全て成功している
- 最新コミットへの承認:古いコミットへの承認は無効化される
これらを設定すると、PR画面の下部に「Merging is blocked」などと表示され、何が足りないかが明確になる。「レビュー待ち」なのか「CI待ち」なのかが一瞬で分かるので、質問したり待ったりする時間が消える。
設定の入り口:Settings → Branches
リポジトリの設定画面から「Branches」を開くと、保護ブランチのルールを追加できる。
mainブランチに対して設定するなら、まずは以下の2つから始めるのが無難:
-
Require a pull request before mergingをON
- 直接pushを禁止して、必ずPRを経由させる
- 「Required approvals」で承認数を指定(最初は1で十分)
-
Require status checks to pass before mergingをON
- マージ前に通すべきCIジョブを指定
- 検索窓にジョブ名を入れて選択する
この2つだけで「承認もCIも通ってないとマージできない」状態が作れる。PR画面を見れば、今何が足りないか全員が同じ情報を見られるようになる。
必須ステータスチェックの落とし穴
便利な必須チェックだが、設定を間違えるとハマる。
ありがちなのが「チェックを送信するGitHub Appを指定し忘れる」パターン。GitHubの仕組み上、チェック結果は誰でも送信できてしまう。悪意はなくても、別のCIサービスが同じ名前のチェックを送ってくることがある。
対策として、ルールセットでは「期待する送信元」を指定できる。GitHub Actionsで動かしているなら、GitHub Actionsを送信元として明示的に指定しておくと安全。
もう一つの落とし穴は「チェックが返ってこない」状態。CIが途中でハングしたとき、いつまでもマージできなくなる。GitHub Enterprise Serverではタイムアウトを分単位で設定できる機能があるが、GitHub.com(Cloud)では使えないケースもあるので、CI側でジョブのタイムアウトを設定しておくのが現実的だ。
レビュー無効化ルール、ONにすべきか
ルールセットには「新しいコミットがpushされたら古い承認を無効化する」オプションがある。
品質を重視するなら確かに正しい。「LGTM」をもらった後にこっそり変更を足してマージ、なんてことを防げる。
ただし、これをONにすると「typo修正の1行pushで再承認待ち」が発生する。修正のたびにレビュアーを呼び戻すことになり、待ち時間は確実に増える。
筆者の意見としては、チーム規模が小さいうちはOFF推奨。信頼関係があるなら、小さな修正のたびに再承認を求める必要はない。チームが大きくなったり、外部コントリビューターが増えてきたらONを検討する、くらいのスタンスでいいと思う。
Merge Queueで「マージ担当」を消す
保護ブランチの設定をしっかりやっても、最後に残るのが「マージボタンを押す人待ち」問題。承認もCIも通ったのに、みんな忙しくて誰もマージしない。
ここで効くのがMerge Queue機能。PRを「Merge when ready」としてキューに入れると、条件が揃った時点でGitHubが自動でマージしてくれる。
流れとしては:
- PRを出す
- レビュー承認をもらう
- 「Merge when ready」でキューに追加
- CIが通ったらGitHubが自動マージ
「誰がマージするか」を考えなくていい。自分のPRをキューに入れたら、あとは次のタスクに移れる。
注意点として、Merge Queueは保護ブランチで「Require merge queue」をONにしないと使えない。また、キュー内のPRが衝突したときの挙動など、チームで事前に認識を合わせておく必要がある。
GitHub以外のプラットフォームでも
Bitbucket CloudやGitLabにも似た機能がある。
Bitbucket Cloudでは「Require checks before merge」で必要承認数やビルド成功を要求できる。面白いのが「Merge while build is running」オプション。ビルド以外の条件が揃っていれば、ビルド完了を待たずにマージ予約ができる。CIが長いプロジェクトでは待ち時間短縮に効く。
ただしBitbucketでは、PR作者自身の承認は必要数にカウントされない点に注意。自分で出して自分で承認、はできない仕組みになっている。
GitLabには「Pipelines must succeed」という設定があり、パイプライン成功を必須にできる。注意点として、パイプラインがスキップされた場合もマージできなくなるケースがある。設定次第で逆にハマることもあるので、最初は小さいリポジトリで試すのがいい。
どこから始めるか
いきなり全部の設定をONにすると、既存の開発フローが詰まる可能性がある。
まずは「必須レビュー1人」と「必須ステータスチェック」の2つだけ設定して、1〜2週間様子を見るのがおすすめ。その後、チームの状況を見ながらMerge Queueや承認無効化ルールを足していく。
見える化の効果は地味だが確実。「今何を待っているのか」が明確になるだけで、コミュニケーションコストがかなり減る。設定は10分もあれば終わるので、次のPRを出す前に試してみてほしい。