Las cinco lecciones anteriores eran laboratorios: cada paso estaba escrito, cada fichero estaba dado y cada fallo estaba previsto. Esta no. Esta es el encargo. Aquí tienes un contexto de empresa, unas restricciones, un presupuesto y una lista de requisitos con sus criterios de aceptación, y a partir de ahí decides tú: qué herramienta, qué estrategia de despliegue, qué pruebas escribir primero, qué escaneos ejecutar en cada PR y cuáles solo en main, dónde poner las puertas, qué dejar fuera y —lo más difícil— cómo justificar cada una de esas decisiones ante alguien que no estaba cuando las tomaste.

Puedes hacerlo sobre un proyecto tuyo (mejor, si tienes uno) o sobre Mini-Reservalia. Lo que no puedes es copiar el pipeline de la 07-05 tal cual: el contexto del encargo tiene restricciones que obligan a apartarse de él en al menos tres puntos, y encontrarlas forma parte del ejercicio.

Contenido

  1. El encargo
  2. El contexto: Citas Norte, S.L.
  3. Requisitos obligatorios y criterios de aceptación
  4. Entregables
  5. Rúbrica de autoevaluación
  6. Plan de trabajo en cinco sesiones
  7. Retos opcionales
  8. Errores típicos del proyecto final
  9. Errores Comunes y Consejos
  10. Ejercicios
  11. Conclusión y cierre del curso en la práctica

  1. El encargo

Te incorporas como responsable de entrega a una empresa pequeña que tiene un producto en producción y ningún pipeline. Despliegan a mano, los viernes no despliegan, y la última vez que algo salió mal tardaron dos horas en volver atrás porque nadie recordaba qué versión estaba antes.

Tu encargo: llevar ese producto desde el estado actual hasta un pipeline completo de extremo a extremo, con puertas de calidad, artefacto inmutable, despliegue automatizado con rollback y métricas que demuestren que la situación ha mejorado.

La condición del encargo: todo lo que construyas tiene que poder ser verificado por un revisor externo que no ha hablado contigo, en menos de una hora, mirando solo el repositorio.

Esa última condición es la que convierte el ejercicio en algo parecido al trabajo real. Un pipeline que solo funciona cuando tú estás delante para explicarlo no es un entregable: es una dependencia.

  1. El contexto: Citas Norte, S.L.

Las restricciones son las que hacen que las decisiones tengan que justificarse. Si todo fuera posible, no habría nada que decidir.

La empresa. Citas Norte, S.L. vende un software de reservas para pequeños negocios. Tiene:

Dato Valor
Clientes de pago 180 negocios
Volumen ~4.000 citas al mes
Equipo técnico 3 personas: una tech lead, un backend, una persona a medias entre frontend y soporte
Producto Un monolito Node.js + PostgreSQL, y una SPA
Entornos actuales Uno solo: producción
Despliegue actual git pull por SSH y pm2 restart, a mano, por la tech lead
Frecuencia Una vez cada dos semanas, martes o miércoles por la mañana
Pruebas 40 pruebas unitarias que "casi siempre" pasan; nadie las ejecuta antes de desplegar
Última incidencia 2 h 20 min de caída por un despliegue que rompió el login

Las restricciones, que son innegociables:

  1. Presupuesto de herramientas: 0 €/mes. La empresa no aprueba gasto nuevo hasta el próximo ejercicio. Todo debe caber en planes gratuitos.
  2. Nadie puede dedicarse a operar el pipeline. El equipo son tres personas y las tres están al 100 % en producto. Un Jenkins autoalojado está descartado por esto, no por lo técnico.
  3. La ventana de mantenimiento actual es sagrada para el negocio: los sábados por la mañana, entre las 9:00 y las 13:00, se concentra el 40 % de las reservas del fin de semana. Una caída ahí cuesta clientes.
  4. Hay datos personales (nombre, teléfono y email de los clientes finales de los 180 negocios). Cualquier filtración es un incidente reportable.
  5. La tech lead se va de vacaciones tres semanas dentro de dos meses. Durante ese tiempo, las otras dos personas tienen que poder desplegar y revertir sin ella.
  6. El equipo desconfía de la automatización. El backend, en concreto, ha dicho literalmente: "cada minuto que le dediquemos a esto es un minuto que no dedicamos a lo que nos pagan". Tu propuesta tiene que rendir pronto y tienes que poder demostrarlo con números.

Tres consecuencias de leer bien las restricciones (compruébalas contra tus decisiones cuando termines):

  • La restricción 2 y la 6 juntas descartan cualquier solución que requiera mantenimiento continuo. Menos piezas y más estándar gana a más potente.
  • La restricción 5 significa que el rollback tiene que ser ejecutable por alguien que no lo escribió, con un botón y sin recordar comandos. Documentar no es opcional aquí: es un requisito funcional.
  • La restricción 3 no significa "ventanas de despliegue". Significa que el tiempo de restauración importa más que la frecuencia. Si puedes revertir en 3 minutos, el sábado deja de dar miedo; si tardas 2 horas, ninguna ventana te salva.

La línea base que tienes que medir antes de tocar nada (es el requisito más incumplido de todo el proyecto):

Métrica DORA Valor actual estimado Cómo lo medirías hoy
Frecuencia de despliegue 0,5 / semana Contar los git log de producción
Lead time (commit → producción) ~9 días Del commit al despliegue en el que entró
Change failure rate ~20 % (1 de cada 5) Incidencias tras despliegue ÷ despliegues
Time to restore 140 min La última incidencia

  1. Requisitos obligatorios y criterios de aceptación

