1. Vision General del Pipeline
Nvito utiliza un modelo de CI/CD dividido en dos sistemas complementarios:
- GitLab CI/CD se encarga de la calidad del código (lint, tests) y de las migraciones de base de datos cuando hay cambios en el schema de Prisma.
- Coolify se encarga del build Docker y deploy, activado automáticamente via webhooks de GitLab al detectar un push.
GitLab CI valida que el código cumple los estandares de calidad y que las migraciones se aplican correctamente. Coolify maneja el ciclo de vida del contenedor Docker (build, health check, rollout). Ambos se disparan en paralelo por el mismo push.
| Repositorio | Pipeline GitLab CI | Deploy Coolify |
|---|---|---|
| nvito-api | quality (lint + test) + migrate | Auto-deploy via webhook |
| nvito-admin | No tiene pipeline CI | Auto-deploy via webhook |
| nvito-invitations | No tiene pipeline CI | Auto-deploy via webhook |
| nvito-pwa | No tiene pipeline CI | Auto-deploy via webhook |
| nvito-landing | No tiene pipeline CI | Auto-deploy Cloudflare Pages |
| nvito-docs | No tiene pipeline CI | Auto-deploy Cloudflare Pages |
Nota: Los frontends (nvito-admin, nvito-invitations, nvito-pwa) no tienen
.gitlab-ci.yml. Su calidad se valida localmente antes de hacer push. Los sitios estáticos (nvito-landing, nvito-docs) se despliegan automáticamente via Cloudflare Pages.
2. Pipeline GitLab CI Completo
El pipeline de nvito-api consta de dos stages secuenciales con cuatro jobs en total:
Pipeline GitLab CI — nvito-api
Stage: quality
Stage: migrate
El pipeline se ejecuta en dos condiciones: push directo a develop o test, y merge request events.
3. Stages del Pipeline
3.1 Stage: quality
Ejecuta dos jobs en paralelo: lint y test:unit.
Job lint — valida formato y estilo con ESLint y Prettier:
lint:
stage: quality
script:
- npm ci --cache $NPM_CONFIG_CACHE
- npm run lint
- npm run format:check
Job test:unit — ejecuta tests contra una BD PostgreSQL efimera:
test:unit:
stage: quality
services:
- postgres:15-alpine
variables:
POSTGRES_DB: nvito_test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
DATABASE_URL: "postgresql://test:test@postgres:5432/nvito_test"
before_script:
- apk add --no-cache openssl
script:
- npm ci --cache $NPM_CONFIG_CACHE
- npx prisma generate
- npx prisma migrate deploy
- npm run test:ci
- GitLab CI levanta
postgres:15-alpinecomo servicio adjunto; la BD se destruye al terminar. - Se instala
opensslen Alpine porque el migration engine de Prisma lo requiere. - Genera reportes de cobertura (Cobertura + JUnit) almacenados como artifacts por 30 días.
3.2 Stage: migrate
Aplica migraciones a las BD reales (Neon). Solo se ejecuta cuando hay cambios en prisma/migrations/**/*:
migrate:dev:
stage: migrate
before_script:
- apk add --no-cache curl unzip openssl
- curl -fsSL ".../bws-x86_64-unknown-linux-musl.zip" -o bws.zip
- unzip bws.zip -d /usr/local/bin && chmod +x /usr/local/bin/bws
script:
- npm ci --cache $NPM_CONFIG_CACHE
- npx prisma generate
- bws run --project-id $BWS_PROJECT_DEV -- npx prisma migrate deploy
rules:
- if: $CI_COMMIT_BRANCH == "develop"
changes:
- prisma/migrations/**/*
migrate:test es identico pero se ejecuta en la rama test usando $BWS_PROJECT_TEST. Si un push no modifica el schema, este stage se omite completamente.
4. Gestión de Secretos con Bitwarden Secrets Manager
Nvito utiliza Bitwarden Secrets Manager (BWS) como vault centralizado. Ningun secreto sensible se almacena directamente como variable de GitLab CI/CD.
4.1 Organización de Projects y Machine Accounts
| Project BWS | Ambiente | Machine Account | Uso |
|---|---|---|---|
nvito-local | Local | local-dev | Desarrollo local via bws |
nvito-dev | DEV | gitlab-cicd | Pipeline GitLab CI/CD |
nvito-test | TEST | gitlab-cicd | Pipeline GitLab CI/CD |
4.2 Inyección de Secretos en el Pipeline
El comando bws run inyecta los secretos del project BWS como variables de entorno en el proceso hijo:
bws run --project-id $BWS_PROJECT_DEV -- npx prisma migrate deploy
- Se autentica con BWS usando
$BWS_ACCESS_TOKEN(única variable sensible en GitLab). - Recupera todos los secretos del project indicado.
- Los inyecta como variables de entorno (incluyendo
DATABASE_URL). - Ejecuta el comando indicado con acceso a esos secretos.
4.3 Variables en GitLab vs BWS
| Variable | Almacenada en | Proposito |
|---|---|---|
BWS_ACCESS_TOKEN | GitLab CI/CD | Token de autenticación contra BWS |
BWS_PROJECT_DEV | GitLab CI/CD | ID del project BWS para ambiente DEV |
BWS_PROJECT_TEST | GitLab CI/CD | ID del project BWS para ambiente TEST |
DATABASE_URL | BWS | URL de conexión a la BD (por ambiente) |
| Demás secrets | BWS | API keys, tokens de servicios, etc. |
5. Despliegue con Coolify
Coolify gestióna el ciclo de vida de los contenedores Docker en un VPS Contabo (Cloud VPS 10 — 4 vCPU, 8 GB RAM) con Traefik como reverse proxy integrado.
5.1 Servicios Desplegados
| Servicio | Branch | Dominio | Puerto |
|---|---|---|---|
| nvito-api-dev | develop | dev-api.nvito.mx | 3000 |
| nvito-api-test | test | test-api.nvito.mx | 3000 |
| nvito-admin-dev | develop | dev-admin.nvito.mx | 5050 |
| nvito-admin-test | test | test-admin.nvito.mx | 5050 |
| nvito-invitations-dev | develop | dev.nvito.mx | 3001 |
| nvito-invitations-test | test | test.nvito.mx | 3001 |
| nvito-pwa-dev | develop | dev-app.nvito.mx | 3002 |
| nvito-pwa-test | test | test-app.nvito.mx | 3002 |
5.2 Mecanismo de Auto-Deploy
Coolify se conecta a GitLab mediante deploy keys (Coolify v4 no soporta GitLab como Source nativo):
- Se genera una clave SSH (
gitlab-deploy-key) en Coolify Security > Private Keys. - La clave pública se agrega como deploy key en cada repositorio de GitLab.
- Coolify expone un webhook URL por servicio; GitLab lo dispara en cada push.
- Coolify hace
git pull, ejecutadocker build(Dockerfile multi-stage), health check, y rollout. - Traefik actualiza el routing automáticamente con SSL via Let's Encrypt.
Las variables de entorno de cada servicio se configuran directamente en el dashboard de Coolify (no via BWS).
Importante: Las variables
NEXT_PUBLIC_*se inyectan en build time. Si se modifican, es necesario hacer un redeploy para que tomen efecto.
5.3 Sitios Estaticos en Cloudflare Pages
Los sitios que no requieren backend (nvito-landing y nvito-docs) se despliegan directamente en Cloudflare Pages, sin pasar por Coolify:
| Sitio | Branch | Dominio | Build Command |
|---|---|---|---|
| nvito-landing | main | nvito.mx | npm run build |
| nvito-docs | main | docs.nvito.mx | npm run build |
El deploy es automático al hacer push a main. Cloudflare detecta el framework (Astro/Next.js), ejecuta el build y pública el output estático con CDN global.
6. Flujo de Deploy Completo
Flujo de Deploy Completo
El pipeline CI/CD y el deploy de Coolify se ejecutan en paralelo. Las migraciones suelen completarse antes que el build Docker, así que para cuando el nuevo contenedor inicia, la BD ya tiene el schema actualizado. Si una migración falla, el desarrollador debe monitorear ambos procesos ya que Coolify no depende del resultado del pipeline.
7. Estrategia de Branching
| Rama | Ambiente | URL Base | Base de Datos |
|---|---|---|---|
develop | DEV | dev-*.nvito.mx | Neon nvito-dev |
test | TEST | test-*.nvito.mx | Neon nvito-test |
Flujo: feature branch --> merge request a develop (trigger pipeline) --> merge en develop (deploy DEV) --> merge develop a test (deploy TEST).
| Acción | develop | test | Merge Request |
|---|---|---|---|
| lint | Si | Si | Si |
| test:unit | Si | Si | Si |
| migrate:dev | Si | No | No |
| migrate:test | No | Si | No |
| Deploy Coolify (auto-deploy) | Si | Si | No |
8. Migraciones de Base de Datos
8.1 Cuando se Ejecutan
Solo cuando se cumplen ambas condiciones: push a develop o test, y cambios en prisma/migrations/**/*.
8.2 prisma migrate deploy vs prisma migrate dev
prisma migrate deploy es el comando seguro para CI/CD:
- Solo aplica migraciones existentes que aun no se han ejecutado.
- No modifica archivos del proyecto ni requiere input interactivo.
- Es idempotente: si no hay migraciones pendientes, no hace nada.
8.3 Flujo de Migración
- El desarrollador crea una migración localmente con
npx prisma migrate dev --name <nombre>. - El archivo SQL se commitea junto con los cambios de código.
- Al hacer push a
develop, el jobmigrate:devaplica la migración en Neon DEV viabws run. - Al hacer merge en
test, el jobmigrate:testaplica la misma migración en Neon TEST. - El job
test:unittambién ejecutaprisma migrate deploycontra la BD efimera de PostgreSQL, garantizando que los tests corran contra un schema actualizado.
9. Variables de CI/CD en GitLab
Configurar en GitLab > Settings > CI/CD > Variables para el repositorio nvito-api:
| Variable | Valor | Protected | Masked |
|---|---|---|---|
BWS_ACCESS_TOKEN | Token del machine account gitlab-cicd | Si | Si |
BWS_PROJECT_DEV | Project ID de nvito-dev en BWS | No | No |
BWS_PROJECT_TEST | Project ID de nvito-test en BWS | No | No |
Principio de seguridad: Los secretos sensibles (DATABASE_URL, API keys) nunca se almacenan como variables de GitLab. Solo el token de acceso a BWS y los IDs de proyecto se configuran ahi. El resto se inyecta en runtime via
bws run.
10. Troubleshooting
10.1 OpenSSL en Alpine
Problema: Error: Could not parse schema engine response en jobs que ejecutan Prisma.
Solución: Agregar apk add --no-cache openssl en el before_script.
10.2 Lint falla por formato Prettier
Solución: Ejecutar npm run format && npm run lint:fix && npm run lint localmente antes de hacer push.
10.3 Migración no se ejecuta
Causa: La directiva changes no detecto cambios en prisma/migrations/. Verificar que los archivos estan commiteados y el push es a la rama correcta.
10.4 Deploy de Coolify falla
Revisar logs en el dashboard de Coolify. Causas comunes: variables NEXT_PUBLIC_* faltantes (se requieren en build time), devDependencies omitidas por NODE_ENV=production, permisos de directorios en el contenedor.