Sincroniza desde el monorepo IDP la corrección del hook-order del ServiceAccount (hook pre-install/pre-upgrade, weight -5) que destraba el helm install del golden-path sin --no-hooks. Cierre del 4º gap del pipeline tenant hands-off: el smoke E2E valida ahora la cadena completa (addon-provisioner materializa MariaDB; AddonClaim publica DATABASE_URL en apps). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
APP_NAME — Web Backend Python (FastAPI + Alembic)
App generada desde el Golden Path web-backend/python de Coralware Cove IDP.
Este repositorio contiene el scaffold completo: aplicación FastAPI, migraciones
Alembic, frontend estático en /demo, Helm chart, workflow de CI y manifiesto
de contrato con la plataforma. Cuando se materializa este template para tu
tenant, los placeholders en mayúsculas se sustituyen automáticamente.
Contrato del shape: ver
coralware-shape.yamlen la raíz. Define los endpoints obligatorios, la BD esperada y la versión del shape. No elimines ese archivo — la plataforma lo lee.
Estructura
.
├── coralware-shape.yaml ← contrato con la plataforma
├── catalog-info.yaml ← entidad Backstage
├── code/
│ ├── app/ ← FastAPI app
│ ├── alembic/ ← migraciones DB
│ ├── tests/ ← pytest + cobertura
│ ├── pyproject.toml
│ ├── requirements.txt
│ └── Dockerfile
├── helm/__APP_NAME__/ ← Helm chart con hook Alembic pre-upgrade
├── claim-mariadb.yaml ← AddonClaim de la BD (ver §Base de datos)
└── .gitea/workflows/ ← CI: tests + build + deploy
Ciclo de vida
- Tú escribes código — endpoints en
code/app/routers/, modelos encode/app/models/, migraciones conalembic revision --autogenerate. git pushamaindispara el workflow Gitea Actions.- El CI corre
black,ruff,bandit,pytest --cov. Si algo falla, el pipeline aborta. - Si pasa, builda la imagen
linux/amd64con BuildKit y la publica en el proyecto Harbor de tu tenant. helm upgrade --installaplica el chart al cluster de tu tenant. Antes del rollout, un Job pre-upgrade correalembic upgrade head. Si Alembic falla, Helm aborta y la app vieja queda intacta.- Tras rollout exitoso, smoke check valida
/health200.
Orden de hooks Helm
El chart usa hooks pre-install,pre-upgrade con hook-weight para garantizar
el orden de creación. El helm upgrade --install funciona sin --no-hooks:
| Recurso | Template | hook-weight |
Motivo |
|---|---|---|---|
ServiceAccount |
serviceaccount.yaml |
-5 |
Lo referencia el pod del Job Alembic — debe existir antes |
Job Alembic |
job-alembic-upgrade.yaml |
0 |
Corre alembic upgrade head antes de rolar el Deployment |
El ServiceAccount se materializa como hook (no en la fase principal de Helm)
porque el Job Alembic, que también es hook, declara serviceAccountName. Si el
SA viviera en la fase principal se crearía después del Job → el pod del Job
nunca arrancaría (serviceaccount not found) → helm --wait haría timeout.
El SA-hook usa hook-delete-policy: before-hook-creation (no hook-succeeded):
el Deployment lo necesita vivo en runtime, así que solo se borra/recrea al
inicio del siguiente hook, manteniéndolo idempotente entre upgrades.
El imagePullSecret y el Secret <APP_NAME>-db-creds que referencia el Job los
provee la plataforma (stack-deployer / addon), no el chart.
Endpoints obligatorios
| Path | Auth | Propósito |
|---|---|---|
/health |
none | Liveness + readiness; devuelve {status: ok, db: up|down} |
/docs |
configurable (OPENAPI_REQUIRE_AUTH) |
Swagger UI |
/openapi.json |
igual que /docs |
Schema OpenAPI |
/demo |
none | Frontend estático servido desde code/app/static/demo/ |
/metrics |
restringido vía NetworkPolicy | Métricas Prometheus |
/health, /docs, /demo son contrato del shape — NO renombres.
Base de datos
Tu app espera un Secret __APP_NAME__-db-creds en su namespace con las
claves DATABASE_URL y MIGRATION_DATABASE_URL. El Secret lo provisiona la
plataforma:
- PoC / MVP — Coralware lo crea manualmente siguiendo el runbook
docs/runbook-mariadb-poc.mden el repo IDP. Tú no haces nada. - Producción (Fase 5.5+) —
claim-mariadb.yamllo materializa automáticamente cuando esté disponible el controlleraddon-provisioner(ver ADR-052).
Variables de entorno
| Variable | Origen | Default | Descripción |
|---|---|---|---|
DATABASE_URL |
Secret | — | Connection string runtime |
MIGRATION_DATABASE_URL |
Secret | = DATABASE_URL |
Connection para Alembic |
LOG_LEVEL |
ConfigMap | INFO |
DEBUG para troubleshooting |
CORRELATION_ID_HEADER |
ConfigMap | X-Correlation-ID |
Header de trazabilidad |
OPENAPI_REQUIRE_AUTH |
ConfigMap | false |
Activar JWT en /docs |
KEYCLOAK_ISSUER |
ConfigMap | — | URL del realm cuando auth activado |
STATIC_DEMO_PATH |
ConfigMap | /app/static/demo |
Path al frontend estático |
Migraciones Alembic
Migración base vacía en code/alembic/versions/0001_initial.py. Para crear
una nueva tras agregar modelos:
cd code
alembic revision --autogenerate -m "agregar tabla users"
Desarrollo local
cd code
pip install -r requirements-dev.txt
docker run --rm -d --name mariadb-dev \
-e MARIADB_ROOT_PASSWORD=dev -e MARIADB_DATABASE=app \
-p 3306:3306 mariadb:11
export DATABASE_URL="mysql+pymysql://root:dev@127.0.0.1:3306/app"
export MIGRATION_DATABASE_URL="$DATABASE_URL"
alembic upgrade head
uvicorn app.main:app --reload --port 8000
Plan de salida
Si decides migrar fuera de Cove, todo lo que necesitas vive en formato estándar:
| Componente | Cómo lo exportas |
|---|---|
| Código | git remote add github && git push github main |
| Imagen | docker pull desde Harbor + push a tu registry |
| Manifests | Ya están en helm/ — helm template genera YAML aplicable |
| Datos | Coralware ejecuta mariadb-dump y entrega .sql.gz |
Sin lock-in técnico.
Referencias
docs/adr-053-shape-web-backend-python.md— anatomía del shapedocs/adr-052-tenant-addon-claim-model.md— modelo de add-ons (BD)docs/adr-038-ci-estandar-reusable-workflow.md— pipeline Python