Code Review Automatico con Claude AI e GitHub Actions

Il code review manuale è uno dei colli di bottiglia più costosi nel ciclo di sviluppo. I reviewer impiegano 30-60 minuti per PR, spesso si concentrano su stile e formattazione invece che sulla logica, e le review arrivano ore o giorni dopo l’apertura. Con Claude AI e GitHub Actions puoi avere un primo feedback automatico entro 30 secondi dall’apertura di ogni PR — non come sostituto della review umana, ma come primo filtro che elimina i problemi ovvi e lascia ai reviewer solo le decisioni che richiedono giudizio umano.

Architettura della pipeline

Il flusso è semplice: (1) sviluppatore apre una PR su GitHub, (2) GitHub Actions triggerizza il workflow, (3) uno script Node.js recupera il diff della PR tramite GitHub API, (4) invia il diff a Claude con un prompt di review strutturato, (5) posta il feedback come commento sulla PR. L’intero processo richiede 20-40 secondi.

GitHub Actions workflow YAML

# .github/workflows/ai-code-review.yml
name: AI Code Review

on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - "src/**/*.ts"
      - "src/**/*.tsx"
      - "src/**/*.js"

permissions:
  contents: read
  pull-requests: write

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"

      - run: npm ci

      - 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:              ${{ github.repository }}
          BASE_SHA:          ${{ github.event.pull_request.base.sha }}
          HEAD_SHA:          ${{ github.event.pull_request.head.sha }}
        run: node scripts/ai-review.mjs

Lo script Node.js di review

// scripts/ai-review.mjs
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const [owner, repo] = process.env.REPO.split("/");
const prNumber = parseInt(process.env.PR_NUMBER);

