Runbook: Deploy de Staging — de cero a andando
Date: 2026-07-25 Status: 🔴 Nada de esto está creado todavía (ni Firebase ni AWS) — es la guía completa, en orden
URLs correctas (reemplazan cualquier placeholder anterior mal definido)
| Sitio | URL |
|---|---|
| App (frontend) | https://soterex.stag.cislatam.net |
| API (backend) | https://api.soterex.stag.cislatam.net |
| Documentación funcional (VitePress) | https://docs.soterex.stag.cislatam.net |
| Referencia de API (ReDoc) | https://docs.api.soterex.stag.cislatam.net |
Patrón: {servicio}.soterex.stag.cislatam.net — el stag va después de soterex, no antes de cislatam. Para producción, mismo patrón sin el segmento stag (a confirmar cuando llegue el momento: soterex.cislatam.net, api.soterex.cislatam.net, etc.).
Qué ya se corrigió en el código (este mismo paquete)
- [x]
doc/.vitepress/config.mts— el link "Referencia de API" ahora sale de una variable de entorno de build (DOCS_API_URL), no está hardcodeado. - [x]
firebase.json(raíz, nuevo) — coordina los 3 sitios estáticos (app,docs,docs-api) como "hosting targets" de un mismo proyecto Firebase, en vez de configs sueltas sin coordinar. - [x]
.firebaserc(raíz, nuevo) — mapea los targets a los Site IDs reales de Firebase Hosting (placeholders — completar en el paso 2). - [x]
infra/terraform/environments/staging/terraform.tfvars.example—cors_allowed_originscorregido ahttps://soterex.stag.cislatam.net. - [x]
.github/workflows/deploy-staging.yml— se agregaron los jobsdeploy-docsydeploy-docs-api(antes no se deployaba ninguna de las 2 webs de documentación, solo la app y el backend).
Paso 1 — Crear el proyecto de Firebase (si no existe)
firebase login
firebase projects:create soterex-staging --display-name "Soterex — Staging"(o usar la consola de Firebase si preferís — mismo resultado)
Anotar el Project ID real que Firebase asigna — reemplaza REEMPLAZAR-PROJECT-ID-STAGING en .firebaserc.
Paso 2 — Crear los 3 Hosting Sites dentro de ese proyecto
Un proyecto de Firebase puede tener varios "sites" de Hosting — necesitamos 3:
firebase hosting:sites:create soterex-stag-app --project soterex-staging
firebase hosting:sites:create soterex-stag-docs --project soterex-staging
firebase hosting:sites:create soterex-stag-docs-api --project soterex-stagingActualizar .firebaserc con el Project ID real (reemplazando el placeholder) — los nombres de sites (soterex-stag-app, etc.) ya coinciden con lo que dejé preparado.
Paso 3 — Habilitar Firebase Authentication (Email/Password)
En la consola de Firebase → Authentication → Sign-in method → habilitar Email/Password. Crear al menos 1 usuario real de prueba (o coordinarlo con el DevUserSeeder del backend, si corre contra este mismo proyecto de Firebase).
Del proyecto, sacar los 6 valores de config (Configuración del proyecto → General → tus apps → Web app → SDK config): apiKey, authDomain, projectId, storageBucket, messagingSenderId, appId — van a los GitHub Secrets del Paso 7.
Paso 4 — Conectar los dominios custom en Firebase Hosting
Para cada uno de los 3 sites, en la consola de Firebase → Hosting → ese site → Agregar dominio personalizado:
soterex-stag-app→soterex.stag.cislatam.netsoterex-stag-docs→docs.soterex.stag.cislatam.netsoterex-stag-docs-api→docs.api.soterex.stag.cislatam.net
Firebase te va a dar registros DNS específicos para cada uno (normalmente un registro TXT para verificar propiedad, y después un A/CNAME) — pasarle esos registros a quien administre el DNS de cislatam.net para que los cargue. Firebase valida solo apenas detecta el DNS propagado (puede tardar unos minutos a unas horas).
Paso 5 — Certificado ACM para el backend (api.soterex.stag.cislatam.net)
El backend no va a Firebase — va a AWS (ALB), y necesita su propio certificado TLS:
aws acm request-certificate \
--domain-name api.soterex.stag.cislatam.net \
--validation-method DNS \
--region us-east-1Esto devuelve un CertificateArn y los detalles del registro CNAME que hay que agregar al DNS para validarlo (aws acm describe-certificate --certificate-arn <arn> para verlos). Pasarle ese CNAME también a quien administre el DNS. El certificado queda en estado PENDING_VALIDATION hasta que el DNS se propague — recién ahí se puede usar en Terraform.
Paso 6 — Terraform: bootstrap (si no se hizo nunca) + Staging
cd infra/terraform/bootstrap
terraform init && terraform apply # una sola vez por cuenta de AWS, si no se hizo ya
cd ../environments/staging
cp terraform.tfvars.example terraform.tfvars
# completar terraform.tfvars con el ARN real del certificado del Paso 5
terraform init
terraform plan # revisar antes de aplicar
terraform applyAl final, terraform output te da: alb_dns_name, el nombre del cluster ECS, los repos ECR, etc. — el alb_dns_name es lo que necesita quien administre el DNS para apuntar api.soterex.stag.cislatam.net ahí (un CNAME al DNS name del ALB, o un registro ALIAS si el DNS de cislatam.net está en Route53).
Paso 7 — Cargar los GitHub Secrets
Lista completa (Settings → Secrets and variables → Actions, en el repo):
Generales / AWS:AWS_REGION, AWS_TERRAFORM_APPLY_ROLE_ARN, AWS_STAGING_DEPLOY_ROLE_ARN, INFRA_ALERT_EMAIL
Firebase (Staging):STAGING_FIREBASE_API_KEY, STAGING_FIREBASE_AUTH_DOMAIN, STAGING_FIREBASE_PROJECT_ID, STAGING_FIREBASE_STORAGE_BUCKET, STAGING_FIREBASE_MESSAGING_SENDER_ID, STAGING_FIREBASE_APP_ID, STAGING_FIREBASE_SERVICE_ACCOUNT (JSON de la service account — Firebase Console → Configuración del proyecto → Cuentas de servicio → Generar nueva clave)
URLs (Staging) — usar las de la tabla de arriba:STAGING_API_BASE_URL = https://api.soterex.stag.cislatam.netSTAGING_DOCS_URL = https://docs.soterex.stag.cislatam.netSTAGING_DOCS_API_URL = https://docs.api.soterex.stag.cislatam.net
Infra (Staging, salen de terraform output del Paso 6):STAGING_ACM_CERTIFICATE_ARN, STAGING_ECR_REPOSITORY, STAGING_ECS_CLUSTER, STAGING_ECS_WEB_SERVICE, STAGING_ECS_WEB_TASK_FAMILY, STAGING_ECS_QUEUE_SERVICE, STAGING_ECS_QUEUE_TASK_FAMILY, STAGING_PRIVATE_SUBNET_IDS, STAGING_ECS_SECURITY_GROUP_ID
Paso 8 — Cargar los secrets del backend real en AWS Secrets Manager
Las credenciales que el backend necesita en runtime (Firebase Admin SDK, credenciales de Soterex — todavía en modo MOCK) se cargan directo en Secrets Manager, no pasan por GitHub:
aws secretsmanager put-secret-value \
--secret-id soterex-staging-firebase-credentials \
--secret-string file://firebase-service-account-staging.json
# Soterex sigue en MOCK — no hace falta cargar credenciales reales todavía
# (ver ADR y Configuración → Soterex Settings, editable desde Admin).(Los nombres exactos de los secrets salen de terraform output del módulo secrets — confirmar ahí antes de correr esto.)
Paso 9 — Primer deploy
git checkout staging
git merge main
git push origin stagingEsto dispara deploy-staging.yml — los 4 jobs (deploy-frontend, deploy-docs, deploy-docs-api, deploy-backend) corren en paralelo. Revisar la pestaña Actions de GitHub.
Paso 10 — Verificación post-deploy
- [ ]
https://soterex.stag.cislatam.netcarga el login real. - [ ]
https://api.soterex.stag.cislatam.net/api/health(o el endpoint de health check que exista) responde 200. - [ ]
https://docs.soterex.stag.cislatam.netcarga el sitio VitePress, y el link "Referencia de API ↗" del nav apunta ahttps://docs.api.soterex.stag.cislatam.net(no a un placeholder). - [ ]
https://docs.api.soterex.stag.cislatam.netcarga el portal ReDoc con login. - [ ] Login real contra el usuario de prueba creado en el Paso 3, y navegación básica de la app.
Orden resumido (para no perderse)
Firebase: crear proyecto → crear 3 sites → habilitar Auth → agregar dominios custom (Paso 1-4)
↓ (en paralelo)
AWS: solicitar cert ACM → validar DNS (Paso 5)
↓
AWS: terraform bootstrap + staging apply, usando el cert ya validado (Paso 6)
↓
DNS: cargar todos los registros que fueron saliendo (Firebase x3 + ACM + ALB) — un solo pase
↓
GitHub: cargar todos los secrets (Paso 7) + Secrets Manager (Paso 8)
↓
git push origin staging → primer deploy automático (Paso 9) → verificar (Paso 10)
