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

ExecutorAislamientoVelocidadCaso de Uso
DockerAlto (contenedor por trabajo)RápidoOpción predeterminada para la mayoría
ShellNinguno (corre en el host)Más rápidoScripts simples, apps legadas
Docker MachineAlto + autoescaladoVariableRunners con autoescalado en la nube
KubernetesAlto (pod por trabajo)MedioDespliegues nativos en Kubernetes
VirtualBoxVM completaLentoCuando 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

AlcanceConfigurado EnDisponible Para
ProjectSettings → CI/CD → VariablesTodos los pipelines del proyecto
GroupGroup → Settings → CI/CDTodos los proyectos del grupo
InstanceAdmin → CI/CD → VariablesTodos los proyectos de la instancia
EnvironmentSettings → CI/CD → Variables (filtro de entorno)Trabajos que apuntan a ese entorno
Jobvariables: en .gitlab-ci.ymlSolo 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ísticaGitLab CI/CDGitHub ActionsJenkinsCircleCI
Archivo de Config.gitlab-ci.yml.github/workflows/*.ymlJenkinsfile.circleci/config.yml
Registro IntegradoSí (contenedor + paquetes)Sí (contenedor)NoNo
Opción Self-hostedSí (GitLab completo)Sí (solo runners)No
Review AppsNativoConfiguración manualManualManual
Pipelines DAGSí (keyword needs)Sí (nativo)
Auto DevOpsNoNoNo
Minutos Gratuitos400 min/mes2.000 min/mesIlimitado (self-host)6.000 min/mes
Curva de AprendizajeMediaBajaAltaBaja

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

ProblemaCausaSolución
Pipeline atascado en “Pending”No hay runners disponibles con las etiquetas correctasRevisa las etiquetas del runner o define tags: [] para usar cualquiera
”Cache not found” en la primera ejecuciónEl caché aún no se ha creadoLa primera ejecución descarga todo; el caché se llena para las siguientes
Servicios no accesiblesHostname incorrecto en la cadena de conexiónUsa el nombre de la imagen del servicio como hostname (p. ej., postgres, no localhost)
“Variable is not set” en trabajosLa variable está protegida y la rama no lo estáDesmarca “Protected” o haz push a una rama protegida
Artefactos faltantes en la siguiente etapaartifacts.paths no coincide con la salidaVerifica 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