Al final de este tutorial, tendrás un pipeline GitLab CI/CD completamente funcional que automáticamente testea tu código, genera reportes y despliega a múltiples entornos. En 75 minutos, construirás un workflow de testing listo para producción que captura bugs temprano y acelera tu ciclo de release.

Lo que Construirás

Crearás un pipeline GitLab CI/CD que:

  • Ejecuta tests unitarios, de integración y end-to-end automáticamente
  • Ejecuta tests en paralelo a través de múltiples etapas
  • Genera reportes de cobertura de código y calidad
  • Despliega a entornos de staging y producción
  • Implementa caché de resultados de tests para pipelines más rápidos
  • Envía notificaciones a canales de equipo en fallos
  • Crea entornos de prueba dinámicos para cada merge request

Esto resuelve el desafío de cuellos de botella de testing manual y verificaciones de calidad inconsistentes que ralentizan la velocidad de desarrollo.

Objetivos de Aprendizaje

En este tutorial aprenderás:

  • Cómo configurar .gitlab-ci.yml para workflows de testing
  • Cómo implementar pipelines multi-etapa con dependencias
  • Cómo usar el registro Docker integrado de GitLab para contenedores de test
  • Cómo cachear resultados de tests y dependencias efectivamente
  • Cómo implementar ejecución de tests en paralelo
  • Cómo asegurar secretos usando variables de GitLab CI/CD

Estimación de Tiempo: 75-90 minutos

Prerequisitos

Software Requerido

Antes de comenzar, instala:

HerramientaVersiónPropósito
Git2.30+Control de versiones
Docker20.10+Runtime de contenedores
Node.js18.x+Entorno de testing
Cuenta GitLab-Plataforma CI/CD

Instalación:

# macOS
brew install git docker node

# Linux (Ubuntu/Debian)
sudo apt update
sudo apt install git docker.io nodejs npm

# Windows (usando Chocolatey)
choco install git docker-desktop nodejs

Conocimiento Requerido

Deberías estar familiarizado con:

  • Operaciones básicas de Git (commit, push, merge)
  • Fundamentos de sintaxis YAML
  • Conceptos básicos de Docker
  • No requerido: Conocimiento avanzado de DevOps o Kubernetes

Recursos Requeridos

  • Cuenta de GitLab (tier gratuito funciona bien)
  • Repositorio con tests existentes
  • Cuenta de Docker Hub (opcional, para imágenes personalizadas)

Paso 1: Crea Configuración Básica de GitLab CI/CD

En este paso, crearemos el archivo base .gitlab-ci.yml.

Crea Configuración de Pipeline

En la raíz de tu repositorio, crea .gitlab-ci.yml:

# .gitlab-ci.yml
image: node:18-alpine

stages:
  - test
  - build
  - deploy

variables:
  npm_config_cache: "$CI_PROJECT_DIR/.npm"
  CYPRESS_CACHE_FOLDER: "$CI_PROJECT_DIR/.cypress"

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .npm
    - node_modules
    - .cypress

before_script:
  - npm ci --cache .npm --prefer-offline

unit-tests:
  stage: test
  script:
    - npm run test:unit
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
  artifacts:
    when: always
    reports:
      junit: junit.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

Qué hace esto:

  • image: Usa imagen base Node.js 18 Alpine (ligera)
  • stages: Define fases del pipeline (test → build → deploy)
  • cache: Cachea npm y Cypress para ejecuciones más rápidas
  • before_script: Instala dependencias antes de cada job
  • coverage: Extrae porcentaje de cobertura del output
  • artifacts: Guarda resultados de tests y reportes de cobertura

Push y Dispara Pipeline

git add .gitlab-ci.yml
git commit -m "Add GitLab CI/CD pipeline"
git push origin main

Navega a CI/CD → Pipelines en GitLab. Deberías ver:

✅ Pipeline #1234567 passed
   ✅ test stage
      ✅ unit-tests (42s)

Checkpoint: Ahora tienes tests unitarios automatizados ejecutándose en cada push.

Paso 2: Agrega Pipeline de Testing Multi-Etapa

Implementa Tests de Integración y E2E

Expande .gitlab-ci.yml con etapas de test adicionales:

stages:
  - test
  - integration
  - e2e
  - build
  - deploy

# Tests unitarios (del Paso 1)
unit-tests:
  stage: test
  script:
    - npm run test:unit
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
  artifacts:
    when: always
    reports:
      junit: junit.xml

