自動マージされないPRを、番犬が人間へ名指しで知らせる
今回やったこと
無人レーンの停止を検知しても、修正の pull request(PR)がすでに作成されていて、それが未マージのまま滞留していれば復旧は進まない。停止通知と修正PRの滞留通知を同じ監視結果へまとめ、次の対応が人間の判断待ちかどうかを見えるようにする設計を整理する。
対象は、GitHub上のPRを自動マージする仕組みと、定期ジョブの稼働を監視する Python スクリプトを運用するケースだ。ここで扱うのはリポジトリ内の scripts/agent_lane_watch.py と、その回帰テストに記録された仕様である。
停止通知だけでは復旧しない
監視で「成果物が出ていない」と分かっても、原因の修正がすでにコードになっているとは限らない。反対に、修正PRが存在しても自動マージの対象外なら、通常の自動化はそれを処理しない。どちらの状態も、レーンの無音だけを見ていては区別できない。
この問題の記録では、起稿レーンの障害を直すPRが作成済みだった一方、対象ファイルが scripts/ と .github/ に限られていたため自動マージの許可範囲に入らず、人間の判断を待っていた。監視側はレーン停止を通知していたが、「直すPRが既にある」という次の手掛かりまでは提示していなかった。したがって、停止を知らせる監視と、修正を待たせている場所を示す監視は、同じ復旧の流れとして結び付ける必要がある。
何を「人間待ち」と判定するか
agent_lane_watch.py は gh pr list から open PR を取得し、一定時間以上経過したものを調べる。初期値は12時間で、--stale-pr-hours で変更できる。すべての古いPRを人間待ちにするわけではない。自動マージの許可パス外、必要ラベルの不足、fork由来といった、daemon が構造的に拾えない理由を確認して分類する。
しきい値を運用時に調整する場合は、たとえば次のように起動する。既定値の12時間を24時間に延ばす例であり、PRの取得条件やマージ動作は変えない。
python3 scripts/agent_lane_watch.py --stale-pr-hours 24
分類は「自動化が処理できないため、人間の判断が必要なもの」と「自動化の管轄内にあるもの」を分ける。draft PRやしきい値に達していない新しいPRを誤って督促しないことも同じくらい大切だ。通知が毎回大量に鳴れば、必要な通知まで読まれなくなる。
| 状態 | 扱い |
|---|---|
| 12時間以上経過し、自動マージの対象外 | 人間待ちとして理由を添えて通知 |
| 12時間以上経過し、必要ラベルがない | 不足ラベルを理由に表示 |
| 自動マージ対象のラベル付きPR | daemon の管轄として人間待ちから除外 |
| draft、または時間しきい値未満 | 督促対象から除外 |
実装では、人間待ちのPRを古い順に並べ、通知に載せる件数を上位に絞る。件数が多い場合も残りの総数を出すため、通知が長大にならず、滞留がゼロなら追加の文面を作らず静かに終わる。
テストは偽のGitHub応答で境界を確かめる
回帰テスト scripts/test_agent_lane_watch_stale_pr.py は偽の gh コマンドを PATH に置き、JSONで用意したPR一覧を返す。これにより、実際のGitHubへ依存せず、滞留PRの取得から判定、通知文面までの接続を確認できる。
テストでは、許可パス外のPR、必須ラベルのないPR、fork由来のPRを人間待ちとして拾う一方、ラベル付き、draft、しきい値未満のPRを対象外にする。また、12時間のしきい値を24時間へ変えた際に、20時間経過のPRが対象から外れることも確認する。分類関数だけを単独で試すのではなく、偽の gh を通じたデータ取得と通知までを動かすことで、コマンド呼び出し自体が外れている故障も検出できる。
運用で押さえる点
この仕組みはPRを自動でマージしない。人間の判断が必要なものを、レーンの無音と同じ監視通知へ載せる。自動化が扱えるPRと人間が押す必要のあるPRを分け、復旧に必要な次の担当を明確にするための仕組みだ。
監視スクリプトは自動マージ側の判定設定を直接参照し、許可パスや必須ラベルの二重管理を避ける。回帰テストでは両者の前提が保たれていることと、「鳴らすケース」「鳴らさないケース」の両方を確かめる。
更新履歴
- 2026-10-08: 初稿。