AIコーディング 2026.06.14
GitHub ActionsとClaude/ChatGPT APIでコードレビューを自動化する【2026年版完全ガイド】
自動コードレビューの全体アーキテクチャ
PRオープン → GitHub Actions起動 → git diff取得
→ Python スクリプト → Claude Haiku / GPT-4o mini API
→ レビューコメント → GitHub PR コメントとして投稿
Step 1: APIキーをGitHub Secretsに登録する
リポジトリ → Settings → Secrets and variables → Actions → New repository secret
ANTHROPIC_API_KEY = sk-ant-xxxxx (Claude用)
OPENAI_API_KEY = sk-xxxxx (GPT-4o mini用・オプション)
GITHUB_TOKEN は Actions が自動で提供
Step 2: GitHub Actionsワークフロー
# .github/workflows/ai-code-review.yml
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
ai-review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: pip install anthropic PyGithub
- name: Run AI code review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO_NAME: ${{ github.repository }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: python .github/scripts/code_review.py
Step 3: コードレビュースクリプト
# .github/scripts/code_review.py
import os
import subprocess
import anthropic
from github import Github
ANTHROPIC_API_KEY = os.environ["ANTHROPIC_API_KEY"]
GITHUB_TOKEN = os.environ["GITHUB_TOKEN"]
REPO_NAME = os.environ["REPO_NAME"]
PR_NUMBER = int(os.environ["PR_NUMBER"])
BASE_SHA = os.environ["BASE_SHA"]
HEAD_SHA = os.environ["HEAD_SHA"]
client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)
REVIEW_PROMPT = """あなたはシニアエンジニアです。以下のコード差分をレビューしてください。
【レビュー観点】
- バグや潜在的なエラー(最優先で指摘)
- セキュリティの問題(SQLインジェクション・XSS等)
- パフォーマンスの問題
- コードの可読性・保守性
【出力形式】
- 問題があれば箇条書きで指摘(日本語)
- 重大度を [重大/警告/提案] で先頭に付ける
- 問題がなければ「✅ 問題なし」とだけ出力
- コードの行数は20行以内で簡潔に
コード差分:
{diff}
"""
def should_review(filename: str) -> bool:
"""レビュー対象ファイルか判定する"""
INCLUDE = {".py", ".ts", ".tsx", ".js", ".jsx", ".go", ".rb"}
EXCLUDE_PATTERNS = ["test_", "_test.", ".spec.", "migrations/", "package-lock"]
ext = os.path.splitext(filename)[1]
if ext not in INCLUDE:
return False
return not any(pat in filename for pat in EXCLUDE_PATTERNS)
def get_diff() -> list[dict]:
"""変更ファイルと差分を取得する"""
result = subprocess.run(
["git", "diff", f"{BASE_SHA}...{HEAD_SHA}", "--name-only"],
capture_output=True, text=True
)
files = [f for f in result.stdout.strip().split("\n") if f and should_review(f)]
diffs = []
for filepath in files[:10]: # 最大10ファイル
diff_result = subprocess.run(
["git", "diff", f"{BASE_SHA}...{HEAD_SHA}", "--", filepath],
capture_output=True, text=True
)
diff = diff_result.stdout[:3000] # 3000文字に制限
if diff:
diffs.append({"file": filepath, "diff": diff})
return diffs
def review_file(filepath: str, diff: str) -> str:
"""Claude HaikuでファイルをレビューしてコメントテキストをReturnする"""
response = client.messages.create(
model="claude-haiku-4-5-20251001", # 入力$0.80/1M、出力$4.00/1M
max_tokens=512,
messages=[{"role": "user", "content": REVIEW_PROMPT.format(diff=diff)}]
)
return response.content[0].text
def post_review(comments: list[dict]) -> None:
"""GitHub PRにレビューコメントを投稿する"""
g = Github(GITHUB_TOKEN)
repo = g.get_repo(REPO_NAME)
pr = repo.get_pull(PR_NUMBER)
body = "## 🤖 AI コードレビュー\n\n"
for item in comments:
body += f"### `{item['file']}`\n{item['comment']}\n\n"
pr.create_issue_comment(body)
def main():
diffs = get_diff()
if not diffs:
print("レビュー対象ファイルなし")
return
comments = []
for item in diffs:
print(f"レビュー中: {item['file']}")
comment = review_file(item["file"], item["diff"])
comments.append({"file": item["file"], "comment": comment})
post_review(comments)
print(f"✅ {len(comments)}件のファイルをレビューしました")
if __name__ == "__main__":
main()
コスト試算
| シナリオ | モデル | 1PR平均コスト | 月間(50PR/月) |
|---|---|---|---|
| 軽量レビュー | Claude Haiku | ~$0.003 | ~$0.15 |
| 標準レビュー | Claude Sonnet | ~$0.02 | ~$1.0 |
| GPT-4o mini | GPT-4o mini | ~$0.001 | ~$0.05 |
| GPT-4o | GPT-4o | ~$0.015 | ~$0.75 |
大規模チーム(日50PR)でもClaude Haikuなら月$10以下で運用可能です。