複数のDependabot PRを連続マージすると事故が怖い
同一リポジトリでDependabotが作成した複数のPull Requestをgh pr mergeで連続マージすると、後続のPRが直前のマージの影響でコンフリクトを起こすことがある。
例えばlockファイルを更新するPR同士は、片方をマージした時点でもう片方のベースブランチとの差分が変わる。そのままマージするとコンフリクトしたコードを取り込んでしまう恐れがあるため、マージボタンを押す前にマージ可否を確認する習慣が必要である。
gh pr viewでマージ可否を確認する
gh pr viewの--jsonオプションを使うと、GitHub PR APIのmergeableとmergeStateStatusを直接取得できる。
$ gh pr view 123 --json mergeable,mergeStateStatus
mergeableフィールドの見方
mergeableはPRのブランチをベースブランチにマージできるかをGitHubが試算した結果であり、値は3種類ある。
MERGEABLE: コンフリクトなくマージできるCONFLICTING: コンフリクトがあり、そのままではマージできないUNKNOWN: GitHub側でまだ判定計算が終わっていない
UNKNOWNは一時的な状態である点に注意が必要である。GitHubはこの判定を非同期のバックグラウンド処理で計算しており、mergeableが未計算の間はUNKNOWNを返す。経験上、直前に別のPRを同じベースブランチにマージした直後は、他のオープンなPRの判定が再計算されるらしく、マージ直後に確認すると一瞬UNKNOWNになることがある。
mergeStateStatusフィールドの見方
mergeStateStatusはmergeableよりさらに詳細な状態であり、CIのステータスやブランチ保護ルール(必須レビューなど)も加味した、実際にマージボタンを押せる状態かを示す。
CLEAN: ブランチ保護ルールも含めてすべて満たし、すぐマージ可能BLOCKED: 必須チェック未完了、または必須レビュー不足BEHIND: ベースブランチより遅れていて、保護ルール上マージ前に更新が必要DIRTY: コンフリクトがある(mergeable: CONFLICTINGに対応)UNKNOWN: 計算中
ほかにUNSTABLE(必須でないチェックの失敗)やHAS_HOOKS、DRAFT(ドラフトPR)といった値もあるが、Dependabot PRのコンフリクト確認という用途では上記5値を押さえておけば十分である。
連続マージの運用手順
同一リポジトリで複数PRを連続マージする場合は、以下の手順で進める。
- 1件目をマージする(
gh pr merge 123 -d -m) - マージ直後に2件目の
gh pr view 124 --json mergeable,mergeStateStatusを叩く UNKNOWN/UNKNOWNが返ってきた場合はGitHubが再計算中のサインなので、数秒〜十数秒待ってから再度チェックするCLEAN/MERGEABLEになっていればコンフリクトなしと判断してマージを進めるCONFLICTING/DIRTYだった場合はコメントで@dependabot rebaseを依頼し、MERGEABLEに変わるまで待ってから再度マージを試みる
lockファイル同士が競合するケースでは、rebaseを依頼すると数分でDependabotが自動でリベースしてくれることが多い。
まとめ
gh pr view --json mergeable,mergeStateStatusを使うと、マージボタンを押す前にPRのコンフリクト有無とマージ可能状態をCLIから確認できる。同一リポジトリで複数のDependabot PRを連続マージする際は、マージ直後のUNKNOWNを早合点でコンフリクトと誤判定しないよう、数秒待ってから再チェックする運用が有効である。
