チェックが1本も走っていない状態を合格にしないCIゲート
今回やったこと
自動マージの前にCI結果を確認する仕組みでは、失敗したチェックを止めるだけでは足りない。チェックがまだ登録されていない状態と、そもそも対象のチェックが存在しない状態を区別する必要がある。scripts/lib/ci_gate.py は、空のチェック一覧を無条件の合格として扱わず、変更ファイルとワークフローの適用範囲も照合する。この設計と、そこで防ごうとしている失敗を整理する。
空の一覧は「成功」ではない
GitHub の PR を作った直後は、チェック結果の一覧が空になることがある。ここで「失敗がないから合格」と判定すると、CI が始まる前にマージできてしまう。実際にこのリポジトリでは、2026年10月7日に、手元で作成してから時間を置いて push したマージコミットが問題になった。ゲートはコミット時刻から1184秒経っていることを根拠に「このパスに走るワークフローがない」と判定したが、実際には9件のチェックが保留中だった。
原因は、猶予時間の時計をコミット時刻から数えていたことにある。ローカルでコミットを作った時点と、GitHub に push してCIが登録される時点には間がある。古いコミット時刻だけを見て猶予を終えると、GitHub 側で何が起きているかを確認する前に「チェックなし」を確定してしまう。
チェックの有無を二段階で見る
空の一覧に猶予を持たせるだけでは、猶予後の誤判定が残る。そこで、変更ファイルがどのワークフローの on.pull_request 条件に一致するかを調べる。変更がワークフローの対象に入っているのに対応するチェックが一覧に無ければ、unregistered として待つ。対象となるワークフローが本当に無い場合だけ no_checks として扱う。
PRの変更ファイルを取得
↓
pull_request 条件に一致するワークフローがある?
├─ あるがチェックが未登録 → 待つ(unregistered)
└─ ない → no_checks の候補
このリポジトリでは gitleaks が全パスを対象にするため、変更ファイルがある通常のPRなら少なくとも対象ワークフローが存在する。実装コメントには、直近にマージされた200件を調べ、チェックが空のまま入ったものが0件だったという2026年10月7日の実測も残されている。これは当時の調査結果であり、将来のPRについて保証する数字ではない。
別リポジトリのワークフローを読めない場合に備え、push 時刻を取得できれば猶予の起点を後ろへ動かす仕組みもある。時刻が取れなくても、ワークフロー範囲を解析できる環境では「対象なのに未登録」を通さない。複数の根拠を使い、単一の時計に判定を預けない形だ。
ゲートは止めるケースと通すケースを両方検査する
CIゲートが存在していても、エラー入力を誤って通せば役には立たない。scripts/test_ci_gate.py は失敗、保留、タイムアウトなどで止まることを確認し、緑なら通ることや、キャンセル済みチェックだけで永久に止めないことも対照として置いている。テストの説明には、判定ロジックだけでなく、実際のマージ経路からゲートが呼ばれていることも確認するとある。
また、ゲートが見たPRの head とマージ対象がずれる問題も別に扱う。チェックを確認した後で新しいコミットが push されれば、確認済みの緑は新しい head の証拠ではない。Verdict に判定時の head SHA を保持し、マージ側がその SHA に一致する head だけを対象にする設計がコードに記載されている。空のチェック一覧への対処と同じく、「確認したつもり」を成功扱いしないための境界である。
適用するときの判断
CIゲートを導入する場合は、少なくとも次の状態を分けて設計する。
| 状態 | 扱い | 理由 |
|---|---|---|
| 失敗したチェックがある | 停止 | 成功の証拠がない |
| チェックが保留中 | 待機 | 結果がまだ確定していない |
| 対象ワークフローがあるのにチェック未登録 | 待機 | CI開始前の可能性がある |
| 対象ワークフローが存在しない | 条件付きで通過 | 実行対象がないと確認できた場合に限る |
| 緑を確認した後に head が変わった | 停止・再確認 | 緑が新しいコミットを検査したとは限らない |
この整理は、チェック名の一覧を固定で持つ方法よりも、ワークフローの実際の適用範囲とPRの変更内容を結び付ける。ワークフローを追加・変更したときは、対応するテストとマージ経路の配線も一緒に見直す必要がある。
環境と確認範囲
対象はこのリポジトリの Python 実装 scripts/lib/ci_gate.py と、その回帰テスト scripts/test_ci_gate.py。記事は参照ドキュメントに記録された設計と事例を説明しており、CIを新たに実行した結果を報告するものではない。時刻猶予やワークフローの適用範囲はリポジトリの構成に依存するため、他の環境では同じ値や結論をそのまま流用できない。
更新履歴
- 2026-10-18: 初稿作成。