パイプラインはいつ停止し、人間の判断を待つべきか

想像してみてほしい。あなたのチームには堅牢なCI/CDパイプラインがある。テストは自動で実行される。セキュリティスキャンも通過する。コードはビルドされ、誰も手を触れることなくステージング環境にデプロイされる。そして、本番環境の直前でパイプラインが停止する。通知が飛ぶ。「承認が必要です」。

誰かが「承認」ボタンをクリックするまで、デプロイは進まない。その人物はテックリードかもしれない。エンジニアリングマネージャーかもしれない。もしかすると会議中だったり、すでにその日は退勤しているかもしれない。デプロイはそこに留まり、待ち続ける。

この瞬間に、すべてのチームが直面する緊張が現れる。パイプラインはどこまで自律的に判断すべきか。そして、いつ停止して人間の判断を仰ぐべきか。

2種類のチェックポイント

すべてのパイプラインにはチェックポイントがある。変更があるステージから次のステージに移る前に、何かがその安全性を検証する。そのチェックポイントには2種類ある。自動化ゲートと手動承認だ。

自動化ゲートとは、人間の介入なしにパイプライン内で実行されるチェックである。パイプラインは一連のテストや検証を実行し、変更を進めてよいかどうかを判断する。たとえば、開発者が新しいコードをプッシュした後、パイプラインは単体テストを実行する。すべてのテストが通れば変更は続行される。いずれかのテストが失敗すれば、パイプラインは停止しチームに通知する。

手動承認とは、人間が下す判断である。通常はリードエンジニア、テックリード、または特定の環境に責任を持つ人物が担当する。その人物は変更をレビューし、コンテキストを考慮して、承認または却下する。パイプラインはその判断が届くまで待機する。

どちらも同じ目的を持つ。悪い変更が先に進むのを防ぐことだ。しかし、その動作方法は根本的に異なる。

次の図は、これら2種類のチェックがデプロイパイプラインにどのように組み込まれるかを示している。

flowchart TD A[変更がパイプラインに入る] --> B{自動化ゲート?} B -->|Yes| C[自動チェックを実行] C --> D{合格?} D -->|Yes| E[次のステージへ進む] D -->|No| F[停止 & チームに通知] B -->|No| G{手動承認?} G -->|Yes| H[人間の判断を待つ] H --> I{承認?} I -->|Yes| E I -->|No| F E --> J[次のパイプラインステージ]

自動化ゲートの得意なこと

自動化ゲートの最大の利点は一貫性である。変更がパイプラインに入るたびに、同じチェックが同じ方法で実行される。誰かが忘れたからといってスキップされることはない。納期が迫っているからといって急かされることもない。パイプラインは疲れず、気を散らさず、えこひいきもしない。

テストが網羅的でチェックが正しければ、自動化ゲートは信頼できるベースラインを提供する。それらのゲートを通過したすべての変更は、最低限の基準を満たしている。誰かが手を抜いたり、ステップを飛ばしたりしていないかと疑問に思う必要はない。

自動化ゲートはスケールもする。5人の開発者チームならすべての変更を手動でレビューできるかもしれない。50人のチームでは無理だ。パイプラインは数分で何百ものチェックを実行できるが、人間のレビュアーが同じ作業を行うには何時間もかかる。

自動化ゲートの限界

しかし、自動化ゲートには死角がある。プログラムされたことしかチェックできないのだ。チームの雰囲気を読むことはできない。プロダクションの状態やムードを感じ取ることはできない。経験に基づいた判断を下すことはできない。

パイプラインはすべての単体テストが通ったことを検証できる。しかし、この特定の変更をブラックフライデーのトラフィック中にデプロイしても安全かどうかは教えてくれない。データベースマイグレーションスクリプトが構文エラーなしで実行されることはチェックできる。しかし、火曜日の午後3時にそのマイグレーションを実行するのが悪いアイデアかどうかは教えてくれない。

自動化ゲートは「これは技術的な基準を満たしているか?」という問いに答えるのは得意だが、「これを今すぐ実行すべきか?」という問いに答えるのは苦手だ。

人間が必要な場面

ここで手動承認の出番となる。人間は、どのテストも捉えられない要素を考慮できる。

  • 今がデプロイの適切なタイミングか? プロダクションがすでに不安定かもしれない。大規模なマーケティングキャンペーンが始まったばかりかもしれない。オンコールのエンジニアがインシデント対応中で、デプロイで気を散らされるべきではないかもしれない。

  • この変更には調整が必要か? デプロイが別のチームのサービスに影響するかもしれない。データベースチームがスキーマ変更を認識する必要があるかもしれない。QAチームが変更をユーザーに届ける前に最終スモークテストを実行したいかもしれない。

  • リスクは許容できるか? 小さなバグ修正なら金曜の午後にデプロイしても安全かもしれない。大規模なリファクタリングはそうではないかもしれない。人間は経験とコンテキストに基づいてリスクを評価できる。

手動承認は説明責任も生み出す。誰かがデプロイを承認するとき、その人物は自分の名前を出すことになる。これは責任追及のためではない。誰かが変更をレビューし、意識的な決定を下したという明確な記録を残すためだ。何か問題が発生した場合、チームはデプロイ前に何が検討されたかを振り返ることができる。

使い分けの判断基準

よくある質問は、どのチェックを自動化し、どのチェックに人間の承認を必要とするべきか、というものだ。

答えはチェックの性質に依存する。コード化できる技術的な検証は自動化ゲートにすべきだ。テスト、セキュリティスキャン、リンティング、フォーマットチェック、依存関係監査などは、すべて機械の方が人間より速く、一貫して実行できる。

判断、コンテキスト、調整を必要とする決定は手動承認にすべきだ。タイミングの判断、リスク評価、チーム間の調整、ビジネス影響の評価は、人間に任せるのが最善だ。

ただし、ここには微妙なニュアンスがある。自動化できるからといって、必ずしもゲートにすべきとは限らない。情報としては有用だが、ブロッカーにはすべきでないチェックもある。たとえば、パフォーマンステストを実行して結果をログに記録するが、結果が期待よりわずかに悪くてもパイプラインをブロックしない、という選択もある。それは人間が判断すべきことだ。

対立ではなく補完関係

自動化ゲートと手動承認は競合するアプローチではない。互いに補完し合う。パイプラインは反復的で一貫性のある技術的なチェックを処理する。人間はコンテキスト依存で状況に応じた判断を担当する。

優れたパイプラインは、自動化ゲートを使って早期に明らかな問題をふるい落とす。変更が手動承認ステップに到達する頃には、すでに一連の品質チェックを通過している。人間のレビュアーはコードがコンパイルされるか、テストが通るかを心配する必要はない。より難しい問いに集中できる。つまり、この変更を、このタイミングで、このコンテキストで実行することが正しいのかどうか、という問いだ。

実践的なチェックリスト

パイプラインのチェックポイントを設計する際は、次の質問を自問してほしい。

  • このチェックはコードで完全に定義できるか? はい → 自動化する。
  • このチェックには現在のプロダクション状態の知識が必要か? はい → 手動のままにする。
  • このチェックはビジネスタイミングやチーム調整を考慮する必要があるか? はい → 手動のままにする。
  • このチェックは純粋に技術的で反復的か? はい → 自動化する。
  • このチェックを自動化すると、貴重な人間の監視が失われるか? はい → 手動のままにする。

まとめ

自動化ゲートはスピードと一貫性をもたらす。手動承認はコンテキストと判断力を提供する。どちらも他方を代替するものではない。両方を使うようにパイプラインを構築すれば、高速に動作しつつも難しい問いをスキップしないシステムが得られる。