- Published on
Issueからデプロイまで — AIがレビューしCI/CDが検証・デプロイする自動化パイプラインを作る (2025)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
プロローグ — 線(line)ではなくループ(loop)
前回の記事では、AI開発自動化の部品を扱った — どんなエージェントがあり、GitHubとどう連携し、チケットをどう任せるか。
今回の記事は、その部品をひとつのパイプラインに組み立てる。目標はこれだ:
人間がIssueをひとつ上げる。席を外す。しばらくして検証済みのデプロイがプロダクションに上がっている。人間が介入したのはただひとつ — マージボタンを押した決定だけだ。
そしてさらに重要なこと: これは線ではなくループだ。デプロイが終わりではない。モニタリングが異常を検知すれば自動rollbackし、その事象が新しいIssueとなってパイプラインの入口に再び入ってくる。 システムが自分自身を直す。
この記事は、そのループを7つのステージに分割し、各ステージのゲートを設計し、GitHub Actionsですべて実装する。核心原則はひとつだ:
「作業は自動化し、決定はゲートする (Automate the work, gate the decisions)。」
AIにコードを書かせ、レビューさせ、デプロイさせる。ただし取り返しのつかない決定(プロダクションマージ、スキーマ変更、セキュリティロジック)には、必ず人間または強力な自動検証を立てる。
0章 · パイプライン全体の鳥瞰図
まず大きな絵。7つのステージと、各ステージを誰がオーナーするか。
┌────────────────────────────────────────────────────────────────┐
│ │
│ [S1] Issue ──ai-readyラベル──▶ AIエージェント ──▶ Draft PR │
│ ▲ │ │
│ │ ▼ │
│ │ [S2] AIコードレビュー │
│ │ (生成≠レビュー) │
│ │ │ │
│ │ ▼ │
│ │ [S3] CI検証ゲート │
│ │ lint·type·test·build·E2E │
│ │ │ │
│ │ ┌── 失敗 ──────┤ │
│ │ ▼ ▼ 通過 │
│ │ AI自己修正 [S4] Human Gate │
│ │ (ログを読み再push) マージ決定 │
│ │ │ │
│ │ ▼ │
│ │ [S5] CD: Preview │
│ │ → Canary → Production │
│ │ │ │
│ │ ▼ │
│ │ [S6] 自動検証 │
│ │ smoke·E2E·SLOゲート │
│ │ │ │
│ │ ┌── 失敗 ──────┤ │
│ │ ▼ ▼ 通過 │
│ └──── 自動Issue生成 ◀─ [S7] モニタリング & フィードバック │
│ (自動rollback + 事象化) デプロイ後観測、rollbackトリガー │
│ │
└────────────────────────────────────────────────────────────────┘
| ステージ | 名前 | オーナー | 出力 |
|---|---|---|---|
| S1 | Issue → PR | AIエージェント | Draft PR |
| S2 | AIコードレビュー | AIレビュアー (生成と別のモデル) | インラインコメント + APPROVE/REQUEST_CHANGES |
| S3 | CI検証ゲート | CIシステム | 青信号/赤信号 |
| S4 | Human Gate | 人間 | マージ決定 |
| S5 | CDデプロイ | CDシステム | Preview → Canary → Production |
| S6 | 自動検証 | 検証システム | 昇格またはrollback |
| S7 | モニタリング & フィードバック | 観測システム | 正常または自動Issue |
この記事の残りは、各ステージをひとつずつ深く掘る。
1章 · パイプライン設計5原則
実装の前に原則を釘付けにする。これが揺らぐとパイプラインが危険になる。
原則1 — すべてのステージはfail-closed
ステージが失敗するか、判断が不確実なら止まる。 通過させない。AIレビューが迷えば → REQUEST_CHANGES。CIがflakyなら → 赤信号。検証が曖昧なら → rollback。疑わしければ進めない。
原則2 — すべてのステージは取り返しがつかなければならない
PRはclose、マージはrevert、デプロイはrollback。各ステージに「キャンセルボタン」がなければ、そのステージは自動化してはいけない。
原則3 — すべてのステージは観測可能でなければならない
誰が・いつ・何を・なぜしたかのログが残る。AIがしたことは特に。デバッグ不可能な自動化は時限爆弾だ。
原則4 — 冪等性 (Idempotency)
同じIssueが二度トリガーされてもPRが二つできてはいけない。同じコミットが二度デプロイされても安全でなければならない。リトライが安全でこそ自動化が安全だ。
原則5 — 信頼の梯子 (Trust Ladder)
最初からすべてを自動化しない。低リスク・高頻度の作業から自動化し、成功率データが溜まれば自動化の範囲を広げる。ドキュメント修正の自動マージ → 依存バンプの自動マージ → … 一段ずつ。
2章 · S1 — Issue → PR (生成ステージ)
前回の記事で扱った部分なので核心だけ。ai-readyラベルがトリガー、AIエージェントがブランチを作り実装しDraft PRを開く。
このステージの本当の目標は「コードを書くこと」ではなく**「レビュー可能なPRを生むこと」**だ。後続のすべてのステージがPR品質に依存する。
PRが「レビュー可能に生まれる」条件
- Draft状態で生成 — 人間が「Ready for review」に昇格する前はマージ不可。
- Issueリンク — PR本文に
Closes #123。マージ時にIssueを自動close。 - 作業サマリー — エージェントが「何を・なぜ」したかを本文に残す。レビュアーの出発点。
- 一貫したPRタイトル —
[AI] fix: ...のように。後続ステージがタイトルで分岐する。 ai-generatedラベル — 追跡用。
冪等性 — 重複PRの防止
# 同じissueにPRがすでにあれば新規に作らない
- name: Check existing PR
id: check
run: |
EXISTING=$(gh pr list --search "in:title #${{ github.event.issue.number }}" --json number --jq 'length')
echo "exists=$EXISTING" >> "$GITHUB_OUTPUT"
- name: Run agent
if: steps.check.outputs.exists == '0'
uses: anthropics/claude-code-action@v1
# ...
3章 · S2 — AIコードレビュー自動化 (核心ステージ)
ここがこのパイプラインの心臓だ。人間レビューの前にAIレビューを一枚挟む。
なぜ人間レビューの前にAIレビューなのか
- ノイズフィルター — 明白なミス(漏れたエラー処理、型不一致、コンベンション違反)を人間が見る前に捕える。
- 人間レビュー時間の節約 — 人間は「これは正しいアプローチか」のような判断に集中。細かい手直しはAIが。
- 24/7 — PRが深夜に上がっても即座にレビュー。
鉄則: 生成 ≠ レビュー (別のモデル、別のエージェント)
PRを作ったエージェントに自分のPRをレビューさせるな。 自分のコードの死角は自分では見えない。可能なら別のモデルでレビューする。Claudeが書いたなら別のツールがレビューするか、最低でも別セッション・別プロンプトで。
生成エージェント (Claude/Copilot) ──▶ PR
│
レビューエージェント (別モデル/ツール) ──▶ レビューコメント
│
人間 ────────────────────────────▶ 最終決定
ツールの地形図
| ツール | 形態 | 特徴 |
|---|---|---|
| CodeRabbit | GitHub App | PRごとに自動レビュー、.coderabbit.yaml設定、サマリー+インライン |
| Greptile | GitHub App | コードベース全体のコンテキストに基づくレビュー |
| GitHub Copilotレビュー | 内蔵 | CopilotをPRレビュアーに指定可能 |
| Claude Code Action | Actions | @claudeまたはワークフローでレビュー、カスタマイズが強力 |
AIレビューがよく捕えるもの / 捕えられないもの
| よく捕える | 捕えられない |
|---|---|
| 漏れたnull·エラー処理 | 「これは正しいアーキテクチャか」 |
| コンベンション·ネーミング違反 | ビジネス要件を満たすか否か |
| 明白なセキュリティパターン (SQLi、ハードコードされたシークレット) | ドメイン特化の微妙なバグ |
| テストカバレッジの空白 | パフォーマンスの微妙なトレードオフ |
| よくあるバグパターン | チームの暗黙の文脈 |
→ だから人間ゲート(S4)が必要だ。 AIレビューは人間を代替せず、人間の負担を減らす。
実装 — Claude Code Actionでレビュー
name: AI Review
on:
pull_request:
types: [opened, synchronize, ready_for_review]
jobs:
ai-review:
# draftでないときだけ — 作業中のPRはレビューしない
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
このPRをレビューせよ。次に集中:
- 正確性: ロジックのバグ、エッジケース、漏れたエラー処理
- セキュリティ: 入力検証、シークレット、権限
- テスト: 変更に対するカバレッジが十分か
- コンベンション: CLAUDE.md に従っているか
問題は該当する行にインラインコメントで残せ。
最後にサマリーとともに APPROVE または REQUEST_CHANGES を明示せよ。
些細なスタイルは nit: で表示し、人間が無視できるようにせよ。
AIレビューを「必須チェック」にする
レビューがコメントだけ残すと無視される。ステータスチェック(status check)にしてブランチ保護ルールに入れれば、REQUEST_CHANGESのときマージ自体が止まる。レビューアクションがGitHub Checks APIでpass/failを報告するよう構成する。
4章 · S3 — CI検証ゲート
AIが書いたコードを機械が検証する段階。CIが弱いとこのパイプライン全体が弱い。
階層化されたチェック
速い ──────────────────────────────────▶ 遅い
lint → typecheck → unit test → build → integration → E2E
│ │ │ │ │ │
秒単位 秒単位 秒〜分 分 分 分〜十分
速いチェックを前に置いて速く失敗させる。lintで壊れることをE2Eまで行って知る必要はない。
CIを「AIが読めるように」する
ここが核心だがよく見落とす。CIの失敗メッセージが親切ならAIが自分で直す。
Error: test failed(悪い) →Error: expected status 200, got 401 at auth.test.ts:42(良い)- 失敗したコマンド、ファイル·行、期待値·実際値を出力せよ。
- AIエージェントはこのログを読み、次のコミットで自己修正する。
自己修正ループ
PR push ──▶ CI実行 ──▶ 失敗
│
▼
エージェントがCIログを読む
│
▼
原因把握 → 修正コミットをpush
│
▼
CI再実行 ──▶ 通過
このループに上限を置く — 3回試行しても赤信号なら人間を呼ぶ。無限の自己修正はコスト爆弾だ。
# CI失敗時にエージェントへログを渡し修正を試みる — ただしラベルで回数制限
- name: Self-heal on CI failure
if: failure() && !contains(github.event.pull_request.labels.*.name, 'ai-heal-exhausted')
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
CIが失敗した。下のログを読み、原因を直してコミットせよ。
推測せず、ログが指し示すものだけを直せ。
ブランチ保護 — ゲートを強制
Settings → Branches → main 保護ルール:
✅ Require status checks: ci/lint, ci/test, ci/build, ai-review
✅ Require branches to be up to date before merging
✅ Require a pull request before merging
✅ Require approvals: 1+ (S4 人間ゲート)
✅ Dismiss stale approvals when new commits pushed
✅ Do not allow bypassing the above
5章 · S4 — Human Gate (人間が守る関門)
自動化の核心は逆説的に**「人間がどこを守るか」を明確にすること**だ。
人間が必ず決定しなければならないこと
- マージ決定そのもの — 「これをmainに入れる」という責任は人間が負う。
- アーキテクチャの方向 — 「このアプローチは正しいか」はAIが判断できない。
- ビジネス要件の充足 — Issueの意図を本当に満たしたか。
- セキュリティ·データ機密の変更 — ミスのコストが大きい領域。
人間レビューを速くするもの
S4がボトルネックにならないためには、人間がPRを受け取ったときにすでに:
- ✅ AIレビューが終わっている (細かい手直しは全部処理済み)
- ✅ CIが青信号だ (機械検証を通過)
- ✅ PRが小さい (レビュー可能なサイズ)
- ✅ 説明が良い (何を・なぜ)
- ✅ PreviewデプロイURLが付いている (実際に押して試せる)
そうすれば人間レビューは**「判断」だけ**すればよい。5分で終わる。
自動マージ — いつOKか
GitHubのauto-mergeは「すべての必須チェック通過 + 必須承認完了時に自動マージ」だ。危険だが、特定の変更タイプには安全だ。
| 自動マージOK | 自動マージ禁止 |
|---|---|
| ドキュメント·コメント修正 | アプリケーションロジック |
| 依存パッチバンプ (CI通過時) | スキーママイグレーション |
| lint·フォーマット自動修正 | セキュリティ·認証ロジック |
| 生成された型·SDK更新 | インフラ·IaC |
# 依存PRでCI通過 + AIレビューAPPROVEなら自動マージ有効化
- name: Enable auto-merge for safe deps
if: |
contains(github.event.pull_request.labels.*.name, 'dependencies') &&
github.event.pull_request.user.login == 'dependabot[bot]'
run: gh pr merge --auto --squash "${{ github.event.pull_request.number }}"
エスカレーション経路
AI(生成であれレビューであれ)が不確実なら人間をタグ付けする。「この変更は認証ロジックに触れます — セキュリティ担当者のレビューが必要」のようなコメントを自動で残し、needs-humanラベルを付ける。
6章 · S5 — CD: Preview → Canary → Production
マージされた。さあデプロイ。核心は一度に全部デプロイしないことだ。
Previewデプロイ — PRごとに
PRが開かれると隔離された実環境にデプロイし固有URLを与える。Vercel·Netlify·Cloudflareはデフォルトで提供、自前インフラはPRごとのネームスペースで実装。
→ S4の人間レビュアーがコードではなく動作する成果物を見る。AIレビュアーもPreview URLにE2Eを回せる。
マージ後 — 段階的デリバリー (Progressive Delivery)
main マージ
│
▼
Canaryデプロイ (トラフィック5%)
│
▼ [S6 自動検証]
smoke test + SLO観測 (5〜15分)
│
├── 失敗 ──▶ 自動rollback (Canary除去)
│
▼ 通過
Production昇格 (トラフィック100%)
- Canary — 新バージョンにトラフィックの一部(5〜10%)だけ。問題が出ても影響範囲が小さい。
- Feature Flag — コードはデプロイするが機能はオフのまま。オンにするのは別の決定。
- 環境昇格 — dev → staging → prod。各段階がゲート。
GitHub Environmentsでゲートを実装
name: Deploy
on:
pull_request:
types: [closed]
branches: [main]
jobs:
deploy-canary:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
environment: canary # 保護ルール: なし (自動)
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh canary
promote-production:
needs: [deploy-canary, verify-canary]
runs-on: ubuntu-latest
environment: production # 保護ルール: required reviewers = 人間ゲート
steps:
- run: ./scripts/deploy.sh production
environment: productionにrequired reviewersをかければ、プロダクション昇格に人間の承認が強制される — ワークフローの中に埋め込まれたもうひとつのHuman Gateだ。
7章 · S6 — 自動検証 (Auto-Verification)
デプロイしたから終わりではない。デプロイされたものが実際に動作するかを機械が確認する。
デプロイ後の検証層
| 検証 | 何を | いつ |
|---|---|---|
| Smoke test | 核心経路をいくつか (ログイン、ヘルスチェック) | デプロイ直後すぐ |
| E2E | 主要なユーザーシナリオ | Canary段階 |
| Synthetic monitoring | 外部から周期的にping (Checkly、Datadog) | 継続 |
| SLO観測 | エラー率·レイテンシ·可用性 | Canaryウィンドウの間 |
| Visual regression | UIのピクセル差分 | Preview/Canary |
検証ゲート — Canaryを昇格するかrollbackするか
verify-canary:
needs: deploy-canary
runs-on: ubuntu-latest
outputs:
verdict: ${{ steps.gate.outputs.verdict }}
steps:
- name: Smoke test
run: ./scripts/smoke-test.sh https://canary.example.com
- name: Observe SLO for 10 minutes
id: gate
run: |
sleep 600
ERROR_RATE=$(curl -s "$METRICS_API/error-rate?env=canary&window=10m")
P99=$(curl -s "$METRICS_API/latency-p99?env=canary&window=10m")
# エラー率1%超過またはp99 500ms超過ならfail
if (( $(echo "$ERROR_RATE > 0.01" | bc -l) )); then
echo "verdict=rollback" >> "$GITHUB_OUTPUT"; exit 1
fi
echo "verdict=promote" >> "$GITHUB_OUTPUT"
rollback-canary:
needs: verify-canary
if: failure()
runs-on: ubuntu-latest
steps:
- run: ./scripts/rollback.sh canary
検証が失敗すれば → Canary自動除去。プロダクショントラフィックはそもそも5%しか影響を受けておらず、それも即座に回収される。
8章 · S7 — モニタリング & フィードバックループ (ループを閉じる)
ここでパイプラインが線からループになる。 デプロイ後もシステムは見守り続ける。
自動rollbackトリガー
プロダクション昇格後も観測は続く。SLOを破れば自動rollback。
- エラーバジェット消尽 (error budget burn rate) — 速く燃え尽きればrollback。
- レイテンシ急騰 — p99が閾値を超過。
- 核心ビジネスメトリクスの低下 — 決済成功率、登録コンバージョン率など。
自己治癒ループ — 事象が再びIssueになる
これがループの核心だ。自動rollbackが起これば、その事象を新しいIssueにしてパイプラインの入口(S1)に戻す。
name: Monitor & Auto-Rollback
on:
schedule:
- cron: '*/5 * * * *' # 5分ごとにSLOチェック
workflow_run:
workflows: ["Deploy"]
types: [completed]
jobs:
slo-check:
runs-on: ubuntu-latest
steps:
- name: Check production SLO
id: slo
run: |
BURN=$(curl -s "$METRICS_API/error-budget-burn?env=prod&window=1h")
echo "burn=$BURN" >> "$GITHUB_OUTPUT"
- name: Rollback + file issue if breaching
if: ${{ steps.slo.outputs.burn > 2.0 }}
run: |
./scripts/rollback.sh production
gh issue create \
--title "Auto-rollback: error budget burn rate ${{ steps.slo.outputs.burn }}" \
--label "ai-ready,incident,priority-high" \
--body "プロダクションSLO違反で自動rollbackした。
最後のデプロイ: ${{ github.sha }}
burn rate: ${{ steps.slo.outputs.burn }}
エージェントはrollbackされたコミットのdiffを分析し原因を診断し、
修正PRを提出せよ。"
このIssueにai-readyラベルが付いているので → S1が再びトリガーされる。 AIがrollbackされたコミットを分析し、修正PRを作り、AIレビュー → CI → 人間ゲート → 再デプロイ。ループが閉じた。
閉じたループの意味
Issue ──▶ PR ──▶ レビュー ──▶ CI ──▶ マージ ──▶ デプロイ ──▶ 検証 ──▶ モニター
▲ │
└──────────────── 事象が新しいIssueへ ◀───────────────────────┘
システムが自分が出した問題を自ら入力として受け取り直す。人間は依然としてマージゲートを守るが、検知·診断·修正着手·再デプロイの反復労働から解放される。
9章 · 全体実装 — GitHub Actionsで紡ぐ
ここまでのステージを実際のファイルへ。5つのワークフローがイベントで連結される。
ワークフロー地図
| ファイル | トリガー | 役割 |
|---|---|---|
ai-resolve.yml | issues: labeled | S1: Issue → PR |
ai-review.yml | pull_request: opened/synchronize | S2: AIレビュー |
ci.yml | pull_request: opened/synchronize | S3: 検証ゲート |
deploy.yml | pull_request: closed (merged) | S5: Canary → Production |
monitor.yml | schedule + workflow_run | S6/S7: 検証·rollback·フィードバック |
イベントでどう連結されるか
GitHub Actionsには中央オーケストレーターがない。イベントがすなわち連結線だ。
issue.labeled('ai-ready') ──▶ ai-resolve.yml ──▶ (PR生成)
│
pull_request.opened ◀──────────────────────────────────┘
├──▶ ai-review.yml (AIレビュー → チェック報告)
└──▶ ci.yml (検証 → チェック報告)
│
[ブランチ保護: すべてのチェック + 人間承認待ち] │
▼
pull_request.closed(merged) ──▶ deploy.yml ──▶ (Canary → 検証 → Production)
│
workflow_run('Deploy' completed) ──▶ monitor.yml │
schedule('*/5') ──▶ monitor.yml ◀─────┘
└──▶ SLO違反時: rollback + issue.create('ai-ready')
│
└──▶ (再びai-resolve.yml — ループ完成)
ai-resolve.yml — S1
name: AI Resolve
on:
issues:
types: [labeled]
jobs:
resolve:
if: github.event.label.name == 'ai-ready'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Skip if PR already exists
id: dedup
run: |
N=$(gh pr list --search "#${{ github.event.issue.number }} in:body" --json number --jq 'length')
echo "exists=$N" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run agent
if: steps.dedup.outputs.exists == '0'
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
Issue #${{ github.event.issue.number }}: ${{ github.event.issue.title }}
${{ github.event.issue.body }}
このissueを実装せよ。ブランチを作り、変更し、テストを通し、
"Closes #${{ github.event.issue.number }}" を含む Draft PR を開け。
CLAUDE.md コンベンションに従い、PR本文に何を・なぜしたかを要約せよ。
ci.yml — S3
name: CI
on:
pull_request:
types: [opened, synchronize, ready_for_review]
concurrency:
group: ci-${{ github.event.pull_request.number }}
cancel-in-progress: true # 新しいpush時に以前の実行をキャンセル — コスト削減
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint # 速いものから先に
- run: pnpm typecheck
- run: pnpm test
- run: pnpm build
deploy.yml — S5 (6章参照、核心だけ)
name: Deploy
on:
pull_request:
types: [closed]
branches: [main]
jobs:
canary:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
environment: canary
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh canary
verify:
needs: canary
runs-on: ubuntu-latest
steps:
- run: ./scripts/smoke-test.sh https://canary.example.com
- run: ./scripts/observe-slo.sh canary 600 # 10分観測
production:
needs: verify
runs-on: ubuntu-latest
environment: production # required reviewers = Human Gate
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh production
rollback:
needs: [canary, verify]
if: failure()
runs-on: ubuntu-latest
steps:
- run: ./scripts/rollback.sh canary
リポ設定チェックリスト
- Secrets:
ANTHROPIC_API_KEY、デプロイ資格情報。 - Environments:
canary(自動)、production(required reviewers指定)。 - Branch protection (main): 必須チェックに
ci/verify、ai-reviewを含める。必須承認1+。 - Labels:
ai-ready、ai-generated、needs-human、incident、dependencies。
10章 · 決定ゲートマトリクス — 何を自動化し何を人間が
パイプラインの本当の設計は「どこまで自動化するか」だ。変更タイプごとにゲートを変える。
| 変更タイプ | AI生成 | AIレビュー | CI | 人間ゲート | 自動マージ | デプロイ |
|---|---|---|---|---|---|---|
| ドキュメント·コメント | ✅ | ✅ | ✅ | 任意 | ✅ 可能 | 自動 |
| 依存パッチバンプ | ✅ | ✅ | ✅ 必須 | 任意 | ✅ 条件付き | Canary自動 |
| バグフィックス (狭い範囲) | ✅ | ✅ | ✅ | ✅ 1名 | ❌ | Canary→自動昇格 |
| 機能追加 | ✅ | ✅ | ✅ | ✅ 1名+ | ❌ | Canary→人間昇格 |
| リファクタリング | ✅ | ✅ | ✅ + カバレッジ | ✅ 1名 | ❌ | Canary→自動昇格 |
| DBマイグレーション | ⚠️ AI補助 | ✅ | ✅ | ✅ 必須 | ❌ | 人間トリガー |
| セキュリティ·認証ロジック | ⚠️ AI補助 | ✅ | ✅ | ✅ 2名 | ❌ | 人間トリガー |
| インフラ·IaC | ⚠️ AI補助 | ✅ | ✅ plan diff | ✅ 必須 | ❌ | 人間トリガー |
凡例: ✅ 自動 / ⚠️ AIは補助のみ、人間が主導 / ❌ しない
信頼の梯子を登る方法
最初はすべてのマスを保守的に始める — 自動マージは全部オフ、デプロイは全部人間トリガー。そしてデータで一段ずつ上げる:
- ドキュメントPRの自動マージを一ヶ月オンにしてみる → 事故0件 → 維持。
- 依存バンプの自動マージをオンにする → CI通過率·rollback率を観察 → 安定していれば維持。
- バグフィックスのCanary自動昇格をオンにする → escape rate(見逃したバグ)を観察。
- …
成功率データなしに自動化の範囲を広げるな。 信頼は積み立てるものであって宣言するものではない。
11章 · 安全装置 & 失敗モード
自動化が速いほど事故も速い。各失敗モードに防御をかける。
「AIがAIを承認」問題
最も危険なアンチパターン。生成エージェントが自分のPRをレビュー·承認すれば検証が0だ。防御:
- 生成とレビューは別のツール/モデル。
- AIレビューのAPPROVEは人間承認を代替できない — ブランチ保護の「必須承認」は必ず人間アカウント。
- ボットアカウントの承認は必須承認数から除外する設定。
パイプラインを通じたPrompt Injection
Issue本文、PRコメント、コード、CIログ — すべてエージェントの入力だ。攻撃者がそこに命令を仕込める。
- 外部ユーザーのIssue/PRは自動トリガー禁止 — メンバーが付けた
ai-readyラベルだけがトリガー。 - エージェントトークンは最小権限 — プロダクション·シークレットへのアクセス不可。
- ワークフローファイルの変更検知 — PRが
.github/workflows/に触れたら無条件で人間の必須レビュー。
コスト暴走
- ステップ上限、自己修正回数上限(3回)。
concurrency+cancel-in-progressで重複実行を除去。- 同時実行エージェント数の制限。
- 日次/週次のコストアラーム。
すべてのステージはfail-closed + rollback
| ステージ | 失敗時 | rollback手段 |
|---|---|---|
| S1 生成 | PRを作らない、issueにコメント | — |
| S2 レビュー | REQUEST_CHANGES、マージ遮断 | — |
| S3 CI | 赤信号、マージ遮断 | — |
| S4 人間 | マージしない | — |
| S5 デプロイ | Canary段階で中断 | rollback.sh canary |
| S6 検証 | 昇格しない | Canary除去 |
| S7 モニター | 自動rollback + 事象化 | rollback.sh production |
監査 — 誰が·いつ·何を
すべてのステージの行為がログに残らなければならない。AIがしたことはコミットトレーラー(Co-Authored-By:)、PRラベル(ai-generated)、ワークフロー実行記録で追跡可能でなければならない。「なぜこれがデプロイされたのか」に答えられないなら、その自動化はオフにする方がよい。
12章 · 運用 — メトリクスと漸進的な信頼
パイプラインをオンにしたから終わりではない。測定してチューニングする。
追跡するメトリクス
| メトリクス | 意味 | 健全な方向 |
|---|---|---|
| Lead time (Issue→デプロイ) | 一周回る時間 | ↓ |
| % auto-merged | 人間なしでマージされた割合 | ↑ (ただしescape rateを見ながら) |
| AIレビュー精度 | AIレビューの指摘のうち実際に有効な割合 | ↑ |
| Escape rate | パイプラインを通過したバグの割合 | ↓ (最も重要) |
| Rollback rate | デプロイ中にrollbackされた割合 | 低く安定的 |
| 自己修正成功率 | CI失敗後にAIが直した割合 | ↑ |
| 人間レビュー待ち時間 | S4のキュー待ち | ↓ |
DORAメトリクスをこのパイプラインに
伝統的なDORA4指標がそのまま適用される — Deployment Frequency、Lead Time、Change Failure Rate、MTTR。AIパイプラインの目標はThroughputを上げつつStabilityを壊さないことだ。Change Failure Rateが上がれば自動化の範囲を減らせ。
ボトルネックはほぼ常にS4
エージェント10個がPR10個を5分で作っても、人間レビューが1日5個ならスループットは1日5個だ。生成速度ではなくレビュー容量が本当の上限だ。 だからチューニングの焦点は:
- AIレビュー(S2)を強化して人間レビューの負担を減らす。
- PRをより小さく分割してレビューを速くする。
- 低リスク変更の自動マージを(データを見ながら)増やしてS4を迂回させる。
漸進的な信頼 — データで梯子を登る
毎週メトリクスを見る。Escape rateが低く安定的なら → 信頼の梯子(10章)を一段上げる。Escape rateが上がるかRollback rateが跳ねれば → 一段下げる。自動化の範囲は固定値ではなく、データで調節するダイヤルだ。
エピローグ — パイプラインがすなわちチームの形
この記事のパイプラインをすべて実装すると、チームの働き方が変わる。
- 開発者はコードを少なくタイプし、Issueをよく書きPRをよくレビューする。
- 細かい手直しのレビューはAIが、判断のレビューは人間が。
- 検知·診断·修正着手·再デプロイの反復労働はシステムが。
- 人間は取り返しのつかない決定のゲートを守る。
核心の洞察を3つに整理する。
-
線ではなくループだ。 デプロイが終わりではない。モニタリングが事象を捉えて再びIssueにすれば、システムが自分の問題を入力として受け取り直す。
-
「作業は自動化、決定はゲート。」 AIにコードを書かせレビューさせデプロイさせる。ただしマージ·スキーマ·セキュリティのような不可逆な決定には人間または強力な自動検証を立てる。fail-closedがデフォルト値だ。
-
信頼は積み立てられる。 最初からすべてを自動化せず、低リスク作業から、メトリクス(特にescape rate)を見ながら一段ずつ上げる。自動化の範囲はデータで調節するダイヤルだ。
逆説的だが、このすべての自動化の最終目的は人間を仕事から外すことではなく、人間を最も重要なところ — 判断と決定 — に集中させることだ。パイプラインが反復労働を吸収すれば、チームの思考は「どう作るか」から「何を・なぜ作るか」へと上がる。
14項目チェックリスト
- 7つのステージを全部識別し、各オーナーを決めたか?
- すべてのステージがfail-closedか?
- すべてのステージにrollback/キャンセル手段があるか?
- 生成エージェントとレビューエージェントが分離されているか (別のモデル)?
- AIレビューが必須ステータスチェックにかかっているか?
- CIの失敗メッセージがAIが読めるほど親切か?
- 自己修正ループに回数上限があるか?
- ブランチ保護に必須チェック + 人間承認が強制されているか?
- 人間承認はボットではなく人間アカウントだけがカウントされるか?
- Preview·Canary·Productionが段階的に分離されているか?
production環境にrequired reviewersがかかっているか?- 自動検証(smoke·SLO)がCanary昇格をゲートするか?
- SLO違反時に自動rollback + 自動Issue生成が行われるか (ループ)?
- Escape rateを追跡し、そのデータで自動化の範囲を調節しているか?
アンチパターン10種
- 生成エージェントが自分のPRをレビュー·承認。
- AIレビューのAPPROVEを人間承認としてカウント。
- アプリケーションロジックを自動マージ。
- マージ即座に100%プロダクションデプロイ (Canaryなし)。
- デプロイ後の検証なし (smoke·SLOゲートの欠如)。
- 自動rollbackはあるのに事象がIssueに戻らない (ループが閉じない)。
- CIの失敗メッセージが不親切でAIの自己修正が不可能。
- 自己修正ループに上限なし → コスト爆弾。
- 外部ユーザーのIssueがパイプラインを自動トリガー。
- Escape rateを測定せずに自動化の範囲だけ広げる。
次の記事の予告
次の記事の候補: AIコードレビュアーを自分で作る — チームコンベンションを学習するカスタムレビューボット、Progressive Delivery深掘り — Argo Rollouts·FlaggerでSLOベースの自動昇格、エージェントオーケストレーション — LangGraphでマルチステージパイプラインをステートマシンに。
「最高のパイプラインは人間を代替しない。人間が決定だけをするように、残りのすべての反復を吸収する。」
— Issueからデプロイまで、自動化パイプラインを作る、おわり。