TL;DR — Resumen Rápido

GitLab CI/CD automatiza build, test y despliegue con .gitlab-ci.yml. Domina etapas, runners, artefactos y estrategias de despliegue en producción.

GitLab CI/CD es una plataforma de integración y entrega continua integrada directamente en GitLab. A diferencia de las herramientas de CI externas que requieren configuración separada y webhooks, GitLab CI/CD lee un único archivo .gitlab-ci.yml de tu repositorio y ejecuta los pipelines automáticamente en cada push. Esta integración estrecha significa que tu código, issues, merge requests y pipelines de despliegue viven todos en un mismo lugar.

Esta guía recorre la configuración de pipelines desde cero: etapas, trabajos, runners, caché, artefactos, variables, entornos y estrategias de despliegue que funcionan en producción real.

Requisitos Previos

  • Una cuenta de GitLab (gitlab.com o instancia propia)
  • Un repositorio Git alojado en GitLab
  • Conocimientos básicos de sintaxis YAML
  • Docker instalado (para runners con executor Docker)
  • Familiaridad con conceptos de CI/CD (build, test, deploy)

Estructura de un Pipeline de GitLab CI/CD

Un pipeline se compone de etapas que se ejecutan en secuencia y trabajos dentro de cada etapa que corren en paralelo. Esta es la estructura fundamental:

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

build-app:
  stage: build
  image: node:20
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 hour

unit-tests:
  stage: test
  image: node:20
  script:
    - npm ci
    - npm run test:unit
  coverage: '/Lines\s+:\s+(\d+\.?\d*)%/'

integration-tests:
  stage: test
  image: node:20
  services:
    - postgres:15
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: runner
    POSTGRES_PASSWORD: testing
    DATABASE_URL: "postgresql://runner:testing@postgres:5432/test_db"
  script:
    - npm ci
    - npm run test:integration

deploy-staging:
  stage: deploy
  script:
    - ./scripts/deploy.sh staging
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"

La etapa build se ejecuta primero. Cuando termina con éxito, ambos trabajos de test corren en paralelo (están en la misma etapa). Solo si todos los tests pasan continúa el despliegue.

Configuración de GitLab Runners

Los runners ejecutan los trabajos del pipeline. Tienes dos opciones:

Runners Compartidos (Inicio Rápido)

GitLab.com ofrece runners compartidos de forma gratuita. Están disponibles de inmediato, sin configuración adicional. Ve a Settings → CI/CD → Runners para verificar que están habilitados.

Runners Propios (Producción)

Para mayor rendimiento y control, instala tu propio runner:

# Instalar GitLab Runner en Ubuntu
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner

# Registrar el runner
sudo gitlab-runner register \
  --url "https://gitlab.com/" \
  --registration-token "YOUR_TOKEN" \
  --executor "docker" \
  --docker-image "alpine:latest" \
  --description "production-runner" \
  --tag-list "docker,linux" \
  --run-untagged="true"

Comparativa de Executors

Executor Aislamiento Velocidad Caso de Uso
Docker Alto (contenedor por trabajo) Rápido Opción predeterminada para la mayoría
Shell Ninguno (corre en el host) Más rápido Scripts simples, apps legadas
Docker Machine Alto + autoescalado Variable Runners con autoescalado en la nube
Kubernetes Alto (pod por trabajo) Medio Despliegues nativos en Kubernetes
VirtualBox VM completa Lento Cuando se necesita aislamiento total de SO

Configuración Avanzada de Pipelines

Caché de Dependencias

El caché evita descargar dependencias en cada ejecución del pipeline:

variables:
  NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm"

cache:
  key:
    files:
      - package-lock.json
  paths:
    - .npm/
    - node_modules/
  policy: pull-push

La directiva key.files genera una clave de caché a partir de package-lock.json. Cuando cambian las dependencias, el caché se invalida automáticamente.

Artefactos Entre Etapas

Pasa los resultados de compilación de una etapa a la siguiente:

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
      - coverage/
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
    expire_in: 1 week

Reglas del Pipeline y Ejecución Condicional

Controla cuándo se ejecutan los trabajos con rules:

deploy-production:
  stage: deploy
  script:
    - ./deploy.sh production
  environment:
    name: production
    url: https://example.com
  rules:
    - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
      when: manual
    - when: never

Este trabajo solo aparece en tags de versión (v1.2.3) y requiere aprobación manual.

Trabajos en Matriz Paralela

Prueba en múltiples versiones simultáneamente:

test:
  stage: test
  image: node:${NODE_VERSION}
  parallel:
    matrix:
      - NODE_VERSION: ["18", "20", "22"]
        DATABASE: ["postgres", "mysql"]
  script:
    - npm ci
    - npm run test

Esto crea 6 trabajos en paralelo (3 versiones de Node × 2 bases de datos).

Variables de CI/CD y Secretos

Almacena valores sensibles de forma segura:

