Dependabot Merge
Dependabot が作成した PR のレビューとマージを gh で標準化する。
依存更新は「CI が通っていること」だけでは安全と言い切れない。semver では >=1.0 のマイナー/パッチは後方互換が期待できるが、0.x(<1.0)はマイナー更新でも破壊的変更があり得る。だから本スキルは、CI 成功の確認に加えて changelog / release notes から影響を読み、判断の根拠を PR コメントに残してからマージする流れを固定する。判断を記録するのは、後から「なぜマージした/しなかったか」を追えるようにするためだ。
使い方
dependabot-merge <PR URL | 番号> 指定した 1 件の Dependabot PR を確認してマージ
dependabot-merge --all 現在の repo の open な Dependabot PR をすべて逐次処理
dependabot-merge (対象未指定)--all と同じ=全 open Dependabot PR を逐次処理
- 対象指定: PR URL / PR 番号(現在の repo)/
--all(一括)。--allは GitHub 自動マージ未設定のリポジトリでの一括処理を想定。 - PR URL / 番号も
--allも指定しない場合は--allとみなす(現在の repo の open な Dependabot PR をすべて逐次処理)。 --all(対象未指定を含む)は「open な Dependabot PR を順に確認してマージしてよい」という委譲の合図。それでも 1 件ずつ影響を確認し、安全と判断したものだけマージする。
例: dependabot-merge 12 / dependabot-merge https://github.com/<owner>/<repo>/pull/12 / dependabot-merge --all
- 自然文でも発動する:「Dependabot の PR をマージして」「依存更新 PR を確認してマージ」「dependabot の PR を全部見て」。
前提
- ツール:
gh(GitHub CLI。gh apiを含む) - 前提スキル: なし
- MCP: なし
- シェル: bash(POSIX 互換シェル)。コマンド例は bash 前提のため、Windows では WSL / Git Bash 等の bash 環境で実行する
- node / pnpm / python などのランタイムは不要。
セットアップ(マージ方式の選択)
マージ方式(squash / merge / rebase)は利用者やリポジトリで好みが異なる。一度決めたら使い続けることが多いので、スキル導入時に一度選び、.config/skills/shoji9x9/skills.yml の skills.dependabot-merge.merge_method に保存する。スキルはマージのたびにこの設定を読む。
version: 1
skills:
dependabot-merge:
merge_method: squash # squash | merge | rebase
- 作成・追記は非破壊: ファイルが無ければ
.config/skills/shoji9x9/ごと作成し、skills.dependabot-merge.merge_methodだけを書く。既にあれば欠けたキーだけを該当セクション(無ければ親も)に追記し、既存のキー・値・コメントは変更しない。既存の設定があれば上書きしない(尊重する)。 - インストール先に設定が無ければ、ユーザーに方式を確認してから書く。設定が無いまま起動した場合はデフォルトの
squashを使い、その旨をユーザーに通知する(次回以降のために設定作成を促してよい)。 - リポジトリで許可されたマージ方式(
gh repo view --json squashMergeAllowed,mergeCommitAllowed,rebaseMergeAllowed)と矛盾する場合は、許可された方式を案内して確認する。
基本フロー(単一 PR)
対象未指定または --all の場合は「--all フロー」へ進む。以下は単一 PR(PR URL / 番号)を指定されたときの手順。
- 入力から owner / repo / PR 番号を抽出する
- 現在の repo と PR の owner / repo が一致するか確認する
- 一致しない場合は、以降の確認・マージを行わず中断し、ユーザーに確認する
- PR の著者が Dependabot か確認する(
gh pr view <番号> --repo <owner>/<repo> --json author --jq '.author.login')- bot の login 表記は揺れる(
dependabot[bot]等)ためdependabotを含むかで判定する。app/dependabotはgh pr list --authorで絞るときの app slug であって、author.loginの値とは別物 - Dependabot 以外なら、本スキルの対象か中断して確認する(取り違え防止)
- bot の login 表記は揺れる(
- CI 成功を確認する(後述「gh メカニクス」)。必須チェックが
- 成功 → 次へ
- 実行中 → 完了を待つ(
--watch)か、待たない場合はその旨を伝えて停止 - 失敗 → マージせず、失敗内容と「どうすれば直せそうか」を PR コメントに記録してユーザーに報告
- マージ影響を確認する。Dependabot が PR 本文に入れる Release notes / Changelog / Commits(
gh pr view <番号> --repo <owner>/<repo> --json title,body,files)と、更新依存・バージョン差分(lockfile / manifest の差分)を読む- 特に 0.x 依存は、マイナー更新でも破壊的変更があり得るため changelog を必ず確認する
- devDependency か runtime か、リポジトリ内での使用箇所も踏まえて影響範囲を見積もる
- 判断の根拠を PR コメントに記録する(
gh pr comment)。マージ可否いずれの場合も残す- マージ不可と判断した場合は、何が課題か(例: 破壊的変更で X の対応が必要 / CI の失敗原因 / behind のため rebase が必要)と、どうすればマージできるかを必ず明記する。次に見た人がそのまま動けるようにするため
- マージする / しない
- 安全 → 設定の
merge_methodでマージ(gh pr merge --<method> <番号> --repo <owner>/<repo>) - リスクあり / 影響が判断できない → マージせず、6 のコメントを残したうえでユーザーに報告
- 安全 → 設定の
- 実施結果(マージ有無・理由)を報告する
返信(コメント)より先にマージしない。 必ず「判断をコメントに記録 → マージ」の順にする。記録のないマージは経緯が追えなくなる。
--all フロー(再作成・force-push を見込んだ逐次処理)
Dependabot は 1 件マージすると、残りの open PR を rebase / force-push で作り直すことがあり、さらに "Dependabot Updates" のバックグラウンドジョブが新しい PR を後から作ることもある。列挙した時点のスナップショットを信じて機械的に回すと、古い head を見たり、新しく出た PR を取りこぼす。だから次のように 状態を取り直しながら、新規が出なくなるまで処理する。
- open な Dependabot PR を列挙する(後述。ページネーション順守)
- 1 件ずつ、処理直前に最新状態を取り直してから単一フローを適用する
- 処理直前に
gh pr view <番号> --repo <owner>/<repo> --json headRefOid,mergeable,mergeStateStatus,stateと CI 状態を再取得する(列挙時の値を使い回さない) mergeStateStatusがBEHIND(base に遅れている)なら@dependabot rebaseで更新を促す。rebase 後の待機・拒否時のrecreateフォールバック・supersede/close 時の後継 PR への切り替えは 「behind(base に遅れている)PR の更新」に従い、更新後の CI 成功は--watchの即時終了を信用せず確認してから判断する- 処理中に
stateがCLOSED(Superseded by #<N>等)へ変わったら当該 PR を追わず、手順 5 の open 一覧再取得で後継 PR を拾う
- 処理直前に
- 1 件マージしたら、残り PR が rebase / force-push・CI 再実行される可能性を見込み、次の PR は head が落ち着き CI が完走するのを待ってから判断する。
このとき
gh pr checks --watchの即時終了(exit 0)を「CI 完了」と信用せず、「CI 成功の確認」の予定(mergeStateStatusがCLEAN/UNSTABLE、または必須チェック行が pending でなくなる)でポーリングしてから判定する - 失敗 / リスクありはスキップし、理由を PR コメントに残す
- 一連の処理後に再確認ループ: open な Dependabot PR 一覧を取り直し、未処理 / 新規 PR が残っていないか確認する。残っていれば(in-flight な update ジョブの完了を待ったうえで)再度フローを回し、新規が出なくなるまで繰り返す
- 最後に、マージした PR・スキップした PR(理由つき)のサマリーを報告する
gh メカニクス
Dependabot PR の列挙(--all・全件取得)
著者で絞って取得する。gh pr list --author には Dependabot の app slug app/dependabot を渡す。
件数が --limit の既定(30)を超えると取りこぼすため、--limit を十分大きく取る(gh pr list に --paginate は無い)。既定 30 で暗黙に打ち切らないこと。
gh pr list --repo <owner>/<repo> --state open --author "app/dependabot" \
--limit 200 --json number,title,headRefName,url
著者の確認(単一 PR)
gh pr view <番号> --repo <owner>/<repo> --json author --jq '.author.login'
author.loginの bot 表記は環境で揺れる(dependabot[bot]等)ため、dependabotを含むかで緩く判定する。app/dependabotはgh pr list --authorで使う app slug であり、author.loginの値ではない(混同しない)。
CI 成功の確認
gh pr checks <番号> --repo <owner>/<repo> --watch --fail-fast
- 全チェックの完了まで待ち、すべて成功なら終了コード 0、いずれか失敗なら非 0 で終わる。待ちたくない場合は
--watchを外して現状だけ見る。 - push 直後はチェック未登録で
no checksと即時に返ることがある。その場合は数秒待ってから再確認する。 - マージ可否そのものは
mergeStateStatusでも確認できる。CLEANはマージ可、BLOCKEDは必須チェック未通過/要件未達、BEHINDは base に遅れ(要 rebase)、UNSTABLEは必須でないチェックが落ちているがマージ可、DIRTYはコンフリクト。
gh pr view <番号> --repo <owner>/<repo> --json mergeable,mergeStateStatus
rebase / force-push 後の --watch 即時終了(exit 0)を「CI 完了」と信用しない。 @dependabot rebase / force-push 直後は、必須チェック(check / signatures 等、ブランチ保護で必須指定されたもの)がまだ登録されておらず、
先に登録されるスキップ専用チェック(CodeQL skipping 等)だけが見える瞬間がある。--watch はその時点で登録済みのチェック集合の完了を待つため、必須チェックが pending のままでも exit 0 で抜ける。
head を差し替える操作(rebase / force-push)を挟んだ後の CI 完了は、次のどちらかを満たすまで上限つきでポーリングしてから判定する:
(a)
mergeStateStatusがBLOCKED/BEHINDを抜けてCLEAN/UNSTABLEになる(リポジトリ非依存で堅い。必須チェック未通過ならBLOCKEDのまま)。(b) 必須チェック行が登録され pending でなくなる。
--jsonのフィールド(bucket, completedAt, description, event, link, name, startedAt, state, workflow)に「必須か」を示すものは無いため、 絞り込みは--requiredフラグで行う(https://cli.github.com/manual/gh_pr_checks)。全チェックを見ると、スキップ専用チェックだけが登録された瞬間に全行が非 pending となり同じ false positive を踏む。gh pr checks <番号> --repo <owner>/<repo> --required --json name,state,bucket行が 0 件のときは pending 不在とみなさない(
--requiredでも同じ。必須チェック未登録か、必須チェックを設定していないリポジトリのいずれか)。 このときghは空配列を返さずno required checks reported on the '<branch>' branchを stderr に出して非 0 で終了する(rebase 直後の未登録はまさにこの状態)ため、 コマンド不備として扱わず「0 件」としてポーリングを続ける。bucketにfail/cancelがあれば CI 失敗が確定しているので、mergeStateStatusの遷移(失敗時はBLOCKEDのまま)を待たずマージしない判断へ進む。
この予定は --all フローで 1 件マージ後に次 PR の CI 完了を待つときにも使う。
behind(base に遅れている)PR の更新
gh pr comment <番号> --repo <owner>/<repo> --body "@dependabot rebase"
Dependabot がブランチを base に追従させ直し、更新後に CI が再実行される。ただし rebase 依頼後の待機を「期待する変化(head 更新・CI 完了)」だけで終わらせると、
Dependabot 側の依頼拒否やグループ更新の再編成による**PR の作り直し(supersede / close)**で空振りする。
待機は headRefOid の変化だけでなく state(CLOSED / MERGED)と直近の Dependabot コメントも監視し、次の分岐を終了条件に含める(上限つきポーリング):
rebase 反映: head が更新され CI が再実行される。CI 完了は上の「CI 成功の確認」の予定(
--watchの即時終了を信用しない)で待ってから判断する。依頼拒否: Dependabot が
The base commit has not changed(実際は BEHIND でも起こる)等で rebase を拒否したら、@dependabot recreateにフォールバックして PR を作り直させ、新しい head の CI 成功を待つ。gh pr comment <番号> --repo <owner>/<repo> --body "@dependabot recreate"supersede / close: グループ更新の再編成で当該 PR が後継 PR に置き換えられ close されることがある(Dependabot コメントの
Superseded by #<N>/updatable in another way、stateがCLOSED)。 この場合は当該 PR を追わず、open な Dependabot PR 一覧を取り直して後継 PR を特定し、既に確認済みの更新内容(changelog / 影響評価)は後継 PR で再利用する。
state と直近の Dependabot コメントは次で確認する(bot 表記の揺れに対応し dependabot を含む author で緩く絞る。コメントは古い順のため末尾が最新):
gh pr view <番号> --repo <owner>/<repo> --json state,headRefOid,mergeStateStatus
gh api --paginate repos/<owner>/<repo>/issues/<番号>/comments \
--jq '.[] | select(.user.login | ascii_downcase | contains("dependabot")) | {created_at, body: (.body // "")[:300]}'
判断の記録(PR コメント)
gh pr comment <番号> --repo <owner>/<repo> --body "<判断と根拠>"
- マージする場合: 何を確認し、なぜ安全と判断したか(例:
>=1.0のパッチで changelog にバグ修正のみ)。 - マージしない場合: 課題と解決策(例:
0.x のマイナーで API 変更あり。<該当箇所> の修正が必要、CI の <ジョブ> が <理由> で失敗。<対処> で直る、BEHIND のため @dependabot rebase 後に再評価が必要)。
マージ
設定 .config/skills/shoji9x9/skills.yml の skills.dependabot-merge.merge_method に従う(既定 squash)。
gh pr merge --squash <番号> --repo <owner>/<repo> # または --merge / --rebase
BEHINDでマージが拒否される場合は「behind(base に遅れている)PR の更新」に従い、@dependabot rebase(拒否されたら@dependabot recreate)で更新 → CI 成功を確認してから再試行する。- commit の
--amendや force push は行わない。@dependabotへの指示コメント以外で履歴を書き換えない。
マージ可否の判断ガイド
機械的に全部マージするのでも全部止めるのでもなく、更新内容の事実に基づいて 1 件ずつ判断する。
- CI が必須チェックを通過しているか(最低条件。未通過ならマージしない)
>=1.0のマイナー/パッチか: semver 上は後方互換が期待でき、changelog がバグ修正・小さな改善中心なら安全寄り- 0.x(<1.0)のマイナー/パッチか: マイナーでも破壊的変更があり得る。changelog / release notes で API 変更・削除・挙動変更の有無を確認する。判断できなければマージせずユーザーに確認する
- 影響範囲: runtime 依存か devDependency か、リポジトリ内の使用箇所、ビルド/テストへの影響
- 判断材料が足りない・影響が大きい・設計判断が絡む場合は、勝手にマージせずユーザーに確認する
追加確認が必要な条件
以下のときは処理を止めてユーザーに確認する。
- 現在の repo と PR の owner / repo が一致しない
- PR の著者が Dependabot でない
- マージ方式の設定が無く、デフォルト以外を使いたい場合
- 設定のマージ方式がリポジトリで許可されていない
- 0.x 依存の破壊的変更の有無が changelog から判断できない
- 影響が大きい、または判断材料が不足している