# Tests de integración
integration-tests:
  stage: integration
  services:
    - postgres:15-alpine
    - redis:7-alpine
  variables:
    POSTGRES_DB: testdb
    POSTGRES_USER: test
    POSTGRES_PASSWORD: testpass
    DATABASE_URL: "postgresql://test:testpass@postgres:5432/testdb"
    REDIS_URL: "redis://redis:6379"
  script:
    - npm run db:migrate
    - npm run test:integration
  artifacts:
    when: always
    reports:
      junit: test-results/integration-junit.xml

# Tests E2E con Playwright
e2e-tests:
  stage: e2e
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  script:
    - npm ci
    - npm run build
    - npx playwright test
  artifacts:
    when: always
    paths:
      - playwright-report/
      - test-results/
    expire_in: 30 days

Qué hay de nuevo:

  • services: Levanta PostgreSQL y Redis para tests de integración
  • variables: Configuración de test específica del entorno
  • npm run db:migrate: Prepara esquema de base de datos antes de tests
  • Imagen personalizada: Usa imagen oficial Docker de Playwright para tests E2E
  • expire_in: Artefactos eliminados automáticamente después de 30 días

Checkpoint: Pipeline multi-etapa ahora ejecuta tests unitarios, de integración y E2E secuencialmente.

Paso 3: Implementa Ejecución de Tests en Paralelo

Divide Tests en Múltiples Jobs

Para feedback más rápido, ejecuta tests en paralelo:

unit-tests:
  stage: test
  parallel: 4
  script:
    - npm run test:unit -- --shard=${CI_NODE_INDEX}/${CI_NODE_TOTAL}
  artifacts:
    when: always
    reports:
      junit: junit-${CI_NODE_INDEX}.xml

e2e-tests:
  stage: e2e
  image: mcr.microsoft.com/playwright:v1.40.0-focal
  parallel:
    matrix:
      - BROWSER: [chromium, firefox, webkit]
  script:
    - npm ci
    - npx playwright test --project=$BROWSER
  artifacts:
    when: always
    paths:
      - playwright-report-$BROWSER/
    reports:
      junit: test-results/junit-$BROWSER.xml

Cómo funciona la ejecución paralela:

  • parallel: 4: Divide tests unitarios en 4 jobs concurrentes
  • CI_NODE_INDEX/CI_NODE_TOTAL: Variables integradas para sharding
  • Estrategia de matriz: Ejecuta tests E2E en 3 navegadores simultáneamente
  • Nombres de artefactos dinámicos: Cada job paralelo sube resultados separados

Ganancia de rendimiento:

  • Tests unitarios: 2m 40s → 40s (4x speedup)
  • Tests E2E: 5m 30s → 2m 10s (3x speedup en paralelo)

Paso 4: Agrega Escaneo de Calidad de Código y Seguridad

Integra GitLab Code Quality

Agrega verificaciones de calidad a tu pipeline:

include:
  - template: Code-Quality.gitlab-ci.yml
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml

stages:
  - test
  - integration
  - e2e
  - quality
  - security
  - build
  - deploy

code_quality:
  stage: quality
  artifacts:
    reports:
      codequality: gl-code-quality-report.json

sast:
  stage: security

dependency_scanning:
  stage: security

Qué agrega esto:

  • Code Quality: Analiza código por complejidad, duplicación y mantenibilidad
  • SAST: Static Application Security Testing para vulnerabilidades
  • Dependency Scanning: Verifica problemas de seguridad conocidos en dependencias
  • Widgets de merge request: Resultados aparecen directamente en interfaz de MR

Paso 5: Implementa Entornos de Test Dinámicos

Crea Review Apps para Cada MR

Agrega entornos dinámicos para testing manual de QA:

deploy-review:
  stage: deploy
  image: alpine:latest
  script:
    - apk add --no-cache curl
    - |
      curl --request POST \
        --header "PRIVATE-TOKEN: $DEPLOY_TOKEN" \
        --data "environment=review-$CI_COMMIT_REF_SLUG" \
        "https://api.your-platform.com/deploy"
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://review-$CI_COMMIT_REF_SLUG.your-app.com
    on_stop: stop-review
  only:
    - merge_requests

stop-review:
  stage: deploy
  script:
    - echo "Deteniendo entorno de review"
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  when: manual
  only:
    - merge_requests

