Docs

CI/CD y Despliegue

Pipeline de integración continua con GitLab CI, gestión de secretos con Bitwarden, despliegue automático con Coolify y estrategia de branching.

PublicadoMarzo 2026Equipo de desarrollo, arquitectos, stakeholders

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.

RepositorioPipeline GitLab CIDeploy Coolify
nvito-apiquality (lint + test) + migrateAuto-deploy via webhook
nvito-adminNo tiene pipeline CIAuto-deploy via webhook
nvito-invitationsNo tiene pipeline CIAuto-deploy via webhook
nvito-pwaNo tiene pipeline CIAuto-deploy via webhook
nvito-landingNo tiene pipeline CIAuto-deploy Cloudflare Pages
nvito-docsNo tiene pipeline CIAuto-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:

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-alpine como servicio adjunto; la BD se destruye al terminar.
  • Se instala openssl en 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 BWSAmbienteMachine AccountUso
nvito-localLocallocal-devDesarrollo local via bws
nvito-devDEVgitlab-cicdPipeline GitLab CI/CD
nvito-testTESTgitlab-cicdPipeline 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
  1. Se autentica con BWS usando $BWS_ACCESS_TOKEN (única variable sensible en GitLab).
  2. Recupera todos los secretos del project indicado.
  3. Los inyecta como variables de entorno (incluyendo DATABASE_URL).
  4. Ejecuta el comando indicado con acceso a esos secretos.

4.3 Variables en GitLab vs BWS

VariableAlmacenada enProposito
BWS_ACCESS_TOKENGitLab CI/CDToken de autenticación contra BWS
BWS_PROJECT_DEVGitLab CI/CDID del project BWS para ambiente DEV
BWS_PROJECT_TESTGitLab CI/CDID del project BWS para ambiente TEST
DATABASE_URLBWSURL de conexión a la BD (por ambiente)
Demás secretsBWSAPI 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

ServicioBranchDominioPuerto
nvito-api-devdevelopdev-api.nvito.mx3000
nvito-api-testtesttest-api.nvito.mx3000
nvito-admin-devdevelopdev-admin.nvito.mx5050
nvito-admin-testtesttest-admin.nvito.mx5050
nvito-invitations-devdevelopdev.nvito.mx3001
nvito-invitations-testtesttest.nvito.mx3001
nvito-pwa-devdevelopdev-app.nvito.mx3002
nvito-pwa-testtesttest-app.nvito.mx3002

5.2 Mecanismo de Auto-Deploy

Coolify se conecta a GitLab mediante deploy keys (Coolify v4 no soporta GitLab como Source nativo):

  1. Se genera una clave SSH (gitlab-deploy-key) en Coolify Security > Private Keys.
  2. La clave pública se agrega como deploy key en cada repositorio de GitLab.
  3. Coolify expone un webhook URL por servicio; GitLab lo dispara en cada push.
  4. Coolify hace git pull, ejecuta docker build (Dockerfile multi-stage), health check, y rollout.
  5. 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:

SitioBranchDominioBuild Command
nvito-landingmainnvito.mxnpm run build
nvito-docsmaindocs.nvito.mxnpm 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

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

RamaAmbienteURL BaseBase de Datos
developDEVdev-*.nvito.mxNeon nvito-dev
testTESTtest-*.nvito.mxNeon nvito-test

Flujo: feature branch --> merge request a develop (trigger pipeline) --> merge en develop (deploy DEV) --> merge develop a test (deploy TEST).

AccióndeveloptestMerge Request
lintSiSiSi
test:unitSiSiSi
migrate:devSiNoNo
migrate:testNoSiNo
Deploy Coolify (auto-deploy)SiSiNo

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

  1. El desarrollador crea una migración localmente con npx prisma migrate dev --name <nombre>.
  2. El archivo SQL se commitea junto con los cambios de código.
  3. Al hacer push a develop, el job migrate:dev aplica la migración en Neon DEV via bws run.
  4. Al hacer merge en test, el job migrate:test aplica la misma migración en Neon TEST.
  5. El job test:unit también ejecuta prisma migrate deploy contra 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:

VariableValorProtectedMasked
BWS_ACCESS_TOKENToken del machine account gitlab-cicdSiSi
BWS_PROJECT_DEVProject ID de nvito-dev en BWSNoNo
BWS_PROJECT_TESTProject ID de nvito-test en BWSNoNo

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.

Esta pagina fue util?