Sí se puede revisar código con IA dentro de GitHub Actions sin perder el control del proyecto, siempre que el agente tenga permisos exclusivos de lectura y un tope de turnos definido. Así se obtiene una segunda opinión automática antes de cada fusión, sin que la IA escriba en el repositorio.
Cuándo conviene un revisor automático en Drupal y PHP
Un revisor automático no reemplaza a la persona que aprueba, pero sí recorta el tiempo de espera cuando el equipo abre varios pull requests por semana. En la práctica, la revisión humana se concentra en lógica de negocio y deja pasar los detalles que se repiten en todos los commits: nombres de servicios, permisos declarados, etiquetas de caché, migraciones sin índice. Un agente bien acotado detecta esos patrones de forma sistemática y los deja escritos en el pull request antes de que llegue a un revisor senior.
En Drupal ese valor es mayor que en un proyecto genérico, porque el framework tiene convenciones que un revisor universal no conoce. Un linter detecta un error de sintaxis en PHP, pero no sabe si un servicio nuevo en services.yaml rompe la inyección de dependencias, si un hook de acceso omite una comprobación crítica o si un render array quedó sin las etiquetas de caché correctas. La documentación oficial de Drupal sobre caché, servicios e inyección de dependencias está disponible en drupal.org/docs, y conviene usarla como referencia del checklist que se le entrega al agente.
El costo también pesa en la decisión. Sin límites, una sola revisión puede consumir más tokens de los previstos. Al fijar un máximo de turnos y un presupuesto por ejecución, el pipeline se vuelve predecible y se puede activar en cada pull request incluso con varios proyectos en paralelo.
Dos rutas para montarlo en GitHub Actions
Las dos opciones que cumplen con autohospedaje o control de modelo, permisos mínimos y salida auditable son Qodo Merge y Claude Code en modo headless. Cualquiera de las dos se conecta con un workflow de pocas líneas, siempre que el repositorio se clonee con historial completo.
Opción 1: Qodo Merge autohospedado con LiteLLM
Qodo Merge es una herramienta pensada específicamente para revisión de pull requests y permite decidir qué proveedor de modelo se usa, qué llaves se almacenan y cómo se limitan los costos. Al apuntar a LiteLLM se pueden enrutar las peticiones al modelo que mejor se ajuste al proyecto sin quedar atado a un solo proveedor.
Dos detalles hacen la diferencia en la práctica. El primero es fetch-depth: 0 en el checkout: sin historial completo el diff contra la rama base sale incompleto y los comentarios pierden sentido. El segundo es .pr_agent.toml, donde se define qué eventos disparan la revisión y qué instrucciones recibe el agente en cada repositorio.
name: Qodo Merge PR Review
on:
pull_request:
types: [opened, reopened, synchronize]
permissions:
contents: read
pull-requests: write
jobs:
pr_agent_job:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Qodo Merge
uses: Codium-ai/pr-agent@main
env:
OPENAI_KEY: ${{ secrets.LITELLM_KEY }}
OPENAI_API_BASE: ${{ secrets.LITELLM_BASE }}
OPENAI_MODEL: ${{ secrets.LITELLM_MODEL }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_AGENT_CONFIG: .pr_agent.toml
En .pr_agent.toml lo recomendable es desactivar las acciones de escritura y reforzar el foco en hallazgos. Para un repositorio Drupal, el checklist de servicios, hooks de acceso y caché se escribe en la sección de instrucciones del agente: ahí es donde el reporte deja de ser genérico.
Opción 2: Claude Code en modo headless
Claude Code se ejecuta sin interfaz con claude -p, devuelve una respuesta estructurada y la action oficial instala el entorno necesario. Para un pipeline seguro hay dos banderas que no son opcionales: --allowedTools, que acota qué puede ejecutar el agente, y --max-turns, que corta la ejecución. La salida en JSON permite registrar costo y duración por cada revisión, y therefore detener el job si se pasa del umbral.
name: Claude Code PR Review
on:
pull_request:
types: [opened, reopened, synchronize]
permissions:
contents: read
pull-requests: write
id-token: write
jobs:
review:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Claude Code review
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
claude_args: |
-p
--allowedTools "Read,Bash(grep:*),Bash(rg:*),Bash(find:*),Bash(cat:*),Bash(php -l:*)"
--max-turns 15
--output-format json
prompt: |
Revisa este pull request como revisor senior de Drupal y PHP.
Concéntrate en arquitectura, seguridad, caché y convenciones del proyecto.
Reporta archivo y línea, severidad (baja/media/alta) y una sugerencia accionable.
No escribas código: solo deja comentarios de revisión.
php -l es útil porque valida sintaxis sin ejecutar nada (php.net/manual/es). Con solo lectura, búsqueda y validación local, el agente no puede escribir archivos, hacer commits ni abrir pull requests.
Qué revisar específicamente en un pull request de Drupal
Un checklist concreto es lo que separa un reporte útil de una lista genérica de estilo. Para Drupal conviene priorizar estos seis puntos y pedirlos explícitamente en el prompt:
- Servicios e inyección de dependencias: definiciones en
services.yaml, argumentos en el orden correcto y evitar instanciar servicios a mano. - Control de acceso: hooks de
access, permisos declarados en el módulo y comprobaciones en rutas o formularios, para descartar escalado de privilegios. - Caché y render arrays: etiquetas, contextos y tiempos en
#cache, porque un#cachemal puesto produce datos obsoletos o visibles entre usuarios. - Base de datos y migraciones: esquemas, índices y cambios destructivos justificados.
- Entrada de datos y SQL: saneamiento con las APIs de Drupal y nada de concatenación directa en consultas.
- Rendimiento: consultas N+1, hooks pesados y compatibilidad con la versión objetivo de Drupal y PHP. El estándar de código del proyecto se puede fijar con Drupal Coder.
Prompt injection: el riesgo que hay que acotar
Todo lo que viene en un pull request es dato no confiable: título, descripción, comentarios e incluso nombres de archivo. Una instrucción oculta en la descripción puede intentar desviar al revisor hacia acciones que nadie autorizó. Es el riesgo principal de correr agentes dentro de CI, y no se resuelve con mejores instrucciones: se resuelve con restricciones técnicas.
La mitigación tiene tres capas. La primera son los permisos del workflow: contents: read como mínimo, nunca contents: write, y GITHUB_TOKEN sin privilegios de escritura en el repositorio. La segunda es acotar las herramientas a lectura, búsqueda y validaciones locales. La tercera son los límites operativos: máximo de turnos, timeout por job y presupuesto de tokens. Con esas tres capas, una instrucción maliciosa en el texto del pull request no tiene por dónde ejecutarse.
Plan de puesta en marcha
La forma segura de adoption es gradual. Primero, crea una rama de prueba con un pull request pequeño que contenga un error intencional de caché o un permiso mal declarado. Segundo, configura una sola de las dos rutas, únicamente con permisos de lectura, y ejecútala sobre ese PR. Tercero, ajusta el checklist de Drupal al repositorio hasta que los hallazgos señalen archivos y líneas reales. Cuarto, activa la revisión en todos los pull requests conservando los topes de turnos y presupuesto definidos desde el primer día.
Si tu equipo necesita integrar este flujo en un repositorio Drupal con reglas propias de revisión, el equipo de Saibher puede ayudarte a ajustar el pipeline y las instrucciones del agente a tu caso.
Preguntas frecuentes
¿Puede un revisor con IA aprobar o fusionar un pull request?
No. Con permisos de solo lectura y herramientas acotadas, el agente solo deja comentarios. La aprobación y la fusión siguen el flujo humano que el equipo haya definido, sin excepciones.
¿Qué diferencia hay entre Qodo Merge y Claude Code para este caso?
Qodo Merge está diseñado específicamente para revisión de pull requests y se configura con reglas por repositorio de forma sencilla. Claude Code da más flexibilidad para razonar sobre arquitectura, pero exige cuidar --allowedTools y --max-turns para mantener el costo acotado.
¿Cómo se evita el prompt injection desde la descripción del pull request?
Tratando todo el texto del pull request como dato no confiable y reduciendo lo que el agente puede hacer: sin herramientas de escritura, con las herramientas limitadas a lectura y con topes de turnos y presupuesto. Así, una instrucción inyectada no tiene con qué ejecutarse.
¿Qué archivos de un proyecto Drupal conviene priorizar?
services.yaml, los archivos que definen hooks de access, los render arrays con #cache, las migraciones y cualquier código que toque consultas a base de datos o validación de formularios. Esos puntos concentran los errores que un revisor genérico deja pasar.
¿Cuánto cuesta ejecutar esto en cada pull request?
Depende del modelo y del tamaño del diff. Al fijar --max-turns, un presupuesto máximo por ejecución y enrutar a modelos ajustados a través de LiteLLM, el costo por revisión se mantiene acotado y se puede auditar con la salida en JSON.