Files
apps-registry/workloads/docs-portal/docs/playbooks/incidente-yaml-anchors-gitea-actions-2026-08.md
T
devops be3e5c2a4c docs(devsecops): documentar 4+1 hallazgos de infraestructura y TODOs de Cosign
5 playbooks nuevos en docs/playbooks/ del portal:
- SQLite en modo DELETE causando SQLITE_BUSY, por que WAL lo resuelve.
- Anchors YAML no soportados por el parser de Gitea Actions, incluido
  el diagnostico equivocado inicial (indentacion) que se corrigio
  despues -- documentado con honestidad como leccion de proceso.
- Docker-in-Docker vs sibling containers, y por que Semgrep corre
  nativo en un venv en vez de como container aparte.
- El SNI/realm HTTP del tunel rompiendo especificamente a Cosign
  (docker push funcionaba, cosign sign no), conectado con el
  incidente ya documentado del 504 -- misma capa de ingress, dos
  fallas distintas.
- Contencion de recursos entre Gitea y su runner: causa raiz real
  confirmada en vivo durante esta misma sesion (ambos contenedores
  reiniciados a mitad de un build, sin limites de CPU/memoria reales),
  con fix propuesto (ver rama fix/gitea-runner-resource-limits en
  scripts/) pendiente de aplicacion manual.

Se actualiza el playbook del 504 para linkear hacia el nuevo hallazgo
de contencion, cerrando el loop que habia quedado abierto ahi.

cosign.md: nueva seccion "Limitaciones conocidas y mejoras futuras"
con los dos TODO reales -- firma por tag en vez de digest (con el
warning real de Cosign visto en los logs) y transparency log de Rekor
deshabilitado, explicado en simple.

index.md: tabla resumen de los 3 pipelines (imagen + adaptacion de
Semgrep por stack), diagrama generalizado para reflejar que es el
mismo patron en los 3 workflows, y "que falta" actualizado.

Validado con mkdocs build --strict (0 errores, 0 warnings) antes de
commitear.
2026-08-15 15:17:43 -05:00

4.9 KiB

Incidente: anchors YAML no soportados por Gitea Actions — y un diagnóstico equivocado en el camino (2026-08)

Ventana del incidente 2026-08-15, desde el primer commit que agregó Gitleaks a build.yaml
Servicio afectado Gitea Actions — el workflow build.yaml (frontend)
Impacto build.yaml no generaba ningún action_run, ni en push ni en pull_request — el pipeline entero era invisible para Gitea, sin ningún error visible en la UI

Qué es un anchor/alias YAML, para quien no lo conoce

YAML tiene una forma de evitar repetir el mismo bloque dos veces:

paths: &frontend_paths
  - 'workloads/ecommerce/**'
  - '.gitea/workflows/build.yaml'

on:
  push:
    paths: *frontend_paths
  pull_request:
    paths: *frontend_paths

&frontend_paths es un anchor (marca ese nodo con un nombre). *frontend_paths es un alias (dice "poné acá una copia de lo que marcó ese anchor"). Es YAML 100% estándar — cualquier parser que siga la especificación lo resuelve sin problema, y es una forma común de no duplicar listas idénticas en el mismo archivo.

Síntoma

build.yaml (con Gitleaks recién agregado, usando anchors para no repetir la lista de paths entre push: y pull_request:) no generaba ningún run en Gitea Actions. Ni en el push directo a la rama del PR, ni al abrir el pull request. Sin mensaje de error visible en la UI de Gitea — el workflow simplemente no aparecía en la lista de Actions, como si no existiera.

Primer diagnóstico (equivocado)

La primera sospecha fue una indentación rota específicamente en el step de Semgrep: el bloque python3 -c "..." embebido dentro de un run: | tenía código pegado a columna 0, por debajo de la indentación esperada del block scalar de YAML. Eso era un problema real — cortaba el block scalar ahí mismo y en teoría podía hacer que Gitea rechazara el archivo con un error de parseo genérico (could not find expected ':').

Se corrigió la indentación, se validó con un parser YAML real y bash -n sobre los 20 steps del archivo, se mergeó a main como fix (fix(ci): corregir indentación YAML rota en el step de Semgrep, PR #19)... y build.yaml siguió sin generar runs.

!!! warning "Por qué vale la pena contar el diagnóstico que no era" El primer fix no estaba mal — la indentación efectivamente estaba rota y corregirla era necesario. El error fue asumir que esa era la única causa sin confirmarlo con una corrida real después del fix. La lección de proceso: un fix que "tiene sentido" y que pasa la validación local (parser YAML, bash -n) todavía necesita una confirmación en vivo contra el sistema real antes de darlo por cerrado — sobre todo cuando el síntoma es "no pasa nada" en vez de un error explícito, que es exactamente el tipo de fallo más fácil de dar por resuelto sin verificar.

Causa raíz real

deploy-docs.yaml (sin anchors) corría normal. build.yaml (con anchors, agregados junto con Gitleaks) no generaba ningún run — ni en push ni en pull_request, desde el primer commit que los introdujo. El log del propio Gitea lo confirmó:

unknown on type: &yaml.Node{...Value:"frontend_paths"...}

El parser propio de Gitea Actions para el bloque on: de un workflow no resuelve &anchor/*alias antes de inspeccionar el tipo de nodo — encuentra un anchor donde esperaba un valor ya resuelto, no sabe qué tipo de dato es, y descarta el archivo completo en silencio. pyyaml y cualquier parser YAML estándar sí resuelven el alias primero (por eso el archivo "parseaba bien" en cualquier herramienta de validación genérica) — es una limitación específica del parser de workflows de Gitea Actions, no un YAML inválido.

Esto explica por qué el síntoma no tenía ningún error visible: no es que el job fallara, es que Gitea nunca llegaba a registrar el workflow como existente.

Fix aplicado

Se eliminaron los anchors/alias. Las dos listas de paths (una para push:, otra para pull_request:) quedan duplicadas literalmente, sin referencia compartida:

on:
  push:
    branches: [main]
    paths:
      - 'workloads/ecommerce/**'
      - '.gitea/workflows/build.yaml'
  pull_request:
    branches: [main]
    paths:
      - 'workloads/ecommerce/**'
      - '.gitea/workflows/build.yaml'

Es más repetitivo, pero es el precio de que el parser de Gitea Actions lo entienda. Este mismo criterio (sin anchors, paths duplicados) se replicó a propósito en build-medusa.yaml y deploy-docs.yaml al agregarles el resto del pipeline de seguridad, para no repetir el mismo problema.

Validación

Confirmado en vivo: tras mergear el fix, build.yaml generó su primer action_run real. Validado también con un parser YAML + bash -n sobre los 20 steps del archivo, igual que en el intento anterior — la diferencia esta vez fue confirmarlo contra una corrida real antes de cerrar el incidente.