TL;DR: Codex CLI(o3モデル)はPR差分解析とレビューコメント自動生成に向く。GitHub Actions YAML・プロンプトテンプレート・AI/人間の役割境界を一式整備すれば、レビュー待ちボトルネックの大半を自動化できる。本記事ではその全設計を公開する。
はじめに:なぜAIコードレビューを自動化するのか
コードレビューはチーム開発において欠かせないプロセスだ。しかし多くのチームで、PRがレビュー待ちで滞留するボトルネックが発生している。
原因のひとつは、機械的にチェック可能な指摘——コーディング規約の違反、型安全性の問題、明らかなバグパターン——に人間のレビュアーのコストがかかっている点だ。このような繰り返しパターンの指摘はAIが担い、人間は設計・ビジネスロジック・チームコンテキストが必要な判断に集中すべきだ。
Codex CLIはo3推論モデルをベースにした論理分析に強みを持ち、コードレビューの自動化と相性が良い(Codex公式リポジトリ)。本記事では、Codex CLIをGitHub Actionsに組み込み、PRが作成・更新されるたびにレビューコメントを自動投稿するパイプラインの全設計を解説する。
Codex と Claude Code の比較・使い分けは Codex vs Claude Code 使い分け2026 で詳しく論じているので、本記事ではCodexのコードレビュー活用に絞る。
全体アーキテクチャ
自動コードレビューパイプラインのフローは次の通りだ。
PR作成/更新 (pull_request event)
↓
GitHub Actions ワークフロー起動
↓
PR差分取得 (git diff / GitHub REST API)
↓
Codex CLIへ差分+プロンプト送信
↓
レビューコメント生成 (JSON形式)
↓
GitHub REST API でPRコメント自動投稿
↓
人間レビュアーが最終判断
各ステップを順番に実装する。
PR差分の取得方法
git diff を使う方法
ローカル環境やCI内で差分を取得する最もシンプルな方法はgit diffだ。
# ベースブランチとの差分を取得(stat付きで変更ファイル一覧も確認)
git fetch origin main
git diff origin/main...HEAD --stat
# 差分本体(コンテキスト3行)
git diff origin/main...HEAD -U3
GitHub Actionsのチェックアウトはデフォルトでshallow cloneになるため、fetch-depth: 0を指定してフルクローンを確保する必要がある(後述のYAML例参照)。
GitHub REST API を使う方法
より細かい制御が必要な場合はGitHub REST APIを使う。PRのファイル一覧取得APIでファイル別の差分が取得できる。
# PRのファイル差分一覧取得(公式値:最大300ファイル)
curl -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/files"
レスポンスのpatchフィールドにunified diff形式の差分が含まれる。ファイルごとに処理できるため、大規模PRでも対応しやすい。
差分サイズの制御
Codexのコンテキスト長は200,000 tokens(公式値)だが、差分が大きい場合はファイル別に分割送信するのが現実的だ。変更行数が500行を超えるPRは、ファイル単位でCodexを呼び出し結果をマージする設計を推奨する(経験則)。
Codexへのプロンプト設計
プロンプトの品質がレビューの品質を直接左右する。目的を絞った構造化プロンプトが効果的だ。
基本プロンプトテンプレート
以下はコピペして使えるテンプレートだ。
以下のPR差分を技術的なコードレビューの観点で分析してください。
## レビュー対象
ファイル: {filename}
PR番号: {pr_number}
PRタイトル: {pr_title}
## 差分
```diff
{diff_content}
```
## レビュー観点
以下の観点で問題を指摘してください。指摘は具体的に、該当行番号を含めてください。
1. **バグ・ロジックエラー**: クラッシュ・データ破損・無限ループにつながる可能性
2. **セキュリティ**: SQLインジェクション、XSS、機密情報の露出、認証バイパス
3. **パフォーマンス**: N+1クエリ、不要なループ、メモリリーク
4. **可読性・保守性**: 命名の不明確さ、関数の責務過多、重複コード
## 出力形式(JSON)
{
"reviews": [
{
"path": "ファイルパス",
"line": 行番号,
"severity": "critical|warning|suggestion",
"body": "指摘内容(日本語)"
}
],
"summary": "全体サマリー(1-2文)"
}
問題がない場合は reviews を空配列にしてください。
スタイルガイド違反・コメントの書き方などの軽微な指摘は severity: suggestion で。
プロンプト設計の3原則
1. 観点を絞る: 「すべてレビューして」は精度が落ちる。バグ・セキュリティ・パフォーマンス・可読性の4軸を明示すると指摘の的中率が上がる(経験則)。
2. 出力形式を固定する: JSON形式で出力させることでパース処理が安定する。自由文で出力させると後処理が複雑になる。
3. 行番号を含める: lineフィールドを要求することでGitHub APIのline-levelコメントとの対応付けが可能になる。
レビューコメントの自動投稿(GitHub API)
Codexが生成したJSONをパースし、GitHub REST APIでPRにコメントを投稿する。
PRレビューコメント投稿API
Pull Request Review Comments APIを使う。
# PRのreview commentを投稿
curl -X POST \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments" \
-d '{
"body": "指摘内容をここに",
"commit_id": "'"$HEAD_SHA"'",
"path": "src/example.ts",
"line": 42
}'
投稿スクリプト(Node.js)
const { Octokit } = require('@octokit/rest');
async function postReviewComments(owner, repo, pullNumber, headSha, reviews) {
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
for (const review of reviews) {
if (review.severity === 'critical' || review.severity === 'warning') {
await octokit.pulls.createReviewComment({
owner,
repo,
pull_number: pullNumber,
commit_id: headSha,
path: review.path,
line: review.line,
body: `**[${review.severity.toUpperCase()}]** ${review.body}`,
});
}
}
// サマリーはIssueコメントとして投稿
await octokit.issues.createComment({
owner,
repo,
issue_number: pullNumber,
body: `## Codex自動レビュー完了\n\n${reviews.summary}`,
});
}
suggestionレベルはノイズになりやすいため、criticalとwarningのみ投稿するフィルタリングを実装している点がポイントだ。
AIと人間の役割分担:境界設計の原則
自動化で最も重要な設計判断が「何をAIに任せ、何を人間に残すか」だ。
AIが得意なこと(自動化すべき)
| カテゴリ | 具体例 |
|---|---|
| パターン検出 | 既知のバグパターン、セキュリティアンチパターン |
| 規約チェック | コーディング規約、命名規則、インポート順序 |
| 静的分析 | 型の不整合、nullチェック漏れ、未使用変数 |
| 一貫性確認 | 既存コードとのスタイル統一、APIの使い方の一貫性 |
人間が判断すべきこと(自動化しない)
| カテゴリ | 具体例 |
|---|---|
| 設計判断 | アーキテクチャの変更、責務分割の方針 |
| ビジネスロジック | 要件の正しさ、ユースケースの適切な表現 |
| チームコンテキスト | 過去の経緯、技術的負債の許容方針 |
| トレードオフ | パフォーマンスvs可読性、今vs将来 |
境界設計の原則
原則1: AIはドラフト、人間は承認者 AIのレビューを「一次フィルタ」と位置づける。AIが指摘した問題を人間が確認・承認するフローにする。AIの指摘をそのままマージ判断に使わない。
原則2: ブロッカーはAIに設定しない
AI自動レビューのFAILをマージブロッカーにすると、誤検知でデリバリーが止まる。required_status_checksには含めず、情報提供のみに留める設計を推奨する(経験則)。
原則3: AIの限界を明示する 自動投稿のサマリーに「このレビューは自動生成です。設計・ビジネスロジックの確認は人間レビュアーが行ってください」の一文を入れる。
レビュー品質の担保
誤検知対策
AIレビューの誤検知(false positive)はチームの信頼を損なう。以下の対策が有効だ。
除外パターンの設定: テストコード、自動生成コード、設定ファイルはレビュー対象外にする。
# 除外ファイルのフィルタリング
git diff origin/main...HEAD --name-only | grep -v \
-e "^tests/" \
-e "\.generated\." \
-e "pnpm-lock.yaml" \
-e "\.min\.js$"
差分コンテキストの充実: 差分だけでなく、変更前後のコンテキスト(関数全体、クラス定義)をプロンプトに含めると精度が上がる(経験則)。
フォールバック設計
Codex APIが応答しない・タイムアウトするケースに備える。
# GitHub Actions でのタイムアウト設定
- name: Run Codex review
timeout-minutes: 5
continue-on-error: true # AI失敗時もワークフローを継続
run: |
codex review --diff "$DIFF_FILE" || echo "CODEX_FAILED=true" >> $GITHUB_ENV
continue-on-error: trueでAIレビューが失敗してもCIが止まらないようにする。
GitHub Actionsへの組み込み(完全YAML例)
以下はそのままリポジトリに追加できる完全なワークフローファイルだ。
# .github/workflows/codex-review.yml
name: Codex Code Review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
codex-review:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # full clone for accurate diff
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install -g @openai/codex @octokit/rest
- name: Get PR diff
id: diff
run: |
git fetch origin ${{ github.base_ref }}
git diff origin/${{ github.base_ref }}...HEAD -U3 \
-- ':!*.lock' ':!*.generated.*' ':!tests/**' \
> /tmp/pr_diff.txt
echo "diff_size=$(wc -l < /tmp/pr_diff.txt)" >> $GITHUB_OUTPUT
- name: Skip if diff is empty
if: steps.diff.outputs.diff_size == '0'
run: echo "No reviewable diff. Skipping."
- name: Run Codex review
if: steps.diff.outputs.diff_size != '0'
timeout-minutes: 5
continue-on-error: true
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
PROMPT=$(cat <<'EOF'
以下のPR差分をレビューしてください。
問題点をJSON形式で出力してください。
出力形式: {"reviews": [{"path": "...", "line": N, "severity": "critical|warning|suggestion", "body": "..."}], "summary": "..."}
EOF
)
DIFF=$(cat /tmp/pr_diff.txt)
echo "$PROMPT\n\n$DIFF" | \
codex --model o3 --quiet > /tmp/review_result.json || \
echo '{"reviews":[],"summary":"Codex review failed"}' > /tmp/review_result.json
- name: Post review comments
if: steps.diff.outputs.diff_size != '0'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
run: |
node - <<'EOF'
const fs = require('fs');
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const result = JSON.parse(fs.readFileSync('/tmp/review_result.json', 'utf8'));
const { owner, repo, pr_number, head_sha } = {
owner: process.env.OWNER,
repo: process.env.REPO,
pr_number: parseInt(process.env.PR_NUMBER),
head_sha: process.env.HEAD_SHA,
};
async function main() {
// critical/warningのみ行レベルコメント投稿
for (const review of result.reviews || []) {
if (['critical', 'warning'].includes(review.severity)) {
try {
await octokit.pulls.createReviewComment({
owner, repo,
pull_number: pr_number,
commit_id: head_sha,
path: review.path,
line: review.line,
body: `**[${review.severity.toUpperCase()}]** ${review.body}\n\n*🤖 Codex自動レビュー*`,
});
} catch (e) {
console.error(`Failed to post comment: ${e.message}`);
}
}
}
// サマリーコメント投稿
const criticalCount = (result.reviews || []).filter(r => r.severity === 'critical').length;
const warningCount = (result.reviews || []).filter(r => r.severity === 'warning').length;
await octokit.issues.createComment({
owner, repo,
issue_number: pr_number,
body: [
'## 🤖 Codex自動レビュー結果',
'',
`- Critical: ${criticalCount}件`,
`- Warning: ${warningCount}件`,
'',
`**サマリー:** ${result.summary}`,
'',
'*このレビューは自動生成です。設計・ビジネスロジックの確認は人間レビュアーが行ってください。*',
].join('\n'),
});
}
main().catch(console.error);
EOF
YAML設計のポイント
fetch-depth: 0: shallow cloneではgit diffが正確に動かない。フルクローンが必須continue-on-error: true: AI失敗時もCIを継続。マージをブロックしないtimeout-minutes: 5: Codex APIのタイムアウトを明示的に設定permissions: pull-requests: write: PRコメント投稿に必要なパーミッション:!*.lockの差分除外: lockファイルはレビュー不要なため除外
👉 シリーズ全体像: Codex vs Claude Code 使い分け2026
まとめ・次のステップ
Codex CLIによるPR自動レビューの設計要素をまとめると:
- 差分取得:
git diffで十分。大規模PRはファイル単位で分割 - プロンプト: 観点を4軸に絞り、JSON出力を強制する
- 投稿: critical/warningのみフィルタリングしてコメント投稿
- 境界: AIはドラフト作成、人間が承認。AIをブロッカーにしない
- フォールバック:
continue-on-error: trueでAI障害がデリバリーに影響しないように
まず試すなら、上記のYAMLをリポジトリに追加し、OPENAI_API_KEYをSecretsに設定するだけで動作する。最初はdraftモードで実際のレビュー品質を確認し、チームで運用ルールを合意してから本番運用に移行するのを推奨する(経験則)。
AIコードレビューの別アプローチとして、知見の資産化に重きを置いたriver-reviewerの設計思想は AIコードレビューを導入する実践ガイド を参照してほしい。また、AIとペアプログラミングする際の役割分担パターンは AIペアプログラミング実践パターン にまとめている。
FAQ
Codexでコードレビューを自動化する方法は?
Codex CLIにgit diffで取得したPR差分をプロンプトとして渡し、問題点をJSON形式で出力させる。出力をGitHub REST APIで解析してPRコメントとして投稿するスクリプトをGitHub Actionsに組み込むことで自動化できる。本記事の完全YAMLサンプルをそのまま使用できる。
AIによるコードレビューの精度はどの程度ですか?
Codex(o3モデル)はバグ・セキュリティ・パフォーマンスの既知パターン検出に高い精度を示す。ただし設計判断・ビジネスロジックの妥当性評価は苦手で、誤検知も一定割合で発生する(経験則)。人間レビュアーの一次フィルタとして使うのが現実的な運用だ。
GitHub ActionsにCodexを組み込むにはどうすればよいですか?
pull_requestイベントをトリガーにして、fetch-depth: 0でフルクローン後にgit diffを取得し、Codex CLIに渡す。OPENAI_API_KEYをRepositoryのSecretsに設定し、permissions: pull-requests: writeでコメント投稿権限を付与する。本記事の完全YAMLをコピーして.github/workflows/codex-review.ymlとして保存するだけで動作する。
AIレビューで何を自動化し何を人間に残すべきですか?
パターン検出(既知バグ・セキュリティアンチパターン・規約違反)はAIに任せる。設計判断・ビジネスロジックの正しさ・チームコンテキストが必要な判断は人間に残す。AIのレビューはマージブロッカーにせず情報提供に留め、最終承認を人間が行う運用を推奨する(経験則)。
Codex CLIのインストールと認証方法は?
npm install -g @openai/codex
export OPENAI_API_KEY=your-api-key
codex --help
Codex公式リポジトリにインストール手順と最新仕様が掲載されている。
References
- OpenAI Codex 公式リポジトリ — CLI仕様・セキュリティモデル
- GitHub REST API: Pull Request Review Comments — PRコメント投稿API
- GitHub REST API: List Pull Requests Files — PR差分取得API
- GitHub Actions: actions/checkout — fetch-depth設定
- GitHub Actions: Encrypted Secrets — API Key管理
- Octokit REST.js — GitHub API Node.jsクライアント