Cada requisito lleva su criterio verificable. La fórmula "un revisor externo debe poder comprobar que…" es deliberada: si no se puede comprobar mirando el repositorio y sus ejecuciones, no cuenta.

Grupo A — Integración continua (módulo 2)

# Requisito Criterio de aceptación
A1 Build reproducible Un revisor debe poder ejecutar el mismo comando que ejecuta el CI, en su máquina, y obtener el mismo resultado. Lockfile commiteado, versión de runtime fijada explícitamente, ninguna dependencia de estado previo del runner
A2 Tres capas de pruebas Existen pruebas unitarias, de integración (contra una dependencia real: base de datos o API) y al menos una end-to-end contra el sistema arrancado. El revisor puede identificar qué fichero pertenece a qué capa sin preguntar
A3 Quality gate Un PR con un fallo de lint, un test roto o cobertura por debajo del umbral no se puede mergear. Verificable abriendo un PR de prueba: el botón de merge está deshabilitado
A4 Artefacto inmutable identificado por digest El pipeline produce un artefacto (imagen de contenedor o equivalente) publicado en un registro, referenciado por digest en todos los despliegues. El revisor puede ver el digest en el resumen del run y comprobar que es el mismo que se desplegó
A5 Protección de rama main no admite push directo. Existe al menos un check obligatorio. Verificable intentando un push directo: es rechazado
A6 Feedback rápido El tiempo desde el push hasta el primer resultado significativo está medido y documentado, y es inferior a 10 minutos

Grupo B — Despliegue continuo (módulo 3)

# Requisito Criterio de aceptación
B1 Separación CI/CD Son workflows distintos con permisos distintos. El de CD no se ejecuta si el de CI falló. Verificable en el YAML y en el historial de ejecuciones
B2 Al menos un entorno con aprobación Existe un entorno cuyo despliegue requiere una acción humana explícita. El revisor puede ver en el historial una ejecución que estuvo en estado Waiting
B3 Despliegue idempotente Ejecutar el despliegue dos veces con el mismo artefacto no cambia nada la segunda vez. Verificable relanzando el workflow y leyendo el log
B4 Smoke test posterior al despliegue Existe una verificación automática que falla si el despliegue fue malo. Debe estar demostrado: un run histórico donde el smoke test bloqueó un despliegue
B5 Promoción sin reconstruir El artefacto que llega al último entorno es byte a byte el mismo que se validó en el primero. Hay una comprobación explícita del digest en el log
B6 Rollback cronometrado < 10 min Existe un procedimiento de rollback ejecutable con una acción, y un run histórico con el tiempo medido en el resumen
B7 Rollback ejecutable por otra persona La restricción 5 del contexto. Documentado en un runbook con el comando exacto y sin conocimiento tácito

Grupo C — Prácticas avanzadas (módulo 4)