// 1. Recupera il diff dalla GitHub API
async function getPRDiff() {
  const response = await fetch(
    `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/files`,
    {
      headers: {
        Authorization: `Bearer ${GITHUB_TOKEN}`,
        Accept:        "application/vnd.github+json",
      },
    }
  );
  const files = await response.json();

  // Limita a 4000 token (~3000 parole) per non eccedere il contesto
  const diff = files
    .filter((f) => !f.filename.includes("package-lock.json"))
    .map((f) => `File: ${f.filename}
${f.patch ?? "(file binario)"}`)
    .join("

---

")
    .slice(0, 12000); // ~3000 token

  return { diff, fileCount: files.length };
}

// 2. Analisi Claude
async function reviewWithClaude(diff, fileCount) {
  const response = await anthropic.messages.create({
    model:      "claude-opus-4-6",
    max_tokens: 1500,
    system: `Sei un senior developer che fa code review.
Analizza il diff e fornisci feedback CONCISO in italiano.
Struttura la risposta con queste sezioni (usa solo quelle rilevanti):
🚨 **Problemi critici** (bug, security issues, race conditions)
⚠️ **Miglioramenti** (performance, leggibilità, best practice)
✅ **Cosa funziona bene**
💡 **Suggerimenti** (opzionali, non bloccanti)

Sii diretto. Max 400 parole. Non commentare su stile o formattazione se ci sono linter configurati.`,
    messages: [
      {
        role:    "user",
        content: `Review questa PR (${fileCount} file modificati):

${diff}`,
      },
    ],
  });
  return response.content[0].text;
}

// 3. Posta il commento sulla PR
async function postComment(review) {
  const body = `## 🤖 AI Code Review

${review}

---
*Generato automaticamente da Claude AI. Non sostituisce la review umana.*`;

  // Cerca se esiste già un commento AI per aggiornarlo invece di crearne uno nuovo
  const commentsRes = await fetch(
    `https://api.github.com/repos/${owner}/${repo}/issues/${prNumber}/comments`,
    { headers: { Authorization: `Bearer ${GITHUB_TOKEN}` } }
  );
  const comments = await commentsRes.json();
  const existing = comments.find((c) => c.body.startsWith("## 🤖 AI Code Review"));

  const url = existing
    ? `https://api.github.com/repos/${owner}/${repo}/issues/comments/${existing.id}`
    : `https://api.github.com/repos/${owner}/${repo}/issues/${prNumber}/comments`;

  await fetch(url, {
    method:  existing ? "PATCH" : "POST",
    headers: {
      Authorization: `Bearer ${GITHUB_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ body }),
  });
}

// Main
const { diff, fileCount } = await getPRDiff();
if (!diff.trim()) {
  console.log("Nessun diff rilevante — skip review");
  process.exit(0);
}
const review = await reviewWithClaude(diff, fileCount);
await postComment(review);
console.log("Review postata sulla PR");

Configurare il secret ANTHROPIC_API_KEY

Vai su GitHub → Repository → Settings → Secrets and variables → Actions → New repository secret. Aggiungi ANTHROPIC_API_KEY con la tua chiave Anthropic. Il GITHUB_TOKEN è automaticamente disponibile in ogni workflow senza configurazione aggiuntiva — fornisce i permessi per leggere la PR e postare commenti.

Filtrare i falsi positivi

Claude occasionalmente segnala “problemi” che non lo sono — pattern che non conosce, convenzioni del tuo team, decisioni architetturali volontarie. Alcune strategie per ridurre il rumore:

Context nel system prompt: aggiungi una sezione con le convenzioni del tuo progetto — “Usiamo react-query per il data fetching, non useEffect per le chiamate API. Non segnalare questo come problema.” File da ignorare: il filtro nel workflow YAML (paths:) limita già la review ai file rilevanti. Aggiungi pattern per escludere test files se vuoi review solo sul codice di produzione, o viceversa. Soglia di confidenza: aggiungi nel system prompt “Se non sei sicuro al 70% che sia un problema reale, mettilo in Suggerimenti, non in Miglioramenti”.

Configurazione avanzata: review differenziata per tipo di PR

Puoi personalizzare il prompt in base al tipo di cambiamento. Usa le GitHub Actions expressions per rilevare il contesto:

// Adatta il focus della review in base ai file modificati
const hasDatabaseChanges = files.some((f) =>
  f.filename.includes("migration") || f.filename.includes("schema")
);
const hasAPIChanges = files.some((f) =>
  f.filename.includes("api/") || f.filename.includes("route")
);

const systemPrompt = `Sei un senior developer che fa code review.
${hasDatabaseChanges ? "ATTENZIONE: Questa PR include modifiche al database. Concentrati su: backward compatibility delle migration, indici mancanti, rischio di data loss." : ""}
${hasAPIChanges ? "ATTENZIONE: Questa PR include modifiche alle API. Controlla: validazione input, autenticazione, rate limiting, gestione errori HTTP." : ""}
...`;

Risorse correlate

Approfondisci sul blog

Documentazione e strumenti

FAQ

Quanto costa questo sistema per team con molte PR?

Con Claude Opus 4.6 a ~$15/M token output, una review media di 1500 token di output costa ~$0,022. Per un team che apre 50 PR/mese, il costo è ~$1,10/mese. Se vuoi ridurre i costi, usa Sonnet per review standard e Opus solo per PR con label “needs-careful-review”.

La review AI può approvare automaticamente le PR?

Tecnicamente sì — puoi usare l’API GitHub per approvare PR. Non è consigliato in produzione: Claude può sbagliare, e la responsabilità dell’approvazione deve rimanere umana. Usa la review AI come primo filtro, non come gate finale. Configura branch protection rules che richiedano comunque almeno 1 review umana.

Funziona con repository privati?

Sì. Il GITHUB_TOKEN ha i permessi di leggere il contenuto del repository privato e postare commenti. Il diff viene inviato all’API Anthropic — verifica che sia accettabile secondo le policy di sicurezza del tuo team prima di abilitarlo su repository con codice sensibile.

Come gestisco PR con diff enormi (100+ file)?

Il codice già include un truncate a 12.000 caratteri. Per PR molto grandi, considera di fare review solo dei file più critici: ordina i file per “additions + deletions” decrescente e prendi i top 10-15. Una PR con 100 file è spesso il sintomo di un problema di processo (commit troppo grandi) — Claude può segnalarlo nel suo feedback.

Condividi

Articoli Recenti

Categorie popolari