Ir al contenido

Despliegue

Ventana de terminal
bunx --bun drizzle-kit generate # genera SQL
bunx --bun drizzle-kit migrate # aplica

Siempre tras migrate (o push en dev), aplicar los triggers:

Ventana de terminal
psql "$DATABASE_URL" -f src/db/triggers.sql

Sin este paso faltan los triggers de integridad cross-evento y de inmutabilidad de la bitácora: la app corre pero sus garantías no.

Ventana de terminal
bun install --production
bun src/index.ts # escucha en :5000 (o $PORT)

En producción:

  • CORREO_PROVEEDOR=smtp con credenciales reales.
  • Los cuatro secretos llenos (BOLETO_HMAC_SECRET fall-fast sin él).
  • TRUST_PROXY=true detrás de proxy/LB.
  • CRON_ENABLED=true en una sola réplica; false en el resto.
  • CORS_ORIGIN con los orígenes del front.

El manual se compila con Astro/Starlight a docs/dist y lo sirve la misma API en la raíz:

Ventana de terminal
cd docs
bun install
bun run build # genera docs/dist
URL Contenido
/ Este manual (si docs/dist existe)
/openapi Referencia de endpoints (Scalar)
/health Salud: proceso + base de datos
/llms.txt Versiones del manual para LLMs; ver llms.txt para LLMs

Si docs/dist no existe, la API responde 404 en / y todo lo demás funciona igual (las rutas de la API tienen prioridad sobre el estático).

El build hornea la URL pública del sitio (site en docs/astro.config.mjs): en producción debe coincidir con APP_URL, o las URLs absolutas del llms.txt y del sitemap apuntarán a otro host.

Para desarrollar el sitio con recarga:

Ventana de terminal
cd docs && bun run dev # http://localhost:4321
Ventana de terminal
curl -s localhost:5000/health # {"status":"ok",...}
curl -s localhost:5000/openapi/json | head -c 100 # especificación
curl -sI localhost:5000/ # 200 si docs construidas

Checklist de release (local, antes de subir):

Ventana de terminal
bunx tsc --noEmit --moduleResolution bundler --module ES2022 --target ES2021 --strict --skipLibCheck --types bun-types
bunx biome lint ./src
bun test --preload ./test/setup.ts
bunx drizzle-kit check
  • Logs: arranque (cron programados), warnings [seguridad] si falta algún secreto, y [cron] <job> ok en cada corrida.
  • Bitácora: GET /auditoria/ + POST /auditoria/verificar periódico (ver Auditoría).
  • Cola de correos: vigila GET /notificaciones/?estado=fallido.

dev despliega al VPS de pruebas; master, a producción:

  • ci.yml corre en ambas ramas: tipos, lint, schema, e2e con Postgres de CI y arranque sin DB.
  • deploy-staging.yml tras CI verde en dev: por SSH hace git pull de dev → drizzle-kit migrate (o push si aún no hay .sql) → psql -f src/db/triggers.sql → docker compose -f compose.staging.yml up -d --build → verifica GET /health.
  • deploy-prod.yml es manual hasta que exista el servidor (mismo flujo con .env.prod y compose.prod.yml: puerto solo en loopback, el TLS lo da el reverse proxy del host, con TRUST_PROXY=true).

Detalles:

  • Solo la API va en Docker; Postgres corre bare-metal en cada host y el contenedor lo alcanza vía host.docker.internal:5432 (ver compose.*.yml). Los pasos de migrate/triggers corren en el host con esa URL traducida a localhost.
  • Los .env.staging / .env.prod viven en /opt/pisa-api de cada servidor (nunca en git); en GitHub solo hay secrets de infra: VPS_STAGING_* y VPS_PROD_* (HOST, USER, SSH_KEY, PORT).
  • Disparo manual: Actions → Deploy staging/prod → Run workflow.
  • drizzle/ está versionado: commitea cada migración generada para que CI y los deploys apliquen el mismo SQL.

→ Tests