deploy:
  stage: deploy
  script:
    - echo "$DEPLOY_KEY" > key.pem
    - chmod 600 key.pem
    - scp -i key.pem dist/* user@server:/var/www/
  after_script:
    - rm -f key.pem

Escenario real: Tu equipo despliega una aplicación Node.js en tres entornos: desarrollo, staging y producción. Cada entorno tiene distintas credenciales de base de datos, API keys y direcciones de servidor. Almacenas estos valores como variables de GitLab CI/CD con alcance por entorno. El mismo YAML del pipeline gestiona todos los despliegues; solo cambian las variables. Cuando un desarrollador hace push a develop, el pipeline despliega automáticamente en staging. El despliegue a producción se activa únicamente con tags y requiere aprobación manual del líder técnico.

Tipos y Alcance de Variables

Alcance Configurado En Disponible Para
Project Settings → CI/CD → Variables Todos los pipelines del proyecto
Group Group → Settings → CI/CD Todos los proyectos del grupo
Instance Admin → CI/CD → Variables Todos los proyectos de la instancia
Environment Settings → CI/CD → Variables (filtro de entorno) Trabajos que apuntan a ese entorno
Job variables: en .gitlab-ci.yml Solo ese trabajo específico

Marca las variables como Protected (disponibles solo en ramas/tags protegidas) y Masked (ocultas en los logs) para las credenciales.

Entornos de Despliegue y Estrategias

Review Apps (Entornos Dinámicos)

Crea un entorno temporal para cada merge request:

review:
  stage: deploy
  script:
    - deploy_review_app "$CI_MERGE_REQUEST_IID"
  environment:
    name: review/$CI_MERGE_REQUEST_IID
    url: https://$CI_MERGE_REQUEST_IID.review.example.com
    on_stop: stop-review
  rules:
    - if: $CI_MERGE_REQUEST_IID

stop-review:
  stage: deploy
  script:
    - teardown_review_app "$CI_MERGE_REQUEST_IID"
  environment:
    name: review/$CI_MERGE_REQUEST_IID
    action: stop
  rules:
    - if: $CI_MERGE_REQUEST_IID
      when: manual

Despliegue a Producción con Rollback

deploy-production:
  stage: deploy
  script:
    - ./deploy.sh production
  environment:
    name: production
    url: https://example.com
    auto_stop_in: never
  rules:
    - if: $CI_COMMIT_TAG
      when: manual
  allow_failure: false

GitLab CI/CD vs Otras Plataformas de CI

Característica GitLab CI/CD GitHub Actions Jenkins CircleCI
Archivo de Config .gitlab-ci.yml .github/workflows/*.yml Jenkinsfile .circleci/config.yml
Registro Integrado Sí (contenedor + paquetes) Sí (contenedor) No No
Opción Self-hosted Sí (GitLab completo) Sí (solo runners) No
Review Apps Nativo Configuración manual Manual Manual
Pipelines DAG Sí (keyword needs) Sí (nativo)
Auto DevOps No No No
Minutos Gratuitos 400 min/mes 2.000 min/mes Ilimitado (self-host) 6.000 min/mes
Curva de Aprendizaje Media Baja Alta Baja

GitLab CI/CD destaca cuando quieres todo integrado: código, CI, registro de contenedores, entornos y monitoreo en una sola plataforma. GitHub Actions gana en amplitud de ecosistema gracias a su marketplace.

Errores Comunes y Casos Especiales

  • Los anchors YAML no funcionan con include: Si usas anchors YAML (&anchor/*anchor) en archivos incluidos, no se resolverán entre archivos distintos. Usa la palabra clave extends en su lugar.

  • El caché no está garantizado: Los cachés de GitLab son de tipo best-effort. Los runners pueden no compartir cachés entre sí. Diseña siempre pipelines que funcionen sin caché (aunque más lentos).

  • Red de servicios: Los contenedores de servicio (como postgres:15) son accesibles mediante el nombre de la imagen como hostname. Usa postgres, no localhost. Esto confunde a muchos desarrolladores.

  • only/except vs rules: La sintaxis heredada only/except es incompatible con rules. Nunca los mezcles en el mismo trabajo. Prefiere rules; es más potente y es el enfoque recomendado.

  • El timeout de trabajos es 1 hora por defecto: Los trabajos de larga duración, como pruebas E2E o compilaciones grandes, fallan silenciosamente al alcanzar el timeout. Define timeout: 2h explícitamente para trabajos que sabes que duran más.

  • Variables de ramas protegidas: Las variables marcadas como “Protected” no están disponibles en ramas de funcionalidades. Si un trabajo necesita credenciales en ramas no protegidas, usa una variable separada sin el flag de protección.

Solución de Problemas

Problema Causa Solución
Pipeline atascado en “Pending” No hay runners disponibles con las etiquetas correctas Revisa las etiquetas del runner o define tags: [] para usar cualquiera
“Cache not found” en la primera ejecución El caché aún no se ha creado La primera ejecución descarga todo; el caché se llena para las siguientes
Servicios no accesibles Hostname incorrecto en la cadena de conexión Usa el nombre de la imagen del servicio como hostname (p. ej., postgres, no localhost)
“Variable is not set” en trabajos La variable está protegida y la rama no lo está Desmarca “Protected” o haz push a una rama protegida
Artefactos faltantes en la siguiente etapa artifacts.paths no coincide con la salida Verifica las rutas exactas; usa ls -la en el script para depurar

Resumen

  • GitLab CI/CD lee .gitlab-ci.yml de tu repositorio y ejecuta pipelines automáticamente, sin necesidad de configurar herramientas externas
  • Las etapas se ejecutan en secuencia mientras que los trabajos dentro de una etapa corren en paralelo, combinando orden y velocidad
  • Los runners propios con executor Docker ofrecen el mejor rendimiento y control para equipos en producción
  • El caché de dependencias y los artefactos entre etapas reducen drásticamente el tiempo de ejecución del pipeline
  • Las variables de entorno con enmascaramiento, protección y alcance por entorno mantienen los secretos seguros en todos los despliegues
  • Las review apps crean entornos temporales por merge request, permitiendo revisión visual antes de hacer merge

Artículos Relacionados