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>
157 lines
7.8 KiB
Markdown
157 lines
7.8 KiB
Markdown
# Bot de incidencias
|
|
|
|
Atiende con Claude las incidencias de `CriptoMart/addons-cm` en Forgejo: responde
|
|
las preguntas funcionales o de configuración y abre un PR cuando hace falta código.
|
|
|
|
- [bot.py](bot.py): orquestador. Habla con la API de Forgejo, prepara un clon
|
|
limpio, lanza `claude -p` y publica el resultado.
|
|
- [prompt.md](prompt.md): instrucciones del bot (criterios y tono), comunes a
|
|
todos los repos.
|
|
- [../../.gitea/issue-bot.md](../../.gitea/issue-bot.md): qué es este repo
|
|
(compartido entre clientes) y sus convenciones. Se añade a las instrucciones;
|
|
es lo único que cambia de un repo a otro.
|
|
- [../../.gitea/workflows/issue-bot.yml](../../.gitea/workflows/issue-bot.yml):
|
|
disparo por Actions al abrir o comentar una incidencia.
|
|
|
|
## Qué hace con cada incidencia
|
|
|
|
Actúa cuando el último mensaje de una incidencia abierta es de una persona:
|
|
|
|
| Decisión | Acción |
|
|
| ------------ | ------------------------------------------------------------ |
|
|
| `answer` | Comenta la respuesta |
|
|
| `needs_info` | Comenta pidiendo los datos que faltan |
|
|
| `code` | Commit en `bot/issue-N`, push, PR contra `18.0` y comentario |
|
|
| `none` | Nada |
|
|
|
|
No actúa sobre PR, incidencias cerradas ni las que llevan la etiqueta `no-bot`, y
|
|
deja de responder tras `BOT_MAX_REPLIES` respuestas en la misma incidencia. Nunca
|
|
fusiona ni cierra nada.
|
|
|
|
Claude trabaja sin el token de Forgejo y sin herramientas web: solo lee el repo y
|
|
las fuentes de Odoo, edita ficheros y pasa pre-commit. Un cambio que toque
|
|
`.gitea/`, `tools/ci/`, `tools/issue_bot/` o `tools/pr_bot/` se rechaza.
|
|
|
|
Los PR que abre los revisa después el [bot de revisión](../pr_bot/README.md),
|
|
que comparte con este la imagen del runner, la cuenta y los secretos.
|
|
|
|
## Puesta en marcha
|
|
|
|
En Forgejo, una vez:
|
|
|
|
1. Dar a la cuenta del bot (`claudia_eco`) permiso de escritura en código,
|
|
incidencias y PR: como colaborador con rol de escritura o desde un equipo
|
|
propio, no desde el equipo de las personas del cliente.
|
|
2. Proteger la rama `18.0` exigiendo aprobación, para que solo se fusione tras
|
|
revisión.
|
|
3. Crear la etiqueta `no-bot`.
|
|
|
|
### Con Actions
|
|
|
|
Los jobs corren en la máquina del runner de ecocentral, con su imagen (Claude
|
|
Code, pre-commit, dependencias de Odoo 18 y Chromium) y sus montajes: las
|
|
fuentes de Odoo/OCA en `/odoo-src` y la caché `issue-bot-cache`. Cómo se monta
|
|
y se mantiene (`Dockerfile`, `update.sh`, `sources.txt`, `runner-config.yml`,
|
|
cron semanal) está documentado en el `tools/issue_bot/README.md` de ecocentral,
|
|
y sus ficheros viven allí: aquí no hay copia, para no tener dos listas de
|
|
fuentes para una misma máquina.
|
|
|
|
Un runner de Forgejo solo atiende el ámbito en el que se registra, y este repo
|
|
(organización `CriptoMart`) y el de ecocentral (`Ecocentral`) están en
|
|
organizaciones distintas. Por eso en esa máquina hay un segundo registro,
|
|
hecho en la organización `CriptoMart`, que comparte imagen, montajes y caché
|
|
con el de ecocentral:
|
|
|
|
1. Con el usuario `runner`, una carpeta propia para el segundo daemon, con una
|
|
copia del `runner-config.yml` de ecocentral (misma etiqueta, `network: host`,
|
|
montajes, `valid_volumes`, `force_pull: false`, `capacity: 1`):
|
|
|
|
```bash
|
|
mkdir ~/runner-criptomart && cd ~/runner-criptomart
|
|
cp ~/<carpeta del runner de ecocentral>/runner-config.yml .
|
|
forgejo-runner register --config runner-config.yml \
|
|
--instance http://localhost:3000 --token <token> \
|
|
--name criptomart --labels issue-bot:docker://eco-issue-bot:latest
|
|
```
|
|
|
|
El token sale de los ajustes de Actions de la organización `CriptoMart`
|
|
(Ajustes → Actions → Runners → Crear nuevo runner).
|
|
|
|
2. Un servicio aparte para este daemon (copia de la unidad de systemd del de
|
|
ecocentral con `WorkingDirectory=` en `~/runner-criptomart` y
|
|
`forgejo-runner daemon --config runner-config.yml`), y arrancarlo.
|
|
|
|
3. Activar Actions en el repo.
|
|
|
|
4. Secretos del repo: `BOT_FORGEJO_TOKEN` (token de `claudia_eco`) y uno de
|
|
`ANTHROPIC_API_KEY` o `CLAUDE_CODE_OAUTH_TOKEN` (lo genera
|
|
`claude setup-token`). Son secretos por repo: no se heredan de ecocentral.
|
|
|
|
Cada daemon tiene su `capacity: 1`, así que un job de cada repo puede correr a
|
|
la vez. Por eso el PostgreSQL del job `test` de aquí escucha en el `54330` y no
|
|
en el `54329` de ecocentral. Los dos comparten la caché `issue-bot-cache`
|
|
(entornos de pre-commit y los `.pot` del bot de revisión, que van por commit).
|
|
|
|
### Tests del CI
|
|
|
|
En cada PR contra `18.0`, y en cada push a esa rama, el job `test` de
|
|
[ci.yml](../../.gitea/workflows/ci.yml) lanza
|
|
[../ci/run_tests.py](../ci/run_tests.py) con el esquema del CI de la OCA: crea
|
|
una base de datos con las dependencias de los addons y después instala los
|
|
addons con `--test-enable`, de modo que solo corren los tests del repo.
|
|
PostgreSQL es un servicio del job, en el puerto 54330 de `127.0.0.1`.
|
|
|
|
Odoo arranca desde las fuentes montadas en `/odoo-src/18.0`, así que:
|
|
|
|
- Todo repo del que dependa un addon de aquí tiene que estar en la parte
|
|
`18.0` del `sources.txt` del runner (en ecocentral). Si falta, el job falla
|
|
diciendo qué módulo no encuentra, en lugar de dejar el addon sin probar.
|
|
- Una dependencia Python nueva (`external_dependencies`) pide añadirla al
|
|
`Dockerfile` del runner (en ecocentral).
|
|
- Ambas cosas llegan al runner al ejecutar `update.sh`, no al fusionar.
|
|
|
|
`/odoo-src/18.0` trae también un clon de este repo, porque ecocentral depende
|
|
de él. El job lo salta (`ODOO_SRC_SKIP: addons-cm` en `ci.yml`) y prueba el
|
|
checkout del PR.
|
|
|
|
Los tests corren contra la OCB y la OCA de la última actualización semanal, no
|
|
contra commits fijados.
|
|
|
|
### Sin Actions (poll)
|
|
|
|
En una máquina con `claude` autenticado, `pre-commit` y el token en
|
|
`~/.config/gitea-addons-cm.token`:
|
|
|
|
```bash
|
|
*/5 * * * * flock -n /tmp/addons-cm-issue-bot.lock python3 /ruta/al/repo/tools/issue_bot/bot.py poll
|
|
```
|
|
|
|
El primer `poll` solo anota la hora: el histórico no se atiende. Para pasar el
|
|
bot por incidencias ya abiertas:
|
|
|
|
```bash
|
|
python3 tools/issue_bot/bot.py run 12 15 --dry-run # enseña lo que publicaría
|
|
python3 tools/issue_bot/bot.py run 12 15
|
|
```
|
|
|
|
## Configuración
|
|
|
|
| Variable | Por defecto |
|
|
| ------------------------------------------- | --------------------------------------------- |
|
|
| `BOT_FORGEJO_URL` | `https://git.criptomart.net` |
|
|
| `BOT_FORGEJO_REPO` | `CriptoMart/addons-cm` |
|
|
| `BOT_FORGEJO_TOKEN` / `..._TOKEN_FILE` | `~/.config/gitea-addons-cm.token` |
|
|
| `BOT_REPO_DIR` (clon propio del bot) | `~/.cache/eco-issue-bot/addons-cm` |
|
|
| `BOT_BASE_BRANCH` (`18.0` en los workflows) | rama por defecto del repo (`16.0`) |
|
|
| `BOT_ODOO_SRC` (carpetas separadas por `:`) | `/media/snt/data/odoo` |
|
|
| `BOT_MODEL` (pide Claude Code ≥ 2.1.280) | `claude-opus-5-5` |
|
|
| `BOT_MAX_BUDGET_USD` (por incidencia) | `5` |
|
|
| `BOT_TIMEOUT` (segundos) | `2400` |
|
|
| `BOT_MAX_REPLIES` | `8` |
|
|
| `BOT_STATE_FILE` | `~/.local/state/eco-issue-bot/addons-cm/since` |
|
|
|
|
`bot.py`, `prompt.md` y los ficheros de [../pr_bot/](../pr_bot/) son copia de
|
|
los de ecocentral; solo cambian los valores por defecto de esta tabla, el de
|
|
`BOT_I18N_LANGS`, las referencias al `sources.txt` del runner y el mensaje
|
|
del commit de traducciones del bot de revisión (`[I18N] …`). Un arreglo en
|
|
uno de los dos repos se copia tal cual al otro.
|