Stack: GitHub Actions · Proyecto: TicketFlow Estado: Publicada — pipelines con pruebas, análisis y despliegue al merge Prerrequisito: Lección 40 — Docker
Objetivos
- Escribir el pipeline de TicketFlow: los jobs, su orden, su paralelismo y qué gatea el merge (y qué no).
- Decidir la estrategia de despliegue (directo al merge, blue-green, canary) según el riesgo del release.
- Cerrar el círculo con observabilidad del propio pipeline: el deploy que nadie sabe si corrió no despliega nada.
1. El pipeline: los gates del merge
El pipeline de un PR corre lo BARATO y lo DETERMINISTA; lo lento corre después del merge o programado. Los jobs:
# .github/workflows/ci.yml (resumen del proyecto)
jobs:
lint: ruff + black --check + mypy (services/, <30 s) # gatea
unit: pytest tests/unit (cacheado, <30 s) # gatea
integration: pytest tests/integration (servicios PG/Redis en el runner, <3 min) # gatea
e2e: compose up + pytest -m e2e (~4 min) # gatea con cache de imagen
build: docker build + trivy + push :sha (paralelo, gatea por CVE bloqueante)
check-deploy: python manage.py check --deploy (22/27) # gatea
load: k6 humo (meseta 1 min) — SOLO nightly o manual # NO gateaEl gate del merge: lint + unit + integration + e2e + build + check-deploy en verde → el botón de merge se desbloquea. El load NO gatea (una meseta de 5 min por PR sería el impuesto que mata el ciclo de feedback; corre nightly y en tags). La disciplina del pipeline: todo lo que gatea debe ser verde y determinista — un test flaky en el gate es una puerta que se abre con re-run (la cultura del "retry hasta que pase", la 35 lo prohíbe).
2. El build: la imagen con digest y el scan
El job de build usa el cache del registry (cache-from: type=registry): el builder de la 40 reutiliza capas de deps entre PRs (el build de 90 s baja a 15 s). El push lleva el SHA del commit como tag (ticketflow:git-a1b2c3d) y el digest resultante es EL artefacto del release: el deploy no reconstruye — despliega EL digest que pasó los tests (la cadena commit→imagen→entorno es auditable de punta a punta). El scan (trivy) gatea en modo "fallo por CVEs CRITICAL explotables" (el triage del 40: los OTHERS entran al reporte, no bloquean) — el pipeline es quien hace cumplir la política de seguridad sin la reunión de las 3 a.m.
3. La estrategia de despliegue: la que el riesgo pide
Tres opciones, en orden de sofisticación: redeploy directo (parar, desplegar, arrancar: 30 s de downtime — sirve hasta ~10 usuarios internos, no para TicketFlow), blue-green (dos entornos completos; el switch del proxy cambia de azul a verde: rollback = re-switch en 5 s; costo: 2× infra), canary (la nueva versión recibe 5% → 25% → 100% del tráfico con las métricas del 46 decidiendo: rollback automático si el p95 o el error-rate se disparan; costo: la complejidad del enrutado). TicketFlow elige: blue-green para el app + migraciones expand-contract (11) — la pareja exacta: la migración EXPAND es backward compatible (la versión vieja sigue funcionando con el esquema nuevo), el deploy green convive con blue durante la ventana, y el CONTRACT del siguiente release cierra el ciclo.
deploy:
steps:
- run: docker pull ticketflow:git-a1b2c3d
- run: ./deploy.sh green # el green arranca con la config del entorno (27)
- run: ./wait_healthy.sh green # el healthcheck del 40 decide
- run: ./switch_traffic.sh blue → green # el proxy cambia en caliente
- run: ./smoke.sh && ./rollback.sh if_smoke_failsEl smoke post-deploy (los 3 checks de la 35: listado, reserva, healthz) decide el switch definitivo; el rollback es el script hermano: el despliegue sin rollback probado no es un despliegue, es una apuesta.
4. Las migraciones en el pipeline (la pareja del 11)
El orden canónico de un release de TicketFlow: (1) CI en verde; (2) migrate EXPAND contra la BD de prod (el job corre desde la imagen del release: docker run ticketflow:git-a1b2c3d python manage.py migrate — las migraciones viajan EN la imagen, no en un branch mágico); (3) deploy blue-green (la app nueva con el esquema expandido); (4) smoke + switch; (5) el CONTRACT queda para el release siguiente (el job de limpieza semanal lo ejecuta). Lo que JAMÁS: migrar DESPUÉS del deploy (la app nueva pega contra el esquema viejo: 500 en cadena) ni migrar en el arranque del contenedor (40). El ADR del 11 vive en el pipeline: la CI es donde las decisiones se vuelven código.
5. El círculo completo: observar el deploy
El deploy es un EVENTO del sistema (45/46): el pipeline anota deployment_started/completed con commit, digest y actor en el monitoreo — las gráficas del p95 llevan la línea vertical del deploy (la 47 pregunta "¿qué cambió a las 14:20?" y la anotación lo responde). Y el loop del release: la cadencia (¿deploy al merge directo o train semanal?) se decide por el costo del rollback: blue-green con rollback de 5 s → deploy al merge es razonable (TicketFlow); rollback doloroso → train y staging más largo. La métrica del propio pipeline (DORA reducida): lead time PR→prod, frecuencia de deploy, tasa de fallo del deploy, MTTR — cuatro números que el equipo de 1 revisa mensualmente y que se imprimen en el dashboard del 46.
Autoevaluación
- ¿Qué gatea el merge en TicketFlow y qué corre después/programado? ¿Por qué el load NO gatea?
- El digest como artefacto: ¿qué cadena auditable construye y por qué el deploy NO reconstruye?
- Blue-green vs canary: ¿qué exige cada uno de tus métricas y por qué TicketFlow elige blue-green?
- Enumera el orden canónico del release con migraciones y los dos JAMÁS del §4.
- ¿Por qué el deploy es un evento del monitoreo y qué cuatro métricas DORA revisa el equipo?
Continúa con los ejercicios. Las solutions.md solo tras intentarlo.