Revisión de código con IA en cada pull request: Open Code Review en GitHub Actions y GitLab CI
La forma en que más se nota Open Code Review es cuando nadie tiene que acordarse de lanzarlo: cada pull request recibe una primera revisión con comentarios en las líneas exactas antes de que llegue un humano. En esta última parte de la guía montamos esa automatización con la GitHub Action oficial y con GitLab CI, explicamos cada secreto y cada opción, y vemos cómo controlar el coste y no abrir un agujero de seguridad.
Partimos de lo que ya sabes de las partes anteriores: instalar y configurar ocr y escribir reglas con rule.json. Todo lo que hay aquí procede del workflow, la acción y la documentación de la v1.13.2. No lo hemos ejecutado en un repositorio con una API key de pago, así que donde citamos comportamiento es el documentado por el proyecto.
Cómo funciona la revisión en CI

Todas las recetas (GitHub, GitLab, Gerrit, Bitbucket, GitFlic, Codeup) siguen el mismo esquema:
- Un evento del PR o MR dispara el job.
- Se instala
ocrcon npm (el runner es efímero). - Se configura el LLM con
ocr config seta partir de los secretos del CI. - Se ejecuta la revisión en modo rango con salida para máquinas:
``bash ocr review --from "origin/<rama-base>" --to "origin/<rama-del-pr>" --format json --audience agent ``
- Un script lee
comments[]y publica cada hallazgo como comentario en línea. Los que no tienen línea (start_line: 0) van a un comentario resumen.
Hay siempre dos credenciales: la del LLM, para generar la revisión, y un token con permiso de escritura en el PR, para comentar. En GitHub la segunda es el GITHUB_TOKEN automático.
GitHub Actions paso a paso
1. Copia el workflow
mkdir -p .github/workflows
curl -o .github/workflows/ocr-review.yml \
https://raw.githubusercontent.com/alibaba/open-code-review/main/examples/github_actions/ocr-review.yml2. Crea los secretos y variables
En Settings → Secrets and variables → Actions:
| Nombre | Tipo | Ejemplo | Para qué |
|---|---|---|---|
| `OCR_LLM_URL` | Secreto | `https://api.anthropic.com` o `https://api.openai.com/v1/chat/completions` | Endpoint del modelo |
| `OCR_LLM_AUTH_TOKEN` | Secreto | `sk-…` | Clave del proveedor |
| `OCR_LLM_MODEL` | Variable | `claude-sonnet-4-6` | Modelo. No tiene valor por defecto. |
| `OCR_LLM_USE_ANTHROPIC` | Variable | `true` | `true` para Anthropic, `false` para APIs compatibles con OpenAI |
3. Lo que hace el workflow oficial
Esta es la parte central del archivo (simplificada; el original añade el mismo filtro en el concurrency):
on:
pull_request_target:
types: [opened, synchronize, reopened]
issue_comment:
types: [created]
permissions:
contents: read
pull-requests: write
jobs:
code-review:
runs-on: ubuntu-latest
timeout-minutes: 30
if: |
github.event_name == 'pull_request_target'
|| (
github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.comment.user.type != 'Bot'
&& contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
&& (startsWith(github.event.comment.body, '/open-code-review')
|| startsWith(github.event.comment.body, '@open-code-review'))
)
steps:
- name: Get PR context
id: pr-context
if: github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner, repo: context.repo.repo,
pull_number: context.issue.number });
core.setOutput('base_ref', pr.base.ref);
core.setOutput('head_sha', pr.head.sha);
- name: Run OpenCodeReview
uses: alibaba/open-code-review@main
with:
llm_url: ${{ secrets.OCR_LLM_URL }}
llm_auth_token: ${{ secrets.OCR_LLM_AUTH_TOKEN }}
llm_model: ${{ vars.OCR_LLM_MODEL }}
llm_use_anthropic: ${{ vars.OCR_LLM_USE_ANTHROPIC }}
base_ref: ${{ steps.pr-context.outputs.base_ref }}
head_sha: ${{ steps.pr-context.outputs.head_sha }}Qué conviene entender:
- Se dispara al abrir, actualizar o reabrir un PR, y cuando un miembro, propietario o colaborador comenta
/open-code-reviewo@open-code-review. Los comentarios de bots y de desconocidos no gastan tu cuota. pull_request_targetse usa para que los secretos estén disponibles también en PRs desde forks. El proyecto lo considera seguro porque la acción solo lee el diff y no ejecuta código del PR. No añadas pasos que ejecuten el código del PR (npm install, tests, builds) en este mismo workflow: conpull_request_targettendrían acceso a tus secretos.concurrencycancela la revisión anterior del mismo PR si llega un push nuevo.- La acción compuesta
alibaba/open-code-review@maininstalaocr, lo configura, ejecuta la revisión y publica los comentarios. Si fallan en bloque, los publica uno a uno, y deja un comentario resumen con estadísticas.
4. Ajustes de la acción que más vas a usar
Todo va bajo with: del paso Run OpenCodeReview:
- name: Run OpenCodeReview
uses: alibaba/open-code-review@main
with:
llm_url: ${{ secrets.OCR_LLM_URL }}
llm_auth_token: ${{ secrets.OCR_LLM_AUTH_TOKEN }}
llm_model: ${{ vars.OCR_LLM_MODEL }}
llm_use_anthropic: ${{ vars.OCR_LLM_USE_ANTHROPIC }}
language: Spanish
effort: medium
max_tokens_budget: '3000000'
rule: .opencodereview/rule.json
background: ${{ github.event.pull_request.title }}
ocr_version: '1.13.2'
incremental: 'true'
resolve_outdated: 'true'
stream_progress: 'true'| Input | Por defecto | Qué hace |
|---|---|---|
| `language` | `English` | Idioma de los comentarios |
| `effort` | (medium) | `low`, `medium` o `high`: 1, 2 o 3 pasadas |
| `max_tokens_budget` | ilimitado | Tope de tokens por ejecución; publica lo revisado y marca el resto como `failed(budget)` |
| `rule` | — | Archivo de reglas pasado a `--rule` |
| `background` | — | Contexto pasado a `--background` (el título del PR funciona muy bien con Conventional Commits) |
| `review_concurrency` | 8 | Subagentes en paralelo; bájalo si tu proveedor te limita |
| `ocr_version` | `latest` | Fija una versión para builds reproducibles |
| `sticky_summary` | `true` | Actualiza el mismo comentario resumen en cada ejecución |
| `incremental` | `false` | Solo añade comentarios que no se solapen con los que ya publicó |
| `resolve_outdated` | `false` | Resuelve sus hilos que GitHub ya marcó como desactualizados |
| `checkpoint_range` | `false` | En cada push revisa solo lo nuevo desde el último commit revisado |
| `route_severity_below` / `route_categories` | — | Manda los hallazgos menores al resumen en vez de en línea |
| `llm_extra_body` | `{"thinking":{"type":"disabled"}}` | Campos extra para el proveedor (por defecto desactiva el *thinking*) |
| `llm_reasoning_effort` | — | `minimal` a `max` para modelos OpenAI-compatibles con razonamiento |
Sobre background: si construyes tus propios comandos run: en lugar de usar la acción, pasa el título del PR por env: y nunca con ${{ }} dentro del script. GitHub sustituye ${{ }} como texto antes de que se ejecute el shell, y un título con caracteres especiales podría ejecutar comandos en tu runner:
- name: Run OCR review
env:
PR_TITLE: ${{ github.event.pull_request.title }}
BASE_REF: ${{ github.base_ref }}
HEAD_REF: ${{ github.head_ref }}
run: |
ocr review --background "$PR_TITLE" \
--from "origin/$BASE_REF" --to "origin/$HEAD_REF" \
--format json --audience agent > ocr-result.json5. Hallazgos en Security → Code scanning (SARIF)
Si prefieres ver los hallazgos en la pestaña de seguridad de GitHub en lugar de como comentarios:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: npm install -g @alibaba-group/open-code-review
- name: Run OCR review
env:
OCR_LLM_URL: ${{ secrets.OCR_LLM_URL }}
OCR_LLM_TOKEN: ${{ secrets.OCR_LLM_AUTH_TOKEN }}
OCR_LLM_MODEL: ${{ vars.OCR_LLM_MODEL }}
BASE_REF: ${{ github.base_ref }}
HEAD_REF: ${{ github.head_ref }}
run: |
ocr review --from "origin/$BASE_REF" --to "origin/$HEAD_REF" \
--format sarif --audience agent > results.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sariffetch-depth: 0 es obligatorio: sin historial completo no hay merge-base. Para subir SARIF, el job necesita el permiso security-events: write.
6. Comentar como un bot con nombre propio
Por defecto los comentarios aparecen como github-actions[bot]. Para que salgan como "OpenCodeReview Bot", crea una GitHub App (permisos: Pull requests de lectura y escritura, Contents de solo lectura), instálala en el repo, guarda GITHUB_APP_ID y GITHUB_APP_PRIVATE_KEY como secretos y genera el token con actions/create-github-app-token@v1. Después pásalo a la acción con el input github_token.
GitLab CI
curl -o .gitlab-ci.yml \
https://raw.githubusercontent.com/alibaba/open-code-review/main/examples/gitlab_ci/.gitlab-ci.ymlSi ya tienes un .gitlab-ci.yml, guarda la receta en otra ruta e inclúyela con include: - local: 'ci/ocr-review.gitlab-ci.yml'.
Variables en Settings → CI/CD → Variables:
| Variable | Obligatoria | Enmascarada | Descripción |
|---|---|---|---|
| `OCR_LLM_URL` | Sí | No | Endpoint del modelo |
| `OCR_LLM_AUTH_TOKEN` | Sí | Sí | Clave del proveedor |
| `OCR_LLM_MODEL` | Sí | No | Modelo |
| `GITLAB_API_TOKEN` | Recomendada | Sí | Token con alcance `api` para publicar comentarios; sin él usa `CI_JOB_TOKEN` |
El núcleo del job es este:
script:
- npm install -g @alibaba-group/open-code-review
- |
ocr config set llm.url "$OCR_LLM_URL"
ocr config set llm.auth_token "$OCR_LLM_AUTH_TOKEN"
ocr config set llm.model "$OCR_LLM_MODEL"
ocr config set llm.use_anthropic false
ocr config set llm.extra_body '{"thinking": {"type": "disabled"}}'
- mkdir -p .ocr
- |
ocr review --background "$CI_MERGE_REQUEST_TITLE" \
--from "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" \
--to "${CI_COMMIT_SHA}" \
--format json --audience agent > .ocr/ocr-result.json
- python3 post_review.py .ocr/ocr-result.jsonEl script de publicación calcula base_sha, start_sha y head_sha con el endpoint versions del MR para que cada comentario caiga en la línea correcta como *discussion*, usa notas normales para lo que no se puede anclar y cierra con un resumen. También deja artefactos (.ocr/ocr-result.json, .ocr/ocr-stderr.log) durante una semana y un informe dotenv con contadores.
Dos detalles de GitLab:
- GitLab rechaza variables de menos de 8 caracteres, así que
llm.use_anthropicestá fijado afalseen el script. Para Claude, edítalo a mano. - Con
only: [merge_requests]se revisa en cada push. La documentación incluye un wrapper en Python que consulta las notas del MR y se salta la revisión si ya hay una de OpenCodeReview. Si nombras el token de proyecto "OpenCodeReview Bot", ese es el nombre que aparecerá en los comentarios.
Para GitLab autoalojado no hay que cambiar nada: usa CI_SERVER_URL.
Otros sistemas de CI
En la carpeta examples/ del repo hay recetas listas para Gerrit (Jenkinsfile + script de publicación), Bitbucket Pipelines, GitFlic CI y Codeup (Alibaba Cloud DevOps). Todas siguen el mismo patrón de cinco pasos.
Controlar el coste
En CI nadie mira el contador, así que conviene limitarlo de entrada:
max_tokens_budget(o--max-tokens-budget): tope duro por ejecución.effort: low: una sola pasada por grupo, la palanca de ahorro más grande.incrementalocheckpoint_range: no repetir la revisión completa en cada push.excludeenrule.json: fuera migraciones, código generado y fixtures.- Disparo bajo demanda: quita
synchronizede los eventos y deja que el equipo comente/open-code-reviewcuando quiera una nueva revisión. review_concurrencymás bajo si tu proveedor te limita: con throttling los reintentos alargan el job.
Errores frecuentes
Cannot find merge-base El checkout se hizo con historial superficial. Pon fetch-depth: 0 en actions/checkout. El workflow oficial ya lo hace; no lo quites si lo editas.
Failed to parse OCR output OCR_LLM_URL o OCR_LLM_AUTH_TOKEN faltan o son incorrectos. Revisa los secretos y mira los artefactos (ocr-result.json y ocr-stderr.log).
Comentarios en líneas equivocadas El diff cambió entre la revisión y la publicación (otro push en medio). El script lo detecta y lo publica como comentario normal.
El job termina en verde pero faltan archivos Algún subagente falló (timeout, límite del proveedor). ocr termina con código 0 si al menos un grupo funcionó; los fallidos aparecen en warnings del JSON y en el resumen.
OCR_DEBUG: "1" no hace nada No está implementado. Para depurar, descarga los artefactos o lanza ocr review en local con las mismas refs.
Preguntas frecuentes
¿Puede bloquear el merge si encuentra algo grave? La acción no falla por hallazgos: comenta. Si quieres bloquear, usa SARIF con Code Scanning y una regla de protección de rama, o lee la salida comments_total de la acción en un paso posterior y haz exit 1 según tu criterio.
¿Es seguro con PRs de forks? El workflow oficial sí, porque solo lee el diff. El riesgo aparece si añades pasos que ejecuten código del PR en el mismo job con pull_request_target.
¿Puedo usar un modelo local en CI? Sí, si el runner llega a tu Ollama o a tu pasarela (LiteLLM, por ejemplo): OCR_LLM_URL apunta a ella y OCR_LLM_USE_ANTHROPIC es false.
¿Cuánto tarda? Según el benchmark del proyecto, entre 1 y 8 minutos por PR real según el modelo. El workflow tiene un timeout-minutes: 30.
Conclusión
Con un archivo YAML, dos secretos y dos variables, cada pull request recibe una revisión con IA anclada a líneas, en tu idioma, con tus reglas y con el coste acotado. Es el punto en el que Open Code Review deja de ser una herramienta que lanzas tú y pasa a ser parte del proceso del equipo.
Con esto termina la guía. Si te la has saltado, empieza por qué es Open Code Review y cómo funciona por dentro, y si buscas más herramientas para tu agente, echa un vistazo a la guía de skills de Claude Code.
// código fuente
// kit para agencias
// implementación
Más sobre Agentes de IA

- Skills para tus agentes
- Claude Code

- Skills para tus agentes
- Claude Code

- Skills para tus agentes
- Claude Code