Módulo 6: Proyecto — Pipeline CI/CD Completo con Claude Code
Failure Paths y Observabilidad
Failure Paths y Observabilidad
Descripción
Las cápsulas 03-04 cubrieron el happy path: lo que pasa cuando todo sale bien. Pero un pipeline production-ready maneja también los casos donde algo falla. Esta cápsula cubre los failure paths del pipeline y la observabilidad necesaria para detectarlos, diagnosticarlos, y responder.
Vas a implementar Phase 4 (post-deploy monitoring + auto-rollback + diagnóstico) y diseñar el comportamiento del pipeline para los 5 modos principales de fallo: code review/security/tests bloquean, staging deploy falla, métricas degradan en producción, approval rechazado, y deploy a producción falla. Cada uno con respuesta clara y observable.
Al terminar, vas a tener un pipeline que falla con gracia en cada modo de fallo, monitoring activo post-deploy, y observabilidad que el equipo usa para tomar decisiones con datos.
Los 5 Failure Modes
1. PR REVIEW BLOQUEA (Phase 1)
- Code review encontró critical issues → bloquea merge
- Security scan encontró critical → bloquea merge
- Tests fallan → bloquea merge
Comportamiento: el PR no puede mergear hasta resolver
Visibilidad: status checks rojos en el PR + comments
2. PRE-DEPLOY VALIDATION FALLA (Phase 2)
- Readiness validation detecta env vars faltantes
- Migrations problemáticas
Comportamiento: deploy a staging no procede
Visibilidad: workflow run failed + readiness report como artifact
3. STAGING DEPLOY FALLA (Phase 3)
- Deploy script error
- Smoke tests staging fallan
- Métricas de staging degradan
Comportamiento: production gate no se activa
Visibilidad: workflow falla, equipo notificado vía Slack
4. APPROVAL RECHAZADO (Phase 3)
- Reviewer humano click "Reject"
- Timeout (24 hrs sin approval)
Comportamiento: deploy a producción no procede
Visibilidad: PR comment + workflow status
5. PRODUCTION FALLA POST-DEPLOY (Phase 4)
- Smoke tests producción fallan
- Métricas degradan después del deploy
Comportamiento: rollback automático + diagnóstico + notification
Visibilidad: PagerDuty incident + Slack + Issue de postmortem
Para cada uno: comportamiento esperado + visibilidad + recovery path.
Phase 4: Implementación Completa
# Continuación del workflow staged-deployment.yml
monitor-post-deploy:
needs: deploy-production
runs-on: ubuntu-latest
outputs:
rollback_needed: ${{ steps.monitor.outputs.rollback_needed }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11', cache: 'pip' }
- run: pip install anthropic requests
- name: Monitor production for 10 minutes
id: monitor
env:
METRICS_API_URL: ${{ secrets.METRICS_API_URL }}
METRICS_API_TOKEN: ${{ secrets.METRICS_API_TOKEN }}
run: |
python scripts/monitor_post_deploy.py
if [ $? -eq 1 ]; then
echo "rollback_needed=true" >> $GITHUB_OUTPUT
else
echo "rollback_needed=false" >> $GITHUB_OUTPUT
fi
continue-on-error: true # ← rollback es separado
rollback:
needs: [deploy-production, monitor-post-deploy]
if: needs.monitor-post-deploy.outputs.rollback_needed == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Execute rollback
env:
PREVIOUS_RELEASE: ${{ needs.deploy-production.outputs.previous_release }}
run: |
echo "🚨 Rolling back production to $PREVIOUS_RELEASE"
./scripts/rollback.sh production "$PREVIOUS_RELEASE"
- name: Verify rollback with smoke tests
run: ./scripts/smoke_tests.sh https://app.example.com
diagnose:
needs: [deploy-production, monitor-post-deploy, rollback]
if: always() && needs.monitor-post-deploy.outputs.rollback_needed == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: actions/setup-python@v5
with: { python-version: '3.11', cache: 'pip' }
- run: pip install anthropic requests
- name: Generate diagnosis
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
DEPLOY_SHA: ${{ needs.deploy-production.outputs.new_release }}
PREVIOUS_SHA: ${{ needs.deploy-production.outputs.previous_release }}
run: python scripts/diagnose_incident.py
- name: Create postmortem issue
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: python scripts/create_postmortem_issue.py
- name: Notify team of rollback
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
PAGERDUTY_TOKEN: ${{ secrets.PAGERDUTY_TOKEN }}
run: python scripts/notify_rollback.py
notify-success:
needs: [deploy-production, monitor-post-deploy]
if: needs.monitor-post-deploy.outputs.rollback_needed == 'false'
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install requests
- name: Notify success
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
run: python scripts/notify_success.py
Lo importante:
monitor-post-deployconcontinue-on-error: true— fallar acá no rompe el workflow, solo dispara rollbackrollbacksolo corre sirollback_needed == 'true'diagnosecorre incluso si rollback falla (if: always()) — el diagnóstico es info críticanotify-successydiagnoseson mutuamente exclusivos
Comportamiento por Failure Mode
Failure Mode 1: PR Review bloquea
LO QUE PASA:
1. Developer abre PR
2. Phase 1 corre los 3 jobs en paralelo
3. Security scan detecta SQL injection (critical)
4. Job security-scan retorna exit 1
5. Status check "security-scan" se marca rojo en el PR
6. Branch protection bloquea el merge
7. Comment en el PR explica el finding
LO QUE EL DEVELOPER VE:
- Status checks: ❌ security-scan failed
- Comment del bot con el finding específico
- Botón "Merge" deshabilitado
- Instrucciones para resolver
LO QUE EL EQUIPO VE:
- Nada hasta que el developer lo resuelva
- Si lo necesita escalar, abre conversación en el PR
RECOVERY PATH:
1. Developer resuelve el finding (o usa override label si es falso positivo)
2. Push de fix
3. Workflow re-corre
4. Status verde → merge habilitado
Failure Mode 2: Pre-Deploy Validation Falla
LO QUE PASA:
1. PR mergea a main
2. Phase 2 corre: readiness-validation
3. Detecta que `STRIPE_API_KEY` no está configurada en environment "production"
4. Job retorna exit 1
5. Phase 3 no comienza (deploy-staging tiene needs: readiness-validation)
LO QUE EL EQUIPO VE:
- Workflow run failed
- Artifact `readiness-report.json` con el detalle
- Notification en Slack si configurada
RECOVERY PATH:
1. Configurar la env var faltante en GitHub Settings → Environments
2. Re-disparar el workflow manualmente:
- Actions → workflow run → "Re-run all jobs"
3. O hacer un push trivial (`git commit --allow-empty -m "trigger ci"`)
Failure Mode 3: Staging Deploy Falla
LO QUE PASA:
1. Deploy a staging script falla (ej. imagen Docker no encuentra)
2. Job deploy-staging retorna exit 1
3. validate-staging no corre (needs: deploy-staging)
4. Production gate nunca se activa
LO QUE EL EQUIPO VE:
- Workflow failed en staging
- Logs del deploy script
- Notification automática (si configurada)
- Producción NO afectada (no llegó a deployarse)
RECOVERY PATH:
1. Investigar logs del deploy script
2. Si es issue de infraestructura: arreglar y re-disparar
3. Si es issue del código: revertir el commit en main
4. Re-mergear cuando esté listo
Failure Mode 4: Approval Rechazado
LO QUE PASA:
1. Pipeline llegó a "Waiting for approval to deploy: production"
2. Reviewer click "Reject" (o timeout 24hr sin approval)
3. Job deploy-production cancelado
4. Phase 4 no corre
LO QUE EL EQUIPO VE:
- Workflow run en estado "cancelled"
- Comment del reviewer (si dejó razón)
- Producción NO afectada
RECOVERY PATH:
1. Si fue rechazo intencional: revisar la razón, ajustar el código si necesario
2. Si fue timeout sin attention: comunicar al equipo, potencialmente delegar approval
3. Re-disparar el workflow después de fixes
Failure Mode 5: Production Falla Post-Deploy
LO QUE PASA:
1. Deploy a producción exitoso
2. Phase 4 corre monitor-post-deploy
3. Métricas degradan en los primeros 5 min:
- error_rate sube a 8% (threshold: 2%)
- latency_p95 sube 3x baseline
4. monitor-post-deploy retorna exit 1
5. rollback se dispara automáticamente
6. Rollback completo en ~3 min
7. diagnose corre y genera postmortem
8. notify_rollback envía a Slack/PagerDuty
LO QUE EL EQUIPO VE:
- Slack: "🚨 Auto-rollback executed in production"
+ diagnóstico breve
+ link al postmortem issue
- PagerDuty: incident creado (si configurado)
- GitHub Issue creado con postmortem draft
- Producción estabilizada en versión anterior
RECOVERY PATH:
1. On-call abre el postmortem issue
2. Valida el diagnóstico automático
3. Identifica root cause exacto
4. Decide: re-aplicar fix vs investigar más
5. Cuando esté listo: nuevo PR con el fix correcto
6. Pipeline normal a producción
Observabilidad: Lo Que el Equipo Necesita Ver
DASHBOARDS NECESARIOS:
1. Pipeline Health Dashboard
- Tasa de éxito de deploys (%)
- Duración promedio del pipeline
- Failures por phase
- MTTR (mean time to recovery) cuando hay rollback
2. Cost Dashboard
- Costo por run (API + runners)
- Costo mensual acumulado
- Top jobs por costo
- Comparación vs budget
3. Quality Dashboard
- PRs con security findings (criticos/high)
- Test coverage trend
- Code review findings categorizados
- False positive rate del bot
4. Production Health (post-deploy)
- Error rate trend (con markers de deploys)
- Latency p95 trend
- Throughput
- Rollbacks ejecutados (count + razones)
Implementar dashboards en tu sistema de observability:
# scripts/export_pipeline_metrics.py
"""Exportar métricas del pipeline a tu sistema de monitoring."""
import os
import json
from datetime import datetime
import requests
def export_to_datadog(metrics: dict):
"""Push métricas a Datadog."""
api_key = os.environ.get("DATADOG_API_KEY")
if not api_key:
return
series = []
for name, value in metrics.items():
series.append({
"metric": f"ci.pipeline.{name}",
"points": [[int(datetime.utcnow().timestamp()), value]],
"tags": [f"workflow:{os.environ['GITHUB_WORKFLOW']}",
f"branch:{os.environ['GITHUB_REF_NAME']}"],
})
requests.post(
"https://api.datadoghq.com/api/v1/series",
headers={"DD-API-KEY": api_key, "Content-Type": "application/json"},
json={"series": series},
)
def main():
# Métricas a exportar al final del workflow
metrics = {
"duration_seconds": int(os.environ.get("WORKFLOW_DURATION", 0)),
"phase1_pass": 1 if os.environ.get("PHASE1_STATUS") == "success" else 0,
"phase2_pass": 1 if os.environ.get("PHASE2_STATUS") == "success" else 0,
"phase3_pass": 1 if os.environ.get("PHASE3_STATUS") == "success" else 0,
"rollback_executed": 1 if os.environ.get("ROLLBACK_EXECUTED") == "true" else 0,
}
export_to_datadog(metrics)
print(f"Pipeline metrics exported: {metrics}")
if __name__ == "__main__":
main()
Agregar al final del workflow:
export-metrics:
needs: [deploy-production, monitor-post-deploy, rollback, diagnose]
if: always()
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install requests
- name: Export pipeline metrics
env:
DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
ROLLBACK_EXECUTED: ${{ needs.monitor-post-deploy.outputs.rollback_needed }}
run: python scripts/export_pipeline_metrics.py
Alerting: Lo Que Despierta a la Gente
ALERTING TIERS:
TIER 1 — DESPERTAR ON-CALL (PagerDuty/SMS):
✅ Auto-rollback ejecutado
✅ Producción failure smoke tests
✅ Pipeline failure en último step antes de prod
TIER 2 — NOTIFICATION ALTA PRIORIDAD (Slack channel #alerts):
⚠️ Critical security finding bloqueó merge
⚠️ Multiple deploys fallaron (último día)
⚠️ Costos del pipeline excedieron budget mensual
TIER 3 — INFO (Slack channel #ci):
💬 Deploy exitoso a producción
💬 Pipeline summary diario
💬 New high-severity findings (no critical)
NUNCA ALERTAR:
❌ Deploy individual exitoso (no es alerta, es info)
❌ PR mergeado (es la info típica de GitHub)
❌ Comments del bot (esperados)
PagerDuty Integration
# scripts/notify_rollback.py — extender con PagerDuty
import requests
def trigger_pagerduty_incident(
summary: str,
severity: str,
details: dict,
routing_key: str,
):
"""Crear incident en PagerDuty."""
payload = {
"routing_key": routing_key,
"event_action": "trigger",
"payload": {
"summary": summary,
"source": "ci-pipeline",
"severity": severity,
"custom_details": details,
},
}
r = requests.post(
"https://events.pagerduty.com/v2/enqueue",
json=payload,
timeout=10,
)
return r.ok
Trampas Comunes en Failure Paths
1. Rollback que también falla
Síntoma: Métricas degradan, rollback se ejecuta, pero el rollback en sí falla. Producción queda mal.
Por qué pasa: El script de rollback no tiene validación post-execution.
Cómo corregir: Después del rollback, smoke tests obligatorios. Si fallan, escalar a humano (PagerDuty crítico).
2. Diagnóstico ignorado
Síntoma: Diagnose genera postmortem issue, pero nadie lo lee. Próximo incident similar pasa de nuevo.
Por qué pasa: El issue queda sin asignar.
Cómo corregir: Auto-asignar a un on-call específico. Slack notification que linkea al issue. SLA: review en 24hr.
3. Notification spam
Síntoma: Slack lleno de notifs. El equipo deja de leer. Cuando hay un alert real, se pierde.
Por qué pasa: Tier 1/2/3 mezclados en el mismo canal.
Cómo corregir: Separar canales. #alerts solo para tier 1. #ci-info para info general. PagerDuty solo para tier 1.
4. Métricas exportadas pero sin dashboards
Síntoma: Estás exportando a Datadog/Prometheus, pero nadie miró un dashboard nunca.
Por qué pasa: Construyeron exports antes de construir consumers.
Cómo corregir: Construir el dashboard primero (aunque sea vacío). Después agregar exports. Sin consumer, no hay valor en exportar.
5. No probar failure paths antes de necesitarlos
Síntoma: Primer rollback real revela bugs en el script de rollback. Bajo presión, rollback fail.
Por qué pasa: Testing solo del happy path.
Cómo corregir: Game days regulares — simular failures intencionalmente para validar que el pipeline responde correctamente. Chaos engineering aplicado al CI/CD.
Diagnóstico
Pregunta 1: ¿Tu pipeline cubre los 5 failure modes con comportamiento explícito?
Si solo tienes happy path, vas a improvisar bajo presión. Cobertura explícita = respuesta predecible.
Pregunta 2: ¿Tu rollback automático tiene smoke tests post-rollback?
Sin esto, puedes tener "rollback exitoso" según el script pero producción mal.
Pregunta 3: ¿Tienes tiers de alerting separados (PagerDuty / Slack alerts / Slack info)?
Sin tiers, el equipo se desensibiliza y los alerts importantes se pierden.
Pregunta 4: ¿Construiste dashboards de pipeline antes que exports?
Si tienes exports sin dashboards, gastas tiempo sin valor. Dashboard primero, después optimizar exports.
Pregunta 5: ¿Probaste tus failure paths intencionalmente?
Si nunca lo hiciste, el primer real falla mal. Game days = practicar bajo control.
Ejercicios
Ejercicio 1: Implementar Phase 4 (Difícil)
Implementa los 4 jobs adicionales: monitor-post-deploy, rollback, diagnose, notify-success/rollback. Verifica que:
- monitor corre 10 min después del deploy
- rollback se dispara si métricas degradan
- diagnose genera postmortem issue
- notifications llegan a Slack
Ejercicio 2: Game day simulado (Medio)
Simula un failure mode end-to-end:
- Configura un endpoint mock que retorna 500 al X% de requests
- Configura thresholds bajos en monitoring
- Mergeas un PR que activa el endpoint
- Verifica que el pipeline ejecuta rollback + diagnose correctamente
- Lee el postmortem auto-generado
Ejercicio 3: Dashboard de pipeline (Difícil)
Crea un dashboard en tu sistema de observability con:
- Pipeline duration trend
- Success rate por phase
- Costo por run (calculado de tokens + minutes)
- Rollbacks ejecutados (count + razones)
Resumen
- 5 failure modes principales: PR review, pre-deploy validation, staging deploy, approval rechazado, production post-deploy
- Cada modo con comportamiento explícito: qué pasa, qué ve el equipo, recovery path
- Phase 4 integra monitor + rollback + diagnose + notify
- 3 tiers de alerting: PagerDuty (crítico), Slack alerts (alto), Slack info (rutina)
- Dashboards primero, exports después — sin consumers no hay valor
- Game days — probar failure paths intencionalmente antes de necesitarlos
if: always()en jobs críticos como diagnose — corren incluso si jobs anteriores fallan
Próxima cápsula: 06 — Documentación, optimización y retrospectiva. Última cápsula del módulo. Conviertes el pipeline funcional en pipeline transferible: documentación operacional, optimizaciones de costos, retrospectiva con métricas. Lo que separa "funciona en mi máquina" de "production-ready".
Recursos Adicionales
- Site Reliability Engineering: Postmortem Culture — Capítulo de Google
- PagerDuty Events API — Para integration
- Datadog API — Métricas custom
- Prometheus + Grafana — Stack open-source
- Chaos Engineering Principles — Para game days
- The Site Reliability Workbook: Incident Response — Capítulo aplicable