Nos encanta la automatización. La usamos para potenciar nuestra infraestructura, para escalar cargas de trabajo a cero y, cada vez más, para reducir la atención humana necesaria para entregar código de alta calidad. Un lugar que aún se sentía obstinadamente manual eran las revisiones de pull requests. Entre Cursor como nuestro IDE, ChatGPT/Codex para prototipos, y gemini-cli para revisiones rápidas, nuestros flujos locales eran rápidos, pero la CI aún esperaba a un humano.
Así que nos hicimos una pregunta simple: ¿podríamos dejar que un modelo de lenguaje grande lea el diff, detecte problemas y comente directamente en el PR?
Resulta que sí. Solo tomó unas pocas líneas de pegamento en GitHub Actions para obtener revisiones útiles y estructuradas en cada pull request.
No intentábamos reemplazar a los humanos. Queríamos un primer filtro que:
Si un cambio está bien, queremos que el bot simplemente lo diga y se haga a un lado.
@google/gemini-cli dentro de la CI para ejecutar el paso de revisión automatizada.gh) para comentar en el PR.Aquí está la Action completa que estamos ejecutando. Ponla en .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 para poder comparar con la rama base del PR de manera fiable.
El toolchain de Rust instala rustfmt y clippy porque nuestros repositorios suelen incluir código Rust; estos se ejecutan en otras partes de la pipeline, pero mantener la configuración aquí evita sorpresas.
Node es necesario para gemini-cli.
Instalamos @google/gemini-cli globalmente dentro del runner.
Creamos un archivo diff:
git diff origin/${{ github.base_ref }} > pr.diff
Esto asegura que el modelo vea solo los cambios bajo revisión.
Canalizamos el prompt a gemini (la CLI lee @pr.diff en línea como referencia de archivo) y capturamos la salida en markdown en review.md.
Adjuntamos la revisión al Resumen del Job ($GITHUB_STEP_SUMMARY) para que sea visible en la UI de Actions.
Comentamos en el PR usando gh pr comment … --body-file review.md.
Las salidas de los LLM solo son tan buenas como las instrucciones. Las nuestras se mantienen prácticas:
Iteramos un poco para llegar aquí. Los ajustes más impactantes fueron: insistir en referencias de archivo/línea y prohibir prosa extra.
En un PR típico, vemos secciones como:
Si todo está bien, recibimos una línea: “Looks good.” Perfecto—eso es exactamente lo que queremos.
GEMINI_API_KEY y GITHUB_TOKEN en los secretos del repositorio u organización. Mantén los permisos ajustados. La Action usa permissions: write-all porque publica un comentario; restringe esto si tu política lo requiere.git diff origin/${{ github.base_ref }} da el contexto correcto. Si tu workflow solo trae el commit mergeado, asegúrate que la rama base esté disponible o ajusta a github.event.pull_request.base.sha.pull_request_target con endurecimiento cuidadoso, o condicionar la revisión por etiquetas.pull_request (no en cada push).Las revisiones automatizadas hacen a los humanos más selectivos con su atención. Pasamos menos tiempo en “renombrar esta variable” y más tiempo en arquitectura, flujos de datos y límites de seguridad. Eso implica:
También es sorprendentemente bueno en consistencia. Un LLM no olvida el patrón acordado de manejo de errores entre servicios ni nuestra estructura preferida de logs; aplica esas revisiones de modo uniforme en cada PR.
Este patrón funciona con casi cualquier modelo o CLI. Algunas extensiones fáciles:
failed para bloquear merges hasta corregir.gh lo soporta) para feedback aún más directo.ai-review, o añade automáticamente needs-attention si hay hallazgos de alta prioridad.Nada de esto reemplaza que un humano apruebe un merge. Es un filtro ligero que se paga solo desde el primer día.