Amiamo l’automazione. La utilizziamo per alimentare la nostra infrastruttura, per scalare i carichi di lavoro fino a zero e—sempre di più—per ridurre la quantità di attenzione umana necessaria per rilasciare codice di alta qualità. Un aspetto che sembrava ancora ostinatamente manuale erano le revisioni delle pull request. Tra Cursor come nostro IDE, ChatGPT/Codex per prototipazione, e gemini-cli per controlli rapidi, i nostri workflow locali erano veloci—ma la CI aspettava ancora un umano.
Così ci siamo posti una domanda semplice: potevamo lasciare che un modello di linguaggio di grandi dimensioni leggesse il diff, individuasse problemi, e commentasse direttamente sulla PR?
Risultato: sì. Sono bastate poche righe di “colla” GitHub Actions per ottenere revisioni utili e strutturate su ogni pull request.
Non volevamo sostituire gli umani. Volevamo un primo passaggio che:
Se una modifica va bene, vogliamo che il bot lo dica semplicemente e si faccia da parte.
@google/gemini-cli dentro la CI per eseguire il passaggio di revisione automatica.gh) per commentare sulla PR.Ecco l’Action completa che stiamo eseguendo. Inseriscila in .github/workflows/gemini-pr.yml:
name: gemini-pr
on:
workflow_dispatch:
pull_request:
jobs:
build:
permissions: write-all
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'
fetch-depth: 0
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
components: rustfmt, clippy
cache: false
- uses: actions/setup-node@v4
with:
node-version: 20
- name: install gemini
run: |
npm install -g @google/gemini-cli
- name: gemini
run: |
echo "merging into ${{ github.base_ref }}"
git diff origin/${{ github.base_ref }} > pr.diff
echo $PROMPT | gemini > review.md
cat review.md >> $GITHUB_STEP_SUMMARY
gh pr comment ${{ github.event.pull_request.number }} --body-file review.md
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PROMPT: >
please review the changes of @pr.diff (this pull request) and suggest improvements or provide insights into potential issues.
do not document or comment on existing changes, if everything looks good, just say so.
can you categorise the changes and improvesments into low, medium and high priority?
Whenever you find an issue, please always provide an file and line number as reference information. if multiple files are affected, please provide a list of files and line numbers.
provide the output in markdown format and do not include any other text.
Checkout con fetch-depth: 0 così possiamo fare diff affidabili contro il ramo base della PR.
Toolchain Rust installa rustfmt e clippy perché i nostri repo spesso includono codice Rust; questi vengono eseguiti altrove nella pipeline, ma mantenere la setup qui evita sorprese.
Node è necessario per il gemini-cli.
Installiamo @google/gemini-cli globalmente dentro il runner.
Creiamo un file diff:
git diff origin/${{ github.base_ref }} > pr.diff
Questo assicura che il modello veda solo le modifiche in revisione.
Iniettiamo il prompt dentro gemini (il CLI legge @pr.diff inline come riferimento a file) e catturiamo l’output markdown del modello in review.md.
Aggiungiamo la revisione al Sommario del Job ($GITHUB_STEP_SUMMARY) così è visibile nell’interfaccia di Actions.
Commentiamo sulla PR usando gh pr comment … --body-file review.md.
Gli output LLM sono validi quanto le istruzioni. Il nostro mantiene tutto pratico:
Abbiamo iterato un po’ per arrivarci. Le modifiche più impattanti sono state insistere sui riferimenti a file/linee e vietare prose aggiuntive.
In una PR tipica, vediamo sezioni come:
Se tutto va bene, riceviamo una riga: “Looks good.” Perfetto—è esattamente quello che vogliamo.
GEMINI_API_KEY e GITHUB_TOKEN nei segreti del repo o dell’organizzazione. Mantieni gli scope limitati. L’Action imposta permissions: write-all perché pubblica commenti; restringi questo se la tua policy lo richiede.git diff origin/${{ github.base_ref }} dà il contesto corretto. Se il tuo workflow recupera solo il commit di merge, assicurati che il ramo base sia disponibile o usa github.event.pull_request.base.sha.pull_request_target con un hardening attento, o limitare la revisione tramite label.pull_request (non a ogni push).Le revisioni automatiche rendono gli umani più selettivi con la loro attenzione. Passiamo meno tempo su “rinomina questa variabile” e più tempo su architettura, flussi dati e confini di sicurezza. Questo significa:
È sorprendentemente efficace anche per la coesione. Un LLM non dimenticherà il pattern di gestione errori concordato tra i servizi o la nostra struttura di log preferita; applica quei controlli in modo uniforme su ogni PR.
Questo schema funziona con quasi tutti i modelli o CLI. Alcune estensioni facili:
failed per bloccare i merge fino alla risoluzione.gh) per feedback ancora più puntuali.ai-review, oppure aggiungi automaticamente una label needs-attention se appaiono rilevazioni ad alta priorità.Niente di tutto ciò sostituisce un umano che approva un merge. È un filtro leggero che si ripaga dal primo giorno.