Files
skill-gitea/SKILL.md

15 KiB

name: gitea description: Da acceso a la instancia self-hosted de Gitea del beneficio Rio Frio (gitea.nucleoriofrio.com, org NucleOS). Úsala para crear/listar/ver PRs, leer comentarios, crear repos (en NucleOS o en tu propio usuario claudeCode0 — los del usuario del bot quedan SIEMPRE públicos por regla dura), y la killer feature — verificar runs de Gitea Actions post-merge (status, logs filtrados con --tail/--head/--errors/--grep, sin volcar el log entero a la ventana). Cubre los casos "mergeé el PR, ¿deployó OK?", "creame un repo nuevo para la skill X", reemplaza los curl ad-hoc anteriores. Ejemplos: "listame los PRs abiertos en nucleo-infra", "creá un PR desde la branch X a main", "qué pasó con el último deploy", "buscame los errores en el run 11 del workflow deploy-infra", "mostrame las últimas 30 líneas de logs del run que falló", "creá un repo skill-foo en mi usuario", "crea repo en NucleOS llamado servicio-X privado". allowed-tools: Bash, Read, Grep

Gitea — skill de PRs + Actions de gitea.nucleoriofrio.com

Qué es esto

Skill para interactuar con la instancia self-hosted de Gitea del beneficio Rio Frio (gitea.nucleoriofrio.com, Gitea 1.24.7) hostea el org NucleOS. Resuelve dos casos de uso principales:

  1. Crear/leer PRs sin escribir curl ad-hoc cada vez (con guards anti-AI attribution y body UTF-8 safe).
  2. Killer feature: introspección de runs de Gitea Actions post-merge — actions-list-runs, actions-view, actions-logs. Cierra el loop GitOps: yo mergeo un PR, el workflow deploy-infra.yml dispara, y con la skill verifico que deployó OK sin necesitar SSH a nucleo001.

Las operaciones admin (Actions secrets/variables) están bloqueadas porque el PAT de claudecode0 no es admin del org. Hay un override GITEA_USER_PAT para esos casos one-shot.

  • Server: https://gitea.nucleoriofrio.com
  • Auth: Authorization: token <PAT> (PAT de claudecode0 en .env, extraído de la skill bitwarden por setup.sh)
  • Override admin: GITEA_USER_PAT=... en el entorno (one-shot temporal)

Cómo invocarla correctamente

Antes de cualquier query:

  1. Verificá ~/.claude/skills/gitea/.env. Si no existe o está vacío:

    bash ~/.claude/skills/gitea/scripts/setup.sh
    

    Eso extrae el PAT desde la skill bitwarden (item con substring "Gitea PAT claude-agent-gitops") y lo escribe al .env. Re-corré setup.sh cada vez que rotás el PAT.

  2. Si una query devuelve 401: el PAT está revocado o el item correcto en bitwarden cambió. Re-corré setup.sh. Si persiste, podría ser que setup.sh está agarrando el PAT duplicado equivocado (hay dos items con el mismo nombre en bitwarden, ver "Errores típicos").

Scripts disponibles

Script Propósito
setup.sh Extrae PAT de bitwarden, escribe .env, valida con /version
query.sh Helper REST genérico con admin-guard (foundation de todos los demás)
pr-list.sh Lista PRs (con --state open|closed|all, --limit N)
pr-view.sh Ver detalle de un PR (incluye body completo)
pr-comments.sh Lista comentarios de un PR (requiere PAT con read:issue)
pr-create.sh Crear PR con guards anti-AI-attribution + body UTF-8 safe
repo-create.sh Crear repo (default owner = bot user; regla dura: bot user → siempre público)
repo-list.sh Listar repos de un owner (default = bot user). Filtros: --limit, --sort.
actions-list-runs.sh Lista runs (filtros client-side: workflow, branch, status, event)
actions-view.sh Detalle de un run + probe del job_id
actions-logs.sh Lee logs con filtros precisos (--tail/--head/--lines/--grep/--errors)

Ver endpoints.md para los endpoints crudos de la API.

Modelo de seguridad

Admin guard en query.sh