# Requisito Criterio de aceptación
C1 Caché y paralelización con tiempos medidos El PIPELINE.md documenta el tiempo antes y después de aplicar caché y paralelización, con capturas o enlaces a los runs concretos
C2 Lógica en scripts, YAML delgado Los pasos con lógica están en scripts/, son ejecutables en local y el YAML los invoca. Verificable: el revisor puede ejecutar ./scripts/desplegar.sh en su máquina
C3 Al menos una pieza reutilizable Una composite action, un reusable workflow o un script compartido entre al menos dos workflows, con su documentación
C4 Gestión de dependencias automatizada Dependabot o equivalente configurado, con agrupación y política de qué se automerge y qué no
C5 Sin "verde falso" Ningún `

Grupo D — Seguridad (módulo 4 y lección 07-05)

# Requisito Criterio de aceptación
D1 Mínimo privilegio permissions: explícito en todos los workflows. Ningún write-all. El permiso por defecto del repositorio es de lectura
D2 Acciones fijadas por SHA Todas las acciones de terceros por SHA de 40 caracteres con comentario de versión. Verificable con un grep
D3 Los cinco escaneos Secretos, SCA, SAST, imagen y configuración. Los cinco reportan a un sitio consultable
D4 Política de severidades Existe un documento que dice qué rompe el build y qué no, y el pipeline la implementa. Las excepciones tienen justificación y fecha de caducidad
D5 Sin secretos de larga vida en el camino crítico Se usa OIDC o tokens efímeros. Si hay algún secreto persistente, está en un entorno protegido y justificado
D6 Datos personales protegidos La restricción 4 del contexto: ninguna prueba usa datos reales, ningún log imprime datos personales, ningún dump de base de datos sale del entorno de producción

Grupo E — Observabilidad (módulo 3 y lección 07-04)

# Requisito Criterio de aceptación
E1 Métricas expuestas La aplicación expone métricas consultables que cubren al menos tres de las cuatro señales de oro
E2 Un SLO con presupuesto de error Documentado con sus cuatro elementos (indicador, umbral, objetivo, ventana) y la aritmética del presupuesto escrita
E3 Una alerta por síntoma Definida con un for:, con runbook enlazado, y demostrada: hay evidencia de haberla visto pasar a firing
E4 Las cuatro DORA calculadas automáticamente Un job programado las calcula y publica. El revisor puede ver al menos dos ejecuciones para comparar
E5 La mejora demostrada El PIPELINE.md compara la línea base del apartado 2 con las métricas actuales

Total: 29 requisitos. No se espera que todos queden impecables; se espera que todos estén considerados y que las ausencias sean decisiones documentadas, no olvidos.

  1. Entregables

4.1 El repositorio

Público (o privado con acceso al revisor), con historial real: ramas, PR, checks, runs con éxito y runs con fallo. Un repositorio con un solo commit gigante no demuestra un pipeline; demuestra un fichero.

Estructura sugerida:

proyecto/
├── .github/
│   ├── workflows/          ci.yml, cd.yml, rollback.yml, seguridad.yml, dora.yml
│   ├── actions/            composite actions propias
│   └── dependabot.yml
├── scripts/                toda la logica: desplegar, smoke, vigilar, dora...
├── src/  test/
├── seguridad/              POLITICA.md, excepciones.json, .trivyignore
├── observabilidad/         compose, prometheus.yml, alertas.yml, SLO.md, RUNBOOK.md
├── Dockerfile  .dockerignore
├── PIPELINE.md             ← entregable 4.2
├── POSTMORTEM.md           ← entregable 4.3
└── README.md               qué es, cómo se ejecuta, badges

4.2 PIPELINE.md — decisiones y contrapartidas

Este es el entregable que más se nota y el que peor se hace. No es documentación de qué hace el pipeline —eso se lee en el YAML—: es el registro de por qué es así y qué se sacrificó.

Plantilla mínima:

# Decisiones del pipeline

## Contexto y restricciones
Resumen de las restricciones del encargo y cómo condicionan lo que sigue.

## Línea base (antes)
| Métrica | Valor | Cómo se midió |

## Decisiones

### D1 — Herramienta de CI/CD: GitHub Actions
**Alternativas consideradas:** GitLab CI, CircleCI, Jenkins autoalojado.
**Decisión:** GitHub Actions.
**Motivo:** el código ya está en GitHub (restricción de identidad, 06-07);
plan gratuito suficiente para el volumen (restricción 1); cero operación
(restricción 2).
**Contrapartida aceptada:** acoplamiento al proveedor. Se mitiga poniendo
toda la lógica en `scripts/` (C2): una migración costaría ~5 días, no 4 semanas.
**Cuándo revisar esta decisión:** si el volumen de minutos supera el plan
gratuito, o si la empresa cambia de proveedor de repositorios.

### D2 — Estrategia de despliegue: rolling, no canary
...

### D3 — Qué NO hemos hecho y por qué
- **No hay entornos efímeros por PR.** Coste de mantenimiento alto para un
  equipo de tres personas (restricción 2). Se revisará cuando el equipo crezca.
- **No hay pruebas de carga en el pipeline.** El volumen actual (4.000
  citas/mes) no las justifica.
...

## Mediciones
| Cambio | Antes | Después | Run de referencia |
| Caché de dependencias | 3 min 40 s | 1 min 15 s | #128 vs #131 |

## Después
| Métrica DORA | Antes | Ahora | Fuente |

La sección "Qué NO hemos hecho y por qué" es la que distingue un trabajo profesional de un ejercicio. Un pipeline sin límites explícitos es un pipeline que crecerá sin control hasta que alguien lo abandone.

4.3 POSTMORTEM.md — un fallo provocado a propósito

Provoca un fallo real, déjalo llegar hasta donde tu pipeline lo detenga, y escribe el post-mortem. Sugerencias de fallo, en orden de dificultad:

Fallo Dónde debería detenerse Qué demuestra
Un test roto En CI, en el primer job Lo básico
Una regresión que las pruebas no cubren En el smoke test de staging Que las capas se complementan
Una migración de BD incompatible hacia atrás En el despliegue, o en el rollback Lo aprendido en la 04-06
Una versión que arranca bien y se degrada a los 5 minutos En la vigilancia posterior, con rollback automático El bucle completo cerrado

Estructura del post-mortem, sin culpables:

# Post-mortem: <título descriptivo del impacto, no de la causa>

**Fecha:** · **Duración del impacto:** · **Severidad:** · **Autor:**

## Impacto
Qué dejó de funcionar, para quién y durante cuánto. En términos de usuario,
no de infraestructura: "los negocios no podían ver los huecos del día",
no "el contenedor estaba unhealthy".

## Cronología
| Hora | Evento | Quién / qué lo detectó |
|---|---|---|
| 10:32 | Merge del PR #47 | — |
| 10:38 | Despliegue a staging | pipeline |
| 10:39 | Smoke test falla | pipeline (automático) |
| 10:39 | Despliegue a producción bloqueado | pipeline |

## Causa raíz
La técnica de los cinco porqués, hasta llegar a algo sistémico.
Si la respuesta final es "un desarrollador se equivocó", no has llegado al final:
la pregunta siguiente es "¿por qué el sistema permitió que ese error llegara ahí?".

## Qué funcionó
Igual de importante que lo que falló. Aquí se justifica la inversión en el pipeline.

## Qué no funcionó

## Acciones correctivas
| # | Acción | Responsable | Fecha | Estado |
Con responsable y fecha, o no es una acción: es un deseo.

## Lecciones

4.4 Panel o resumen de métricas

Un panel de Grafana versionado, o —si no montas Prometheus— un $GITHUB_STEP_SUMMARY de un job programado con las cuatro DORA, el estado del SLO y el consumo del presupuesto de error. Lo que se evalúa es que exista una superficie donde alguien que no eres tú pueda ver cómo va la cosa sin pedirte nada.

  1. Rúbrica de autoevaluación

Aplícatela con honestidad. La columna "Insuficiente" describe lo que la mayoría entrega en el primer intento.

Criterio Insuficiente Correcto Excelente
Build reproducible El pipeline "funciona" pero no se puede reproducir en local Lockfile, runtime fijado, mismo comando en local y en CI Además, verificado periódicamente por un job que ejecuta el build en una máquina limpia
Pruebas Solo unitarias, o cobertura sin asserts Tres capas identificables, umbral de cobertura que rompe Además, test de contrato entre implementaciones, casos límite documentados y detección de flaky
Quality gate Los checks existen pero no bloquean main protegida con check obligatorio, comprobado por el lado negativo Job agregador que desacopla la protección de la forma del pipeline
Artefacto Se reconstruye en cada entorno Imagen publicada, desplegada por digest Firmada, con SBOM, y la firma se verifica antes de desplegar
Separación CI/CD Un solo workflow lo hace todo Workflows separados con permisos distintos Además, el CD se puede lanzar a mano con un digest arbitrario para reintentos
Puerta de aprobación No hay Entorno con revisor requerido Aprobación condicional: automática si las métricas están bien, humana si no
Idempotencia Redesplegar reinicia el servicio sin necesidad El script detecta que ya está desplegado y no hace nada Además, el script rechaza referencias mutables y valida antes de tocar nada
Smoke test Solo comprueba que responde 200 Comprueba salud, funcionalidad y versión desplegada Además, comprueba que los errores siguen dando error, y hay un run donde bloqueó
Rollback Existe como documento Workflow ejecutable, cronometrado, < 10 min < 3 min, automático por métricas, y ejecutado con éxito por otra persona
Rendimiento Sin medir Caché y paralelización aplicadas, tiempos documentados Ejecución selectiva por cambios, y el coste en minutos también medido
Reutilización Todo copiado y pegado entre workflows Una pieza compartida y documentada Reusable workflow versionado, con inputs, outputs y su propia prueba
Mínimo privilegio Sin permissions Explícito en workflow y ampliado por job Verificado provocando el fallo, y documentado qué necesita cada job
Escaneos Ninguno, o con ` true`
Secretos En el repositorio o en variables globales Secretos de entorno, alcance mínimo OIDC / tokens efímeros; ningún secreto de larga vida en el camino crítico
Observabilidad Solo logs Métricas expuestas y un panel SLO con presupuesto, alerta demostrada y despliegues anotados en el panel
DORA No se calculan Calculadas a mano una vez Job programado, histórico y tendencia comparada con la línea base
PIPELINE.md Describe qué hace el YAML Explica por qué, con alternativas Incluye contrapartidas, límites explícitos y cuándo revisar cada decisión
POSTMORTEM.md Narra el fallo Cronología, causa raíz, acciones Sin culpables, con "qué funcionó", y las acciones tienen responsable y fecha
Reproducibilidad por un tercero Solo tú sabes ejecutarlo README con los pasos Un revisor externo lo verifica entero en una hora sin preguntarte nada

Cómo puntuarte: cuenta cuántas filas caen en cada columna.

  • Mayoría en Insuficiente: tienes un pipeline que funciona pero no es defendible. Prioriza el grupo A y el B4/B6.
  • Mayoría en Correcto: es un pipeline profesional, entregable. Es el objetivo realista del curso.
  • Varias en Excelente: estás por encima de lo que tienen muchos equipos en producción. Elige dos o tres para llevar a excelente en vez de subir todas a la vez.

  1. Plan de trabajo en cinco sesiones

Cinco sesiones de 2-4 horas. El orden no es arbitrario: cada sesión deja algo funcionando y medible, y ninguna depende de terminar la siguiente para aportar valor. Es el mismo principio de los siete incrementos de la 05-04.

Sesión 1 — Medir y hacer verificable el proyecto (sin tocar el pipeline)

  1. Mide la línea base. Las cuatro DORA con los datos que tengas, aunque sean aproximados. Anótalas en PIPELINE.md hoy, porque dentro de tres semanas no podrás reconstruirlas.
  2. Consigue que el proyecto se verifique con un solo comando: npm ci && npm run lint && npm test && npm run build. Si eso no funciona en una máquina limpia, arréglalo antes de escribir una línea de YAML.
  3. Escribe la prueba que falta para el bug más reciente que hayáis tenido.
  4. Commitea el lockfile si no está.

Entregable de la sesión: un comando que verifica el proyecto y la línea base escrita.

Sesión 2 — CI y la primera puerta

  1. ci.yml incremental, como en la 07-01: primero que se ejecute, luego que instale y pruebe, luego jobs en paralelo, luego caché. Mide los tiempos en cada paso y anótalos.
  2. Las tres capas de pruebas (07-02). Empieza por la que más miedo te da romper.
  3. Cobertura con umbral 2-3 puntos por debajo del valor actual.
  4. Protección de main con un job agregador como único check requerido.
  5. Rompe algo a propósito y comprueba que bloquea.

Entregable: A1-A6 cumplidos, con los tiempos antes/después de la caché.

Sesión 3 — Artefacto y despliegue

  1. Dockerfile multi-etapa, no-root, HEALTHCHECK (07-03).
  2. Publicación en el registro por digest, con el digest visible en el resumen.
  3. scripts/desplegar.sh idempotente y ejecutable en local. Escríbelo antes que el YAML: si empiezas por el YAML, acabarás con lógica dentro del YAML.
  4. scripts/smoke.sh que verifique salud, funcionalidad y versión.
  5. cd.yml con dos entornos y aprobación en el segundo.
  6. rollback.yml cronometrado. Ejecútalo y anota el tiempo.
  7. Provoca un despliegue malo y comprueba que el smoke test lo detiene.

Entregable: B1-B7 cumplidos, con el run del rollback cronometrado y el run del despliegue bloqueado.

Sesión 4 — Seguridad

  1. Auditoría de lo que llevas construido, con la lista de la 07-05.
  2. permissions de mínimo privilegio, provocando un fallo para entenderlo.
  3. Acciones por SHA + Dependabot.
  4. Los cinco escaneos, uno cada vez, comprobando que cada uno detecta algo real antes de pasar al siguiente.
  5. Política de severidades escrita y el job de caducidad de excepciones.
  6. SBOM, firma y verificación antes de desplegar.

Entregable: D1-D6, con evidencia de que cada escaneo ha detectado algo.

Sesión 5 — Observabilidad, cierre y documentación

  1. /metricas con las señales de oro (07-04).
  2. SLO con la aritmética del presupuesto escrita.
  3. Una alerta por síntoma, disparada a propósito y con captura.
  4. Job programado de DORA. Ejecútalo dos veces con días de diferencia para tener tendencia.
  5. Provoca el fallo del post-mortem y escríbelo.
  6. PIPELINE.md completo, incluida la sección de qué no has hecho.
  7. Pásate la rúbrica.

Entregable: E1-E5, PIPELINE.md, POSTMORTEM.md y la autoevaluación.

Consejo sobre el ritmo. Si vas corto de tiempo, sacrifica el grupo E antes que el B. Un pipeline que despliega y revierte pero no se mide es incompleto; uno que se mide pero no puede revertir es peligroso. Y si tienes que elegir un solo requisito de los 29, que sea B6: rollback cronometrado. Es el que convierte el miedo en un número.

  1. Retos opcionales

Para cuando lo básico esté cerrado. Cada uno vale por sí solo.

Reto Qué añade Dificultad Referencia
Canary real con decisión automática Despliegue por peso + medición + promoción o retirada automática Alta 03-04, 07-03 ej. 2
Entornos efímeros por PR Un entorno por pull request, destruido al cerrarlo Alta 02-07, 06-02
Matriz de dos herramientas El mismo pipeline en GitHub Actions y en GitLab CI, comparando esfuerzo real Media Módulo 6 completo
IaC del entorno de destino Terraform que crea el host, el registro y la red, con plan en PR y apply tras aprobación Alta 03-03
Migraciones de BD en el pipeline Expand and contract, migración versionada, y un rollback que no pierde datos Muy alta 04-06
Política de admisión externa Un script que valida firma, SBOM, escaneos y procedencia, consultado por el CD Media 07-05 reto
Reparto de shards por tiempos Balanceo real de la suite con histórico Media 07-02 reto

El más instructivo de todos, si quieres cerrar el curso con algo que te cambie la perspectiva, es la matriz de dos herramientas: reimplementar el pipeline en GitLab CI te obliga a separar lo que es tu proceso de lo que es sintaxis de GitHub, y esa separación es exactamente la que la 06-07 defendía. Se tarda menos de lo que parece —el trabajo real ya está en los scripts— y el resultado es una tabla de equivalencias que has escrito tú.

  1. Errores típicos del proyecto final

Estos tres son, con diferencia, los que más se repiten. Los tres tienen la misma forma: hacer la parte visible antes que la parte que la sostiene.

Error 1: empezar por el YAML en vez de por los scripts

Cómo se manifiesta. Se abre ci.yml y se empieza a escribir. A los tres días hay 200 líneas de YAML con run: | de veinte líneas cada uno, y la única forma de probar un cambio es hacer push y esperar cuatro minutos.

Por qué es grave. El ciclo de depuración pasa de segundos a minutos, y multiplicado por cada intento. Un problema que en local se resuelve en cinco iteraciones de diez segundos se convierte en cinco iteraciones de cuatro minutos, con commits de "arreglar CI", "arreglar CI 2", "ahora sí". Además, esa lógica no es testeable, no es revisable y no se puede ejecutar en una emergencia si el CI está caído.

El orden correcto:

1. El comando funciona en tu terminal
2. El comando está en un script con argumentos y valores por defecto
3. El script está en el repositorio y tiene su documentación
4. El YAML LLAMA al script

Prueba de fuego: ¿puedes desplegar sin GitHub Actions? Si la respuesta es no, la lógica está en el sitio equivocado.

Error 2: automatizar antes de tener una prueba que valga

Cómo se manifiesta. Un pipeline precioso que despliega en noventa segundos... el código roto. Las pruebas existen, pasan siempre, y no cubren nada de lo que se rompe de verdad.

Por qué es grave. Automatizar el despliegue multiplica la velocidad a la que llegan los cambios a producción. Si la verificación es débil, lo que has multiplicado es la velocidad a la que llegan los bugs. Un pipeline rápido sobre pruebas malas es objetivamente peor que el despliegue manual del principio, porque el manual al menos incluía a una persona mirando.

El orden correcto: una prueba que detecte el último bug real que tuvisteis, antes de automatizar el despliegue. Si no puedes escribirla, no automatices todavía: automatiza solo hasta staging y deja producción manual hasta que la red de seguridad exista.

La señal de alarma: si tu suite nunca ha estado en rojo por un bug real —solo por errores de sintaxis—, no está probando nada.

Error 3: no medir la línea base y quedarse sin poder demostrar la mejora

Cómo se manifiesta. Tres semanas de trabajo, un pipeline excelente, y en la reunión con la dirección: "¿y esto qué ha mejorado?""Pues... va todo mucho mejor".

Por qué es grave. Es el error que hace que la siguiente inversión no se apruebe. Recuerda la restricción 6 del contexto: el backend ya piensa que esto es tiempo robado al producto. Sin números, tiene razón él, porque su escepticismo sí está basado en algo concreto (las horas invertidas) y tu defensa no.

Y hay un agravante técnico: la línea base no se puede reconstruir a posteriori. Una vez que el pipeline está montado, el "antes" ya no existe. Es información que se destruye al hacer el trabajo.

El orden correcto: medir en la sesión 1, antes de tocar nada, aunque sea con estimaciones toscas. Cuatro números y la fecha. Diez minutos de trabajo que valen por las tres semanas siguientes.

Cómo se presenta después:

Métrica Antes (12/03) Ahora (28/04) Cambio
Frecuencia de despliegue 0,5 / semana 6 / semana ×12
Lead time 9 días 4 h −98 %
Change failure rate 20 % 6 % −70 %
Time to restore 140 min 3 min −98 %
Tiempo de la tech lead en desplegar 45 min/despliegue 0 −6 h/mes

Esa última fila es la que cierra la discusión, y por eso conviene tenerla: traduce el trabajo a horas de personas, que es la unidad en la que piensa quien aprueba presupuestos. Es exactamente el argumento del TCO de la 06-07, aplicado a tu propio proyecto.

  1. Errores Comunes y Consejos

Síntoma: el proyecto se atasca en la sesión 3 y no llega a producción. Causa: intentar montar el entorno de destino "de verdad" (un VPS, Kubernetes, AWS) antes de tener el pipeline. Arreglo: usa un destino simulado como el de la 07-03 y termina el circuito completo. Un pipeline que despliega a un contenedor local pero cubre las siete piezas de B1-B7 vale infinitamente más que medio pipeline apuntando a infraestructura real. Cambia el destino al final; es la parte más fácil de cambiar.

Síntoma: 29 requisitos parecen inabordables y no se empieza. Causa: intentar hacerlos en paralelo. Arreglo: el plan de cinco sesiones está ordenado por dependencia. Haz A completo antes de tocar B. Un grupo terminado vale más que cinco a medias, porque los grupos incompletos no se pueden verificar.

Síntoma: el PIPELINE.md acaba siendo una descripción del YAML. Causa: documentar mientras se escribe el código, cuando aún no hay perspectiva. Arreglo: escribe cada decisión en el momento en que descartas una alternativa, con una línea: "descartado X porque Y". Al final, esas líneas son el documento. Si nunca descartaste nada, no tomaste decisiones: copiaste.

Síntoma: la rúbrica sale mayoritariamente en "Correcto" y no sabes qué mejorar. Consejo: no subas todo a "Excelente". Elige dos o tres con criterio: las que más reduzcan el riesgo en tu contexto concreto. Con las restricciones de Citas Norte, las tres candidatas obvias son el rollback (restricción 5), la verificación de firma (restricción 4, datos personales) y las DORA con tendencia (restricción 6, hay que convencer a alguien).

Consejo — no lo hagas todo tú. Si tienes con quién, pide a alguien que verifique tu repositorio siguiendo los criterios de aceptación, sin que le expliques nada. Los puntos donde tenga que preguntarte algo son exactamente los que te faltan por documentar. Es la prueba más barata y la más reveladora del proyecto.

Consejo — el pipeline nunca está terminado. Cuando cierres los 29 requisitos, el pipeline será bueno para el contexto de hoy. Con el doble de equipo y diez veces el tráfico, tres de tus decisiones serán incorrectas. Por eso cada decisión del PIPELINE.md lleva "cuándo revisar esta decisión": no es burocracia, es reconocer que un pipeline es un organismo vivo y que la alternativa a revisarlo es reescribirlo entero dentro de dos años.

  1. Ejercicios

Estos tres no son variaciones del laboratorio: son extensiones del propio proyecto final, pensadas para hacerlas después de entregarlo.

Ejercicio 1: la revisión cruzada

Intercambia repositorios con otra persona que haya hecho el proyecto (o audita un repositorio público real que use GitHub Actions). Aplica los 29 criterios de aceptación sin hablar con nadie y escribe un informe de auditoría con los hallazgos priorizados.

Ejercicio 2: la prueba de las vacaciones

La restricción 5 del contexto: la tech lead se va tres semanas. Demuestra que el sistema sobrevive.

Ejercicio 3: el mismo pipeline con la mitad del tiempo

Reduce a la mitad el tiempo de tu pipeline sin quitar ninguna verificación. Documenta cada cambio con su medición.

Soluciones

Solución 1. Plantilla de informe de auditoría:

# Auditoría del pipeline de <repositorio>
**Auditor:** · **Fecha:** · **Tiempo empleado:** · **Commit auditado:**

## Resumen ejecutivo
Tres frases: estado general, el riesgo más grave, la mejora de mayor
relación valor/esfuerzo.

## Verificación de criterios
| # | Requisito | Cumple | Evidencia | Notas |
|---|---|---|---|---|
| A1 | Build reproducible | ✅ | Ejecuté `npm ci && npm test` en limpio: OK | — |
| A4 | Artefacto por digest | ⚠️ | Run #88: publica por digest pero el CD usa `:main` | **La promoción no garantiza el mismo artefacto** |
| B4 | Smoke test | ❌ | No encontré ningún run donde bloqueara | Puede que nunca se haya probado |

## Hallazgos priorizados
### H1 (Alto) — El CD despliega por tag, no por digest
**Evidencia:** `cd.yml:47` usa `ghcr.io/...:main`.
**Riesgo:** entre la validación en staging y el despliegue a producción, otro
merge puede mover el tag. Producción ejecutaría código no validado.
**Arreglo:** resolver el digest una vez en un job `preparar` y propagarlo por
`outputs`. Coste: ~30 min.

## Lo que está bien hecho
(Obligatorio. Una auditoría que solo lista problemas no se lee entera y
no se aplica.)

## Preguntas que tuve que hacer al autor
Cada una de estas es documentación que falta.

Lo que enseña este ejercicio: auditar el trabajo de otro es la forma más rápida de ver los agujeros del tuyo. Casi todo el mundo encuentra en el repositorio ajeno dos o tres cosas que también le faltan al propio y que no había visto en semanas.

Solución 2. El protocolo de la prueba:

# Prueba de continuidad ("las vacaciones")

## Regla
Durante el ejercicio, quien escribió el pipeline **no habla, no toca el teclado
y no responde preguntas**. Solo observa y toma notas.

## Escenario 1 — Despliegue rutinario (objetivo: < 15 min)
La otra persona debe, usando solo el repositorio:
1. Localizar cómo se despliega.
2. Lanzarlo.
3. Aprobar la puerta de producción.
4. Verificar que la versión nueva está sirviendo tráfico.

## Escenario 2 — Rollback bajo presión (objetivo: < 10 min)
Se despliega una versión mala (rompe `/salud`). La otra persona debe:
1. Darse cuenta de que algo va mal (¿la alerta llegó? ¿a quién?).
2. Encontrar a qué versión volver.
3. Ejecutar el rollback.
4. Confirmar la recuperación.

## Escenario 3 — Fallo del pipeline (objetivo: desplegar sin CI)
GitHub Actions está caído (simúlalo deshabilitando el workflow) y hay que
desplegar un parche urgente. ¿Existe un camino manual documentado?

## Registro
| Escenario | Tiempo | ¿Lo consiguió? | Dónde se atascó | Documentación que faltaba |

## Acciones correctivas
Cada atasco es un fallo del SISTEMA, no de la persona. Se convierte en:
- Una línea en el runbook, o
- Un valor por defecto mejor, o
- Un mensaje de error más claro.

Los tres fallos que aparecen casi siempre en este ejercicio, por si quieres adelantarte:

  1. Encontrar el digest anterior. Nadie sabe dónde mirar. Arreglo: imprimirlo en el resumen de cada despliegue y aceptar el input vacío en el rollback (07-03 ejercicio 1).
  2. La alerta no llegó a nadie. Estaba configurada en Prometheus pero sin destinatario. Arreglo: Alertmanager con un canal real, y una prueba de que llega.
  3. El camino manual no existe. Todo el conocimiento está dentro del YAML. Arreglo: scripts/desplegar.sh ejecutable en local (requisito C2), documentado en el runbook con el comando literal.

Si tu proyecto pasa el escenario 3, has cumplido el criterio más exigente de todo el curso: el pipeline es una comodidad, no una dependencia.

Solución 3. La estrategia, en orden de rentabilidad:

# Reducción del tiempo de pipeline

## Medición inicial (run #142)
| Job | Duración | ¿Camino crítico? |
|---|---|---|
| calidad | 1m 10s | No |
| test (×4) | 3m 40s | **Sí** |
| cobertura | 2m 50s | No |
| build | 2m 20s | Sí |
| publicar | 4m 10s | **Sí** |
| **Total (pared)** | **10m 30s** | |

Regla previa: **solo cuenta el camino crítico**. Optimizar un job que corre en
paralelo con otro más lento no ahorra ni un segundo de tiempo de pared.

## Cambios aplicados

### C1 — Caché de dependencias (−1m 50s)
`cache: 'npm'` en los 5 jobs. Segunda ejecución en adelante.
Antes: `npm ci` 22s/job · Después: 4s/job.

### C2 — Caché de capas de Docker (−2m 30s)
`cache-from: type=gha` / `cache-to: type=gha,mode=max`.
El mayor ahorro individual: el módulo nativo dejó de recompilarse.

### C3 — Reordenar el Dockerfile (−40s)
`COPY package*.json` y `npm ci` ANTES de `COPY . .`.
Sin esto, cualquier cambio de código invalida la capa de dependencias
y la caché de C2 no sirve para nada. **C3 es lo que hace que C2 funcione.**

### C4 — Fusionar `cobertura` en el job de test (−0s de pared, −2m de máquina)
No estaba en el camino crítico: no ahorra tiempo de pared, pero sí coste.
Se documenta porque el coste también es una métrica.

### C5 — Ejecución selectiva (−variable)
Los jobs pesados solo si cambian los ficheros relevantes, con job agregador
que siempre reporta (07-01 ejercicio 2). En PR de solo documentación:
10m 30s → 45s.

### C6 — Descartado: runners más grandes
Reduciría ~30 % pero cuesta dinero. Restricción 1 del encargo.
**Se documenta el descarte para que no haya que volver a evaluarlo.**

## Resultado (run #171)
| Job | Antes | Después |
|---|---|---|
| test (×4) | 3m 40s | 1m 30s |
| publicar | 4m 10s | 1m 20s |
| **Total (pared)** | **10m 30s** | **4m 15s** (−60 %) |
| Minutos de máquina | 14m 10s | 7m 30s (−47 %) |

## Verificaciones NO eliminadas
Ninguna. Mismos 5 escaneos, misma cobertura, misma matriz.
`git diff` de los workflows: solo caché, orden y condiciones.

La lección de este ejercicio es C3: la caché de Docker no funciona si el Dockerfile está mal ordenado, y mucha gente añade C2, no ve mejora y concluye que "la caché no sirve". El orden de las capas es el 80 % del resultado, y es gratis.

  1. Conclusión y cierre del curso en la práctica

Si has llegado hasta aquí con el proyecto entregado, tienes en tu repositorio algo que muchos equipos en producción no tienen: un pipeline que integra, verifica en tres capas, construye un artefacto inmutable identificado por su contenido, lo escanea de cinco formas distintas, lo firma, lo despliega tras una puerta explícita, comprueba que el despliegue funcionó, promociona el mismo artefacto sin reconstruirlo, revierte en minutos —solo, si las métricas empeoran—, y se mide a sí mismo para poder demostrar que todo eso sirve de algo.

Pero el entregable que más va a durar no es el YAML. Son los dos documentos.

El PIPELINE.md, porque contiene lo único que no se puede deducir leyendo el código: por qué es así y qué se sacrificó a cambio. Dentro de un año, cuando alguien —quizá tú— se pregunte por qué no hay canary o por qué las acciones están fijadas por esos SHA raros, la respuesta estará escrita, con su fecha y con la condición que obligaría a revisarla. Un pipeline sin ese documento se reescribe entero cada dos años porque nadie se atreve a tocar lo que no entiende.

Y el POSTMORTEM.md, porque documenta la única prueba que de verdad importa: que el sistema falló y lo aguantó. Cualquiera puede enseñar un pipeline en verde. Enseñar uno que se puso en rojo por el motivo correcto, en el sitio correcto, y que se recuperó en tres minutos, es enseñar que funciona.

Hay una última cosa que este módulo te ha hecho hacer sin decírtelo explícitamente, y conviene nombrarla ahora. En cada laboratorio has roto algo a propósito: un test, un despliegue, un secreto, una consulta SQL, un endpoint lento. Eso no era decoración pedagógica. Es la práctica profesional que separa a quien tiene un pipeline de quien confía en su pipeline: verificar por el lado negativo. Cualquiera puede comprobar que un control deja pasar lo bueno; comprobar que detiene lo malo requiere fabricar lo malo, y casi nadie lo hace. Si te llevas una sola costumbre del curso, que sea esta: cada vez que añadas una puerta, provoca el fallo que debería detener, y no des la puerta por buena hasta haberlo visto.

Con esto se cierra la parte práctica y, con ella, la materia del curso. Has recorrido los principios (módulos 1 a 4), cuatro contextos reales (módulo 5), la maquinaria (módulo 6) y la construcción de extremo a extremo con tus manos (módulo 7). Lo que queda ya no es materia: es a dónde ir después.

El módulo 8 es el mapa de esa continuación. Las lecturas recomendadasContinuous Delivery, Accelerate, The DevOps Handbook, el SRE Workbook— que dan el fundamento y los datos detrás de casi todo lo que has aplicado aquí. Las comunidades y foros donde se discuten estos problemas cuando se salen de lo que cabe en un curso. Las herramientas y plugins adicionales que quedaron fuera por espacio y que resuelven problemas concretos que ya sabrás reconocer: gestión de secretos con Vault, entrega progresiva con Flagger o Argo Rollouts, plataformas internas de desarrollo, políticas como código. Y la ruta de aprendizaje y certificaciones, con el orden razonable para profundizar según hacia dónde quieras moverte —plataforma, SRE, seguridad de la cadena de suministro— y qué certificaciones valen realmente la pena en cada caso.

Empieza por 08-01: Lecturas Recomendadas. Y, cuando lo hagas, léelo con el pipeline delante: ahora tienes un sistema real sobre el que probar cada idea, que es exactamente lo que faltaba la primera vez que abriste este curso.

Curso de CI/CD: Integración y Despliegue Continuo

Módulo 1: Introducción a CI/CD

Módulo 2: Integración Continua (CI)

Módulo 3: Despliegue Continuo (CD)

Módulo 4: Prácticas Avanzadas de CI/CD

Módulo 5: Implementación de CI/CD en Proyectos Reales

Módulo 6: Herramientas y Tecnologías

Módulo 7: Ejercicios Prácticos

Módulo 8: Recursos Adicionales

© Copyright 2026. Todos los derechos reservados