diff --git a/README.md b/README.md index da02e9d..b5298c0 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ Consulta .env.example para un listado comentado con valores de ejemplo. - Volumen persistente: mapea /app/data a un volumen (persistencia de SQLite). - Red interna con Evolution API (ideal: no exponer públicamente el webhook). - El worker de la cola arranca con el servidor (en NODE_ENV=test se desactiva). +- Plan operativo mínimo (CI/CD, healthcheck y backups): ver docs/CI-CD-PLAN.md (decisiones pendientes marcadas). ## Seguridad y buenas prácticas - Mantén WEBHOOK_URL accesible desde Evolution API preferiblemente en red interna; si se expone, restringe IPs o usa reverse proxy/firewall. diff --git a/STATUS.md b/STATUS.md index 3654c5f..0329c88 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,6 +1,7 @@ # Estado del Proyecto — Task Manager para WhatsApp Estado general: listo para piloto con la junta directiva; 170 tests pasando. Riesgos operativos principales: CI/CD básico, red interna entre Evolution API y el bot, y backups/persistencia. +Siguiente paso de desarrollo: ejecutar el plan mínimo de CI/CD, healthcheck y backups descrito en docs/CI-CD-PLAN.md (pendiente de cerrar las decisiones marcadas). ## Hecho (por áreas) - Servidor webhook diff --git a/docs/CI-CD-PLAN.md b/docs/CI-CD-PLAN.md new file mode 100644 index 0000000..28a16f2 --- /dev/null +++ b/docs/CI-CD-PLAN.md @@ -0,0 +1,121 @@ +# Plan mínimo de CI/CD, healthcheck y backups (pendiente de decisiones) + +Este documento describe un plan pragmático y de bajo mantenimiento para asegurar despliegues seguros y copias de seguridad consistentes, sin introducir infra innecesaria. No aplicar todavía: sirve como guía de implementación para la siguiente iteración. + +## Contexto actual (resumen) +- Despliegue: push a main en Forgejo → webhook a CapRover → build/deploy con Dockerfile. +- Imagen: basada en oven/bun con utilidades de depuración (curl, netcat, sqlite3). Útil para inspección. +- Healthcheck en Dockerfile “permisivo”: permite éxito aunque /health falle (usa `|| exit 0`). +- Script de arranque con `sleep 10` (resto histórico). +- No hay guardarraíl que bloquee despliegue si fallan tests. + +## Objetivos +1) Evitar desplegar una versión rota a producción (guardarraíl mínimo). +2) Mejorar detección temprana de fallos (healthcheck real). +3) Asegurar backups diarios consistentes sin parar el servicio y con verificación de integridad. +4) Mantener la simplicidad operativa. + +## Decisiones pendientes (elegir antes de implementar) +- [ ] Disparo de despliegue (elige 1): + - [ ] A) Desplegar solo con tags (vX.Y.Z). Flujo: tests locales → tag → push → CapRover deploy. + - [ ] B) Hook server-side en Forgejo (pre-receive/update) que corre `bun test` y rechaza el push si falla. + - [ ] C) “Webhook gate” mínimo: un endpoint propio que ejecuta tests y reenvía a CapRover solo si pasan. +- [ ] Herramientas en imagen: + - [x] Mantener sqlite3 por ahora (útil en prod). + - [ ] Retirar curl y netcat tras piloto (no crítico). +- [ ] Monitor externo muy ligero: + - [ ] Usar Uptime-Kuma (o similar) para /health cada 1 min. + - [ ] No usar monitor externo (conformarse con CapRover). +- [ ] Almacenamiento de backups: + - [ ] Mismo disco (operacional; conservar varias generaciones). + - [ ] Segundo disco/NAS/otro servidor (preferible si posible). +- [ ] “Smoke” post-deploy: + - [ ] Enviar DM a BOT_OWNER (si configurado) de “deploy OK”. + - [ ] Solo registrar métrica (`app_started_at` y `migrations_ok`). + +## Cambios planificados (sin aplicar todavía) + +### 1) Arranque y healthcheck +- startup.sh: eliminar `sleep 10` y arrancar directamente `bun run index.ts`. +- Dockerfile: endurecer HEALTHCHECK para que falle si /health no responde 200 (eliminar `|| exit 0`). Mantener endpoint básico (sin `full=1`). +- EXPOSE: mantener lectura de PORT por env; sin cambios funcionales. + +### 2) Guardarraíl de despliegue (elige 1 opción) +- Opción A — Deploy por tags: + - Convención de versiones semánticas (vX.Y.Z). + - Procedimiento: correr `bun test` local → crear tag → push tag → CapRover deploy. + - Pros: cero infra extra; fácil de revertir en hábitos. +- Opción B — Hook server-side en Forgejo: + - Añadir hook `pre-receive` (o `update`) que: + - Chequea que el push es a `refs/heads/main`. + - Ejecuta `bun test` en un checkout temporal del commit/refs recibido. + - Si falla, exit ≠ 0 y Forgejo rechaza el push. + - Pros: no requiere runners ni servicios; bloquea pushes rotos. +- Opción C — Webhook gate mínimo: + - Service pequeño (script) que recibe el webhook de Forgejo, ejecuta `bun test` y solo si pasa reenvía el webhook a CapRover. + - Pros: aísla validación del despliegue; Contras: un servicio más que mantener. + +### 3) Imagen Docker +- Mantener sqlite3 para inspección en producción. +- Plan (post‑piloto): retirar curl/netcat si no se usan. +- Añadir `.dockerignore` para reducir contexto (node_modules, tests si no son necesarios en build, etc.) — opcional a corto plazo. + +### 4) Backups de SQLite (prioridad alta) +- Método recomendado: backup “online” con sqlite3 (sin detener el servicio). +- Procedimiento diario (cron en host o contenedor programador): + 1) Ruta base: `/app/data/tasks.db`. + 2) Crear directorio de backups: `/app/data/backups/`. + 3) Generar nombre con timestamp: `tasks-YYYYMMDD-HHmm.sqlite3`. + 4) Ejecutar backup online: + - `sqlite3 /app/data/tasks.db ".backup '/app/data/backups/tasks-YYYYMMDD-HHmm.sqlite3'"`. + - Alternativa: `VACUUM INTO` a un archivo temporal y luego renombrar. + 5) Verificar integridad en la copia: + - `sqlite3 /app/data/backups/tasks-... "PRAGMA integrity_check;"` debe devolver `ok`. + - Registrar resultado en un log de backups (`/app/data/backups/backup.log`). + 6) Comprimir (opcional): `gzip -9`. + 7) Retención: mantener p. ej. 7 diarias + 4 semanales; purgar el resto. +- Notas: + - Con WAL activado, `.backup` maneja consistencia; evita copiar a pelo sin incluir `-wal/-shm`. + - Si se dispone de otro disco/servidor, replicar las copias (scp/rsync) al menos semanalmente. +- Ensayo mensual de restauración: + - En un contenedor aislado: montar una copia del backup como `tasks.db` y arrancar la app; comprobar `/health` y que migraciones aplican. + +### 5) Detección temprana de fallos +- Healthcheck real (Dockerfile): CapRover marcará “unhealthy” si /health no está OK. +- Smoke post‑deploy: + - Si se elige DM: encolar un mensaje “deploy OK” a BOT_OWNER tras el arranque (idempotente). + - Alternativa sin DM: exponer métricas `app_started_at` (epoch ms) y `migrations_ok` (0/1). + +### 6) Runbook operativo (resumen) +- Desplegar: + - Opción A (tags): `bun test` local → `git tag vX.Y.Z` → `git push --tags`. + - Opción B/C: `git push` a main (tests bloquean si fallan). +- Verificación: + - CapRover: health verde. + - `/health` OK; `/metrics` visible. + - Logs sin errores de migraciones/cola. +- Rollback: + - CapRover: revertir a la versión previa (history). +- Backup manual (ad hoc): + - Ejecutar el mismo comando `.backup` y verificar integridad. +- Restore: + - Parar app (si procede), sustituir `data/tasks.db` por la copia, arrancar, verificar `/health`. + +## Checklist de implementación +- [ ] Decidir estrategia de trigger de despliegue (A/B/C). +- [ ] Endurecer HEALTHCHECK en Dockerfile (sin `|| exit 0`). +- [ ] Eliminar `sleep` en startup.sh. +- [ ] (Opcional) Añadir `.dockerignore`. +- [ ] Implementar guardarraíl elegido: + - [ ] A) Convención de tags y documentación de flujo. + - [ ] B) Hook en Forgejo con `bun test`. + - [ ] C) Webhook gate que ejecuta tests y reenvía a CapRover. +- [ ] Programar backup diario con verificación de integridad y retención. +- [ ] Documentar y ensayar restore. +- [ ] (Opcional) Monitor externo para `/health`. +- [ ] (Opcional) Smoke post‑deploy (DM o métricas). + +## Impacto esperado +- Riesgo de “romper prod” se reduce significativamente con coste operativo mínimo. +- Backups confiables y verificables sin actividad manual diaria. +- Cambios reversibles y sin bloqueo del desarrollo.