query.sh bloquea cualquier path que matchee:

  • /admin/* (operaciones admin del server)
  • /orgs/{org}/actions/(secrets|variables)/*
  • /repos/{o}/{r}/actions/(secrets|variables)/*

Mensaje del guard: pide al usuario un PAT temporal con scope admin, lo exporta como GITEA_USER_PAT=..., y le recuerda BORRAR el PAT desde https://gitea.nucleoriofrio.com/user/settings/applications apenas termine (Gitea no tiene PATs efímeros nativos).

# Bypass legítimo del guard:
export GITEA_USER_PAT=<el-pat-temporal-admin>
bash ~/.claude/skills/gitea/scripts/query.sh /repos/NucleOS/X/actions/secrets
unset GITEA_USER_PAT  # limpiar al terminar

Anti-AI-attribution guard en pr-create.sh

Regla dura (ver memoria feedback_no_ai_attribution.md). Antes de POST, escanea title + body por (case-insensitive):

  • Co-Authored-By: Claude (o Anthropic)
  • 🤖
  • Generated with [Claude Code] / Generated with Claude / Generated with Anthropic
  • Created with Claude / Powered by Claude / Made with Claude

Si match → exit 4 con mensaje + las líneas ofensivas. Esto es imposibilitar, no advertir — el usuario considera deshonesto darle crédito a Claude/Anthropic por trabajo del usuario.

Visibilidad de repos del bot (regla dura)

repo-create.sh rechaza --private cuando el owner es el bot user (case-insensitive match contra $GITEA_BOT_USER). Justificación: la cuenta claudeCode0 es del bot, pero el usuario humano tiene que poder auditarla sin login. Si los repos del bot fueran privados, sería una caja negra. Para algo realmente privado, crearlo bajo la org NucleOS.

Para repos en orgs (NucleOS u otra), el flag --public o --private es requerido — sin default sorpresa. Forzá la decisión consciente.

Scope del PAT de claudecode0

El PAT cacheado tiene scope: write:organization, write:package, write:repository, write:user. NO incluye read:issue / write:issue, así que pr-comments.sh (que lee issue comments) puede devolver 403. Si el usuario quiere usar pr-comments o crear PRs con descripciones largas que generen comentarios, debe regenerar el PAT con esos scopes adicionales y re-correr setup.sh.

Cuándo usar qué endpoint

Caso típico: "mergeé el PR, ¿deployó OK?"

Después de mergear un PR a main en nucleo-infra, el workflow corre. Para verificar:

# 1. Ver el último run del workflow:
bash ~/.claude/skills/gitea/scripts/actions-list-runs.sh NucleOS/nucleo-infra --limit 3

# 2. Si está in_progress, esperar 30-60s y reintentar.
#    Si terminó, ver los logs:
bash ~/.claude/skills/gitea/scripts/actions-logs.sh NucleOS/nucleo-infra <run_number>

# 3. Si falló, buscar errores específicos:
bash ~/.claude/skills/gitea/scripts/actions-logs.sh NucleOS/nucleo-infra <run> --errors -C 3

"Quiero crear un PR"

Para body con tildes/ñ, siempre pasarlo via --body-file. NO usar heredoc inline (memoria feedback_api_utf8_encoding.md):

# Crear el body en un archivo (con Write tool, UTF-8 nativo):
cat > /c/Users/jodar/AppData/Local/Temp/pr-body.md <<'EOF'
## Qué cambia

Esto arregla el bug X — resumen de cambios.

## Por qué
[...]
EOF

bash ~/.claude/skills/gitea/scripts/pr-create.sh NucleOS/nucleo-infra \
  --head fix/foo \
  --title "fix(x): short imperative" \
  --body-file /c/Users/jodar/AppData/Local/Temp/pr-body.md

Para body simple sin caracteres especiales, --body "..." inline también va.

"Listame PRs abiertos"

bash ~/.claude/skills/gitea/scripts/pr-list.sh NucleOS/nucleo-infra
# Default state=open, limit=20.

"Ver detalle del PR #14"

bash ~/.claude/skills/gitea/scripts/pr-view.sh NucleOS/nucleo-infra 14

"Mostrame solo los runs que fallaron"

bash ~/.claude/skills/gitea/scripts/actions-list-runs.sh NucleOS/nucleo-infra \
  --status failure --limit 20

"Buscá errores en el run 7"

bash ~/.claude/skills/gitea/scripts/actions-logs.sh NucleOS/nucleo-infra 7 --errors -C 3
# --errors es shortcut para --grep '(error|fail|fatal|exception|panic|...)'

"Quiero el log entero del run X para grep-ear con mis tools"

bash ~/.claude/skills/gitea/scripts/actions-logs.sh NucleOS/nucleo-infra X \
  --save /c/Users/jodar/AppData/Local/Temp/run-X.log
# Guarda raw (sin sanitizar) para preservar fidelidad.

"Creá un repo nuevo en mi (bot) usuario"

Default owner = $GITEA_BOT_USER (claudeCode0). Siempre público por regla dura — --private está bloqueado bajo el bot user (exit 5):

bash ~/.claude/skills/gitea/scripts/repo-create.sh skill-foo \
  --description "Skill X — qué hace" --license "MIT" --gitignore "Node"
# → claudeCode0/skill-foo (public), html_url + clone_url + ssh_url

"Listame los repos del bot / del org"

bash ~/.claude/skills/gitea/scripts/repo-list.sh                  # bot user
bash ~/.claude/skills/gitea/scripts/repo-list.sh --owner NucleOS  # org
bash ~/.claude/skills/gitea/scripts/repo-list.sh --sort alpha --limit 10

"Creá un repo en NucleOS"

Para org, --public o --private es requerido (exit 6 si no pasás ninguno — sin default sorpresa):

bash ~/.claude/skills/gitea/scripts/repo-create.sh nuevo-servicio \
  --owner NucleOS --private --description "..." --gitignore "Go"

Reglas de comportamiento

Filtros sobre logs son obligatorios

Los runs de deploy-infra tienen ~1700 líneas (post-sanitización). Volcar entero satura mi ventana. Default es siempre summary (header + tail 5/40 según status). Solo usar --full cuando es chico, y nunca sin --i-mean-it si supera 1000 líneas.

Workflow GitOps (memoria feedback_swarm_changes_via_gitea.md)

Toda modificación al Swarm va por PR + workflow. Después de mergear, antes de declarar el cambio listo, verificar con actions-logs que el deploy terminó OK. Sino, esa "termina" es prematura.

Operaciones disruptivas requieren OK explícito

pr-merge no está en la skill (out of scope). Mergear con la API requiere construir el endpoint manualmente con query.sh y antes pedir confirmación explícita al usuario — un merge dispara deploy a producción. Memoria feedback_disruptive_actions.md aplica.

PAT duplicado en bitwarden

Hay 2 items con substring Gitea PAT claude-agent-gitops en el vault de claudecode0. setup.sh toma el primero. Si la validación falla:

  • Listar los items: bash ~/.claude/skills/bitwarden/scripts/query.sh "/list/object/items?search=Gitea"
  • Pedirle al usuario que limpie el duplicado desde https://vault.nucleoriofrio.com (la skill bitwarden tiene DELETE bloqueado).

Errores típicos

Error Causa Qué hacer
setup.sh "no encontré ningún item..." El PAT no está guardado en bitwarden Generar PAT en Gitea + guardarlo en bitwarden con substring "Gitea PAT claude-agent-gitops"
Validación 401 PAT revocado o duplicado equivocado Limpiar duplicados desde web vault, regenerar si es necesario, re-correr setup.sh
query.sh admin guard exit 3 Endpoint requiere admin Pedir PAT temporal admin al usuario, exportar GITEA_USER_PAT, recordar borrarlo apenas termine
pr-create.sh exit 4 Body con AI attribution Remover los markers (regla dura)
pr-comments.sh 403 PAT sin scope read:issue Regenerar PAT con read:issue+write:issue, re-correr setup.sh
actions-logs.sh "no pude resolver job_id" Probe de ±10 falló (Gitea no expone listado de jobs) Probar con --job <jid> directo; rangear con query.sh /repos/.../actions/jobs/<jid>/logs manualmente
actions-list-runs 0 results con filtro Filtros son client-side; el server solo respeta limit Subir --limit (default 10) para incluir runs más viejos

Lifecycle: cuándo correr cada script

Script Cuándo
setup.sh (a) Primera vez. (b) Cuando el PAT rota. (c) Cuando agregás scopes nuevos al PAT. (d) Cuando 401 inesperado
query.sh Endpoint nuevo o ad-hoc no cubierto por otros scripts
pr-*.sh Operaciones de PRs
actions-*.sh Verificar deploys, debug runs, etc.

Setup inicial (lo hace el usuario UNA vez)

1. Generar PAT en Gitea

  • https://gitea.nucleoriofrio.com/user/settings/applications (logueado como claudecode0)
  • "Generate New Token" con scopes:
    • read:repo, write:repo — push, leer/crear PRs, branches
    • read:issue, write:issue — comentarios y descripciones de PRs
    • read:user — sanity check de auth
    • (NO usar admin scopes acá; eso queda para PATs temporales)
  • Copiar el token (sólo se ve una vez).

2. Guardar en bitwarden (vault de claudecode0)

  • Web: https://vault.nucleoriofrio.com → login como claudecode0
  • New item: name = claudecode0 · Gitea PAT claude-agent-gitops (cualquier nombre con substring Gitea PAT claude-agent-gitops sirve)
  • Username: claudecode0. Password: el PAT.
  • Save.

3. Correr setup

bash ~/.claude/skills/gitea/scripts/setup.sh

Esperado:

→ Listo: Gitea 1.24.7 | user=claudeCode0 | https://gitea.nucleoriofrio.com

4. Probar

bash ~/.claude/skills/gitea/scripts/pr-list.sh NucleOS/nucleo-infra
bash ~/.claude/skills/gitea/scripts/actions-list-runs.sh NucleOS/nucleo-infra --limit 3

Limitaciones conocidas de la API de Gitea 1.24

  • No hay endpoint global de runs: /actions/runs 404. Usamos /actions/tasks que sí existe pero solo acepta page+limit — los demás filtros (workflow, branch, status, event) son client-side.
  • No hay endpoint para listar jobs de un run: /actions/runs/{id}/jobs 404. La skill hace probe de job_ids en task_id ± 10 matcheando la primera línea del log con received task <task_id>. Si tu run tiene múltiples jobs o el offset es mayor, falla — pasale --job <jid> directo.
  • Logs por job son texto plano (/actions/jobs/{job_id}/logs). Logs por run completo (/actions/runs/{id}/logs) devuelven zip — la skill nunca los toca porque no son procesables desde Bash sin extraer.
  • Actor del run no expuesto: /actions/tasks no devuelve quién disparó el run. Si querés saber quién mergeó, mirá el merge commit con git log.

Qué NO hace esta skill

  • No mergea PRs (out of scope; disruptive — dispara deploy a prod, requiere confirmación explícita del usuario y prefijar query.sh manualmente).
  • No comenta PRs (POST a issues/comments — out of scope; el PAT tampoco tiene scope para issues por default).
  • No gestiona issues, releases, webhooks ni runners. Out of scope.
  • No lee zip de logs run-level. Sólo job-level texto plano.
  • No hace AI attribution en commits ni PRs. Imposible de bypassear desde esta skill (regla dura).

Archivos de la skill

Archivo Qué tiene
SKILL.md Este archivo
endpoints.md Cheat sheet de la API de Gitea 1.24 (lo relevante)
.env.example Plantilla de config
.env Generado por setup.sh (NO versionado, contiene el PAT)
scripts/setup.sh Extrae PAT de bitwarden + valida
scripts/query.sh Helper REST con admin guard
scripts/pr-*.sh Wrappers de PRs
scripts/actions-*.sh Wrappers de Gitea Actions

Referencias

  • API spec oficial Gitea: https://docs.gitea.com/api/1.24/
  • Swagger JSON de la instancia: https://gitea.nucleoriofrio.com/swagger.v1.json
  • endpoints.md — cheat sheet de los endpoints relevantes