Introducción
La Integración Continua detecta bugs en el momento del merge, no en producción. El costo de un test fallido en CI son unos minutos de atención de un desarrollador. El costo del mismo bug en producción es mucho mayor. GitLab CI está integrado en GitLab, no requiere ningún servicio separado y se configura completamente mediante un archivo YAML en tu repositorio.
¿Qué es la Integración Continua?
La Integración Continua es la práctica de fusionar cambios de código en una rama compartida con frecuencia, con builds y tests automatizados que se ejecutan en cada merge. El objetivo es detectar problemas de integración de forma temprana, cuando son baratos de corregir, en lugar de durante un ciclo de release cuando múltiples cambios ya se han acumulado.
Los beneficios prácticos: los bugs se detectan cerca del momento en que se introducen, por lo que el contexto sigue fresco; los fallos en los tests bloquean los merges antes de que código defectuoso llegue a la rama principal; y los equipos ganan confianza en que la rama principal siempre está en un estado deployable.
GitLab CI
GitLab CI es el servicio de CI/CD integrado en GitLab. Lee un archivo .gitlab-ci.yml en la raíz de tu repositorio y ejecuta los jobs definidos allí en cada push. No necesitas un servidor Jenkins separado ni un servicio de CI externo.
Razones para usarlo: la configuración del pipeline vive junto a tu código y evoluciona con él, los runners compartidos de GitLab gestionan el cómputo para la mayoría de los proyectos, y el estado del pipeline es visible directamente en las merge requests.
Configurando GitLab CI para un Proyecto Node.js
Requisitos Previos
- Una cuenta en GitLab.
- Un proyecto Node.js en un repositorio GitLab.
- Familiaridad básica con YAML.
Paso 1: Crear un Archivo .gitlab-ci.yml
En la raíz de tu proyecto, crea .gitlab-ci.yml:
image: node:14
stages:
- test
test_job:
stage: test
script:
- npm install
- npm test
La clave image especifica la imagen Docker en la que se ejecuta el job. La clave stages define los stages del pipeline y su orden. Cada job especifica a qué stage pertenece y qué comandos ejecutar.
Paso 2: Configurar GitLab Runner (Opcional)
Los runners compartidos de GitLab atienden a la mayoría de los proyectos sin ninguna configuración adicional. Si necesitas que los jobs se ejecuten en tu propia infraestructura, puedes instalar y registrar un GitLab Runner auto-hospedado. Para la mayoría de los proyectos Node.js, los runners compartidos son suficientes.
Paso 3: Commit y Push
git add .gitlab-ci.yml
git commit -m "Add GitLab CI configuration"
git push origin main
GitLab detecta el archivo e inicia el pipeline de inmediato.
Paso 4: Monitorear el Pipeline
Navega a CI/CD > Pipelines en tu proyecto GitLab. Puedes ver los logs de los jobs, descargar artefactos y consultar el estado del pipeline. Los jobs fallidos muestran el comando exacto que falló y su salida.
Configuración Avanzada
Caché de Dependencias
Hacer caché de node_modules evita reinstalar paquetes en cada ejecución del pipeline:
cache:
paths:
- node_modules/
test_job:
stage: test
script:
- npm install
- npm test
Múltiples Entornos
Despliega a staging automáticamente en cada merge a main:
stages:
- test
- deploy
deploy_staging:
stage: deploy
script:
- npm run build
- scp -r ./build user@staging-server:/var/www/app
only:
- main
Tests en Paralelo
Divide una suite de tests lenta entre múltiples runners:
test_job:
stage: test
script:
- npm install
- npm test
parallel: 4
Variables de Entorno
Almacena los secretos en la configuración del proyecto GitLab en Settings > CI/CD > Variables y referencíalos en tu pipeline:
script:
- npm run deploy -- --api-key=$API_KEY
Nunca pongas secretos directamente en .gitlab-ci.yml. Quedarían visibles en el historial del repositorio y para cualquier persona con acceso de lectura.
Buenas Prácticas para GitLab CI con Node.js
Fija la versión de Node.js para evitar divergencias de entorno entre ejecuciones del pipeline y el desarrollo local:
image: node:14.17.0
Agrega un paso de lint para que los problemas de formato y análisis estático fallen el pipeline antes de que se ejecuten los tests:
script:
- npm run lint
- npm test
Restringe los jobs costosos a las ramas relevantes. Ejecutar la suite de tests completa en cada commit de una feature branch generalmente no es necesario:
only:
- merge_requests
- main
Declara artefactos de build para que puedan descargarse desde la UI del pipeline o pasarse entre stages:
artifacts:
paths:
- build/
Resolución de Problemas Comunes
Si el pipeline falla en la instalación de dependencias, verifica que todos los paquetes estén declarados en package.json y que no haya conflictos de versión. El log del job muestra el error exacto.
Para errores de permisos al ejecutar scripts, agrega un paso de chmod:
script:
- chmod +x ./deploy.sh
- ./deploy.sh
Para variables de entorno faltantes, verifica que estén definidas en la configuración de variables CI/CD de GitLab y que el nombre de la variable en el YAML coincida exactamente.
Integrando Docker
Para despliegues en contenedores, usa Docker-in-Docker para construir y subir imágenes en CI:
image: docker:stable
services:
- docker:dind
variables:
DOCKER_DRIVER: overlay2
build_docker_image:
stage: build
script:
- docker build -t my-node-app .
- docker push my-node-app
only:
- main
El servicio docker:dind ejecuta un daemon Docker dentro del contenedor del pipeline, al que se conecta el script de build.
Conclusión
Un pipeline GitLab CI para un proyecto Node.js tarda menos de una hora en configurarse y mejora de inmediato el ciclo de feedback en cada merge. Los fallos de lint y de tests aparecen en minutos, en lugar de durante la revisión de código o después del despliegue. Una vez que lo básico funciona, agrega caché para acelerar las ejecuciones, restringe los jobs a las ramas donde aportan valor y extiende el pipeline con stages de despliegue conforme el proyecto madura.
Recursos Adicionales
Glosario
- Integración Continua (CI): Una práctica en la que los desarrolladores integran cambios de código con frecuencia, con builds y tests automatizados.
- GitLab Runner: La aplicación que ejecuta los jobs de CI definidos en
.gitlab-ci.yml. - Pipeline: Una colección de stages y jobs ejecutados en un orden definido en cada push.