Same system as ecocentral-18 (see its docs/CI-CD.md): - ci.yml: lint (pre-commit), test (tools/ci/run_tests.py, OCA-style two-phase install) and review (PR bot, after lint and test). - issue-bot.yml: the issue bot answers issues or opens a PR on bot/issue-N. - pr-bot.yml: review when WIP is removed or the i18n label is added. - .gitea/issue-bot.md: context for the bots; this repo is shared by several clients. The bot scripts are copies of ecocentral's. Only the defaults differ (repo, token and state files, i18n languages es,eu,ca,gl) along with the [I18N] commit message and the references to the runner's sources.txt. The jobs run on a second forgejo-runner registration (CriptoMart org) on ecocentral's runner machine, sharing its image, mounts and cache. The runner files (Dockerfile, update.sh, sources.txt) live in ecocentral. Specific to this repo: - ODOO_SRC_SKIP: the runner's /odoo-src/18.0 holds a clone of addons-cm, so test skips it and checks the PR checkout instead. - BOT_BASE_BRANCH "18.0": the repo's default branch is 16.0. - test PostgreSQL on port 54330: ecocentral's runs on 54329 and a test job from each repo can run at the same time. The lint job fails until the repo is cleaned up with pre-commit run --all-files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
115 lines
6 KiB
Markdown
115 lines
6 KiB
Markdown
# Bot de revisión de PR
|
|
|
|
Revisa con Claude los pull requests de `CriptoMart/addons-cm` en Forgejo cuando
|
|
ya han pasado el linter y los tests, y deja un comentario con lo que encuentra.
|
|
No aprueba, no bloquea y no fusiona: la decisión sigue siendo de quien revisa.
|
|
|
|
- [review.py](review.py): orquestador. Decide si toca revisar, prepara la
|
|
cabeza del PR, lanza `claude -p` y publica el comentario. Reutiliza la API de
|
|
Forgejo, el clon y la llamada a Claude del
|
|
[bot de incidencias](../issue_bot/bot.py).
|
|
- [prompt.md](prompt.md): instrucciones de la revisión, comunes a todos los
|
|
repos.
|
|
- [i18n.py](i18n.py): prepara y repasa los `.po`.
|
|
- [../../.gitea/issue-bot.md](../../.gitea/issue-bot.md): qué es este repo y
|
|
sus convenciones, entre ellas la de idiomas. Es el mismo fichero que
|
|
usa el bot de incidencias.
|
|
|
|
## Qué revisa
|
|
|
|
| Parte | Qué busca |
|
|
| ---------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
| Seguridad y permisos | ACL que faltan o sobran, reglas de registro, `sudo()`, métodos públicos, controladores, SQL a mano |
|
|
| Idiomas y traducciones | Textos en un idioma que no es el del addon o que Odoo no puede traducir (`_()` mal usado) |
|
|
| Flujos de Odoo | Sobrescrituras, otras entradas al mismo modelo, otros addons que tocan lo mismo, datos que ya hay en producción |
|
|
|
|
Cada hallazgo lleva gravedad (alta, media, baja), fichero y línea, el caso
|
|
concreto y un arreglo propuesto. Estilo, formato y lo que cubren los tests no
|
|
entran: de eso ya se han ocupado el linter y el CI.
|
|
|
|
## Cuándo actúa
|
|
|
|
| Disparo | Dónde |
|
|
| ------------------------------------------ | ------------------------------------------------------------------------ |
|
|
| El CI de un PR pasa lint y test | job `review` de [ci.yml](../../.gitea/workflows/ci.yml) (`needs`) |
|
|
| Se quita la marca WIP o se pone `i18n` | [pr-bot.yml](../../.gitea/workflows/pr-bot.yml), si el CI ya había pasado |
|
|
|
|
Se salta los PR cerrados, los marcados como WIP (`WIP:` o `[WIP]` en el
|
|
título), los que no van contra `18.0` y los que llevan la etiqueta `no-bot`.
|
|
Revisa cada commit una sola vez y deja de hacerlo tras `BOT_MAX_REVIEWS`
|
|
revisiones del mismo PR. Cada revisión nueva sustituye a la anterior: repite lo
|
|
que sigue vigente y deja fuera lo arreglado.
|
|
|
|
## Traducciones (etiqueta `i18n`)
|
|
|
|
Por defecto el bot solo revisa los textos. Con la etiqueta `i18n` en el PR,
|
|
además:
|
|
|
|
1. Recoge el `.pot` de cada addon que toca el PR. Lo exporta Odoo en el job
|
|
`test`, cuando los tests pasan, y lo deja en la caché del runner
|
|
(`BOT_POT_DIR/<commit>/`).
|
|
2. Pone al día `i18n/<addon>.pot` y prepara un `.po` por idioma de
|
|
`BOT_I18N_LANGS` (`es`, `eu`, `ca`, `gl`) con los términos de todo el addon.
|
|
3. Claude rellena los `msgstr` vacíos. Un `.po` nuevo que se quede sin ninguna
|
|
traducción no se crea.
|
|
4. Se descartan las traducciones que no conservan los marcadores (`%s`,
|
|
`%(nombre)s`) del original.
|
|
5. El bot sube el resultado a la rama del PR en un commit `[I18N] <addons>: …`.
|
|
Ese commit pasa el CI como cualquier otro, pero no se vuelve a revisar.
|
|
|
|
Poner la etiqueta en un PR ya revisado lanza otra pasada, esta vez con las
|
|
traducciones. Los addons que el CI no instala (`EXCLUDE` en `ci.yml`) no tienen
|
|
`.pot` y se quedan como están.
|
|
|
|
Riesgo aceptado: el `.pot` sale de una caché en la que el job `test`, que
|
|
ejecuta el código del PR, puede escribir. Un test malicioso podría dejar un
|
|
`.pot` falso para el commit de otro PR, y si ese PR lleva la etiqueta, el bot
|
|
subiría a su rama términos que no salen de su código. Solo afecta a ficheros
|
|
`i18n/`, solo con la etiqueta y solo con acceso de escritura al repo, que es
|
|
privado. Lo de fondo es que todos los jobs comparten `issue-bot-cache`; si
|
|
algún día entra código menos fiable, el job `test` debería tener su propia
|
|
caché.
|
|
|
|
## Puesta en marcha
|
|
|
|
Usa la misma imagen, la misma cuenta (`claudia_eco`) y los mismos secretos que
|
|
el bot de incidencias: ver su [README](../issue_bot/README.md), que a su vez
|
|
remite al de ecocentral para el runner. Solo hay que añadir:
|
|
|
|
1. La etiqueta `i18n` en el repo de Forgejo.
|
|
2. La caché que comparten los jobs. Ya está si el runner monta
|
|
`issue-bot-cache:/root/.cache` como dice el README del runner; los `.pot`
|
|
van en
|
|
`/root/.cache/eco-pr-bot/pot` y se borran solos a los 14 días.
|
|
|
|
El job `review` corre con el `review.py` de la propia rama del PR, así que los
|
|
PR abiertos antes de fusionar este bot no se revisan hasta que incorporen
|
|
`18.0`.
|
|
|
|
## A mano
|
|
|
|
En una máquina con `claude` autenticado, `python3-polib` y el token en
|
|
`~/.config/gitea-addons-cm.token`:
|
|
|
|
```bash
|
|
python3 tools/pr_bot/review.py run 217 --dry-run # enseña lo que publicaría
|
|
python3 tools/pr_bot/review.py run 217 --force # repite un commit ya revisado
|
|
```
|
|
|
|
Sin `--ci-passed` comprueba en Forgejo que el commit tiene lint y test en
|
|
verde. Fuera del runner no hay `.pot` del CI, así que las traducciones no se
|
|
tocan aunque el PR lleve la etiqueta.
|
|
|
|
## Configuración
|
|
|
|
Las variables del bot de incidencias (`BOT_FORGEJO_*`, `BOT_REPO_DIR`,
|
|
`BOT_ODOO_SRC`, `BOT_MODEL`, `BOT_MAX_BUDGET_USD`, `BOT_TIMEOUT`) valen igual
|
|
aquí. Propias de este bot:
|
|
|
|
| Variable | Por defecto |
|
|
| --------------------------------- | --------------------------------------------------- |
|
|
| `BOT_MAX_REVIEWS` (por PR) | `6` |
|
|
| `BOT_CI_CONTEXTS` (separados por `,`) | `CI / lint (pull_request),CI / test (pull_request)` |
|
|
| `BOT_I18N_LABEL` | `i18n` |
|
|
| `BOT_I18N_LANGS` | `es,eu,ca,gl` |
|
|
| `BOT_POT_DIR` | `~/.cache/eco-pr-bot/pot` |
|