AIコーディング 2026.06.14

GitHub ActionsとClaude/ChatGPT APIでコードレビューを自動化する【2026年版完全ガイド】

タグ:GitHub Actions / Claude API / ChatGPT API / コードレビュー自動化 / CI/CD

自動コードレビューの全体アーキテクチャ

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 miniGPT-4o mini~$0.001~$0.05
GPT-4oGPT-4o~$0.015~$0.75

大規模チーム(日50PR)でもClaude Haikuなら月$10以下で運用可能です。


あわせて読みたい

参考ソース