Paso 6: Agrega Notificaciones y Monitoreo

Configura Notificaciones Slack

notify-failure:
  stage: .post
  image: curlimages/curl:latest
  script:
    - |
      curl -X POST $SLACK_WEBHOOK_URL \
        -H 'Content-Type: application/json' \
        -d '{
          "text": "❌ Pipeline falló para '"$CI_PROJECT_NAME"'"
        }'
  when: on_failure
  only:
    - main
    - develop

Configura Slack Webhook

  1. Crea app de Slack en api.slack.com/apps
  2. Habilita “Incoming Webhooks”
  3. Copia URL del webhook
  4. En GitLab: Settings → CI/CD → Variables
    • Key: SLACK_WEBHOOK_URL
    • Value: [pega URL del webhook]

Paso 7: Optimiza Rendimiento del Pipeline

Implementa Caché Avanzado

Optimiza estrategia de caché:

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

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

Mejoras de caché:

  • Key por lockfile: Caché se invalida solo cuando dependencias cambian
  • policy: pull: La mayoría de jobs solo leen caché (más rápido)
  • policy: pull-push: Primer job actualiza caché

Agrega Reglas de Optimización de Pipeline

Omite jobs innecesarios:

unit-tests:
  stage: test
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
    - changes:
        - "src/**/*"
        - "tests/**/*"
        - package.json
      when: always
    - when: never

Ganancias de rendimiento:

  • Cambios solo de docs: Pipeline omitido (0s vs 3m)
  • Caché de dependencias: Tiempo de instalación 2m → 15s
  • Omisión inteligente de jobs: Pipeline promedio 3m → 1m 30s

Solución de Problemas

Problema 1: Servicios No se Conectan

Síntomas:

Error: connect ECONNREFUSED 127.0.0.1:5432

Solución: Usa alias de servicio como hostname:

integration-tests:
  services:
    - name: postgres:15-alpine
      alias: postgres
  variables:
    DATABASE_URL: "postgresql://test:testpass@postgres:5432/testdb"

Problema 2: Timeout del Pipeline

Solución: Aumenta timeout del job:

e2e-tests:
  timeout: 90 minutes

Problema 3: Caché No Funciona

Verifica key de caché:

cache:
  key:
    files:
      - package-lock.json  # Asegúrate de que este archivo existe
  paths:
    - .npm
    - node_modules

Próximos Pasos

¡Felicitaciones! Has construido un pipeline de testing GitLab CI/CD de grado de producción. 🎉

Lo que Has Construido

Ahora tienes:

  • ✅ Pipeline multi-etapa con tests unitarios, de integración y E2E
  • ✅ Ejecución de tests en paralelo para feedback más rápido
  • ✅ Escaneo de calidad de código y seguridad
  • ✅ Entornos de review dinámicos para cada MR
  • ✅ Caché inteligente para rendimiento optimizado
  • ✅ Notificaciones Slack en fallos

Mejora Tus Habilidades

Mejoras Fáciles (30 min cada una)

  1. Agrega Testing de Regresión Visual
  2. Habilita Auto-Merge en Éxito

Mejoras Intermedias (1-2 horas cada una)

  1. Implementa Dashboard de Reportes de Tests
  2. Agrega Performance Testing

Mejoras Avanzadas (3+ horas)

  1. Pipelines Multi-Proyecto
  2. Integración Kubernetes

Tutoriales Relacionados

Continúa aprendiendo:

Conclusión

Lo que Lograste

En este tutorial:

  1. ✅ Creaste un pipeline GitLab CI/CD multi-etapa
  2. ✅ Implementaste ejecución de tests en paralelo para velocidad
  3. ✅ Agregaste escaneo de calidad de código y seguridad
  4. ✅ Configuraste entornos de review dinámicos
  5. ✅ Configuraste notificaciones Slack
  6. ✅ Optimizaste pipeline con caché inteligente y reglas

Conclusiones Clave

  • GitLab CI/CD es poderoso: Características integradas aceleran desarrollo
  • La ejecución paralela importa: Paralelización estratégica reduce tiempo de pipeline 50-70%
  • El caché inteligente es esencial: Configuración adecuada reduce trabajo redundante
  • Las reglas optimizan costos: Omite jobs innecesarios para ahorrar recursos de cómputo

¿Preguntas o feedback? ¡Deja un comentario!

¿Te resultó útil? ¡Compártelo con tu equipo!