Al final de este tutorial, tendrás una configuración completamente funcional de Bitbucket Pipelines que ejecuta pruebas automáticamente en cada commit. En solo 45 minutos, configurarás un pipeline CI/CD que detecta errores antes de llegar a producción, con testing paralelo, caché y estrategias de despliegue.

Lo Que Construirás

Crearás un pipeline de testing listo para producción que:

  • Ejecuta automáticamente pruebas unitarias, de integración y E2E en cada push
  • Ejecuta pruebas en paralelo para reducir el tiempo de build en 60%
  • Almacena en caché las dependencias para acelerar los builds
  • Genera reportes de cobertura de pruebas
  • Despliega automáticamente cuando todas las pruebas pasan

Esta configuración es utilizada por empresas como Atlassian, Docker y miles de equipos de desarrollo para mantener la calidad del código y entregar más rápido.

Objetivos de Aprendizaje

En este tutorial aprenderás:

  • Cómo configurar bitbucket-pipelines.yml para testing automatizado
  • Cómo configurar ejecución de pruebas en paralelo para feedback más rápido
  • Cómo implementar estrategias de caché para optimizar tiempos de build
  • Cómo integrar reportes de cobertura y quality gates
  • Cómo manejar diferentes entornos (staging, producción)
  • Cómo solucionar problemas comunes del pipeline

Tiempo Estimado: 45-60 minutos

Prerequisitos

Software Requerido

Antes de comenzar, instala:

HerramientaVersiónPropósito
Git2.0+Control de versiones
Node.js18+Runtime para el proyecto ejemplo
npm9+Gestión de paquetes
Docker20+Runtime de contenedores (opcional)

Instalación:

# macOS
brew install git node

# Linux (Ubuntu/Debian)
apt-get install git nodejs npm

# Windows
choco install git nodejs

Conocimientos Requeridos

Debes estar familiarizado con:

  • ✅ Flujos básicos de Git (commit, push, pull)
  • ✅ Fundamentos de línea de comandos
  • ✅ Comprensión básica de conceptos CI/CD
  • ❌ No requerido: Conocimiento avanzado de Docker o Kubernetes

Recursos Requeridos

  • Cuenta de Bitbucket (tier gratuito funciona)
  • Un repositorio con pruebas (o usa nuestro proyecto ejemplo)
  • Acceso de escritura a configuración del repositorio
  • 15 minutos para ejecución inicial del pipeline

Paso 1: Configuración del Proyecto

En este paso, crearemos el archivo de configuración del pipeline y entenderemos su estructura.

Crear Configuración del Pipeline

Navega a la raíz de tu repositorio y crea el archivo de configuración:

cd tu-proyecto
touch bitbucket-pipelines.yml

Agrega la estructura básica del pipeline:

# bitbucket-pipelines.yml
image: node:18

pipelines:
  default:
    - step:
        name: Build and Test
        caches:
          - node
        script:
          - npm install
          - npm test

Lo que hace esto:

  • image: node:18 - Especifica la imagen Docker para el entorno de build
  • caches: - node - Cachea node_modules para acelerar builds subsecuentes
  • script - Comandos ejecutados en secuencia

Commit y Push

git add bitbucket-pipelines.yml
git commit -m "Add Bitbucket Pipelines configuration"
git push origin main

Deberías ver:

  • Bitbucket detecta automáticamente la configuración
  • La primera ejecución del pipeline comienza en 30 segundos
  • El pipeline aparece en la UI de Bitbucket en la pestaña “Pipelines”

💡 Consejo Pro: Habilita Pipelines en Configuración del Repositorio → Pipelines → Configuración si aún no está habilitado.

Verificar Configuración

Navega a tu repositorio en Bitbucket y haz clic en la pestaña “Pipelines”.

Resultado esperado:

✅ Pipeline #1 (en progreso)
   └── Build and Test (ejecutando)

Punto de Control: Ahora deberías tener un pipeline básico ejecutándose. Incluso si las pruebas fallan, el pipeline debería ejecutarse.

Paso 2: Configurar Múltiples Tipos de Pruebas

Los proyectos del mundo real necesitan diferentes tipos de pruebas. Configuremos pruebas unitarias, de integración y linting en paralelo.

Actualizar Configuración del Pipeline

Modifica tu bitbucket-pipelines.yml:

image: node:18

definitions:
  caches:
    npm: ~/.npm

pipelines:
  default:
    - parallel:
      - step:
          name: Unit Tests
          caches:
            - node
            - npm
          script:
            - npm ci
            - npm run test:unit
          artifacts:
            - coverage/**

      - step:
          name: Linting
          caches:
            - node
          script:
            - npm ci
            - npm run lint

      - step:
          name: Integration Tests
          caches:
            - node
          services:
            - docker
          script:
            - npm ci
            - npm run test:integration

Lo que cambió:

  • parallel: - Ejecuta múltiples pasos simultáneamente (60% más rápido)
  • npm ci - Instalación limpia, más rápida y confiable que npm install
  • artifacts - Guarda reportes de cobertura para pasos posteriores
  • services: - docker - Inicia el daemon de Docker para pruebas de integración

Actualizar Scripts de package.json

Asegúrate de que tu package.json tenga los scripts de prueba:

{
  "scripts": {
    "test:unit": "jest --coverage --testPathPattern=unit",
    "test:integration": "jest --testPathPattern=integration",
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
  }
}

Problemas Comunes ⚠️

Problema: “npm run test:unit not found”

Solución: Agrega el script faltante a package.json o actualiza el comando del pipeline para coincidir con tu comando de prueba real:

script:
  - npm ci
  - npm test  # Usa tu comando de prueba real

Problema: Errores de memoria insuficiente durante las pruebas

Solución: Aumenta la asignación de memoria:

- step:
    name: Unit Tests
    size: 2x  # Duplica la memoria (4GB en lugar de 2GB)

Verificar Este Paso

Haz push de tus cambios y monitorea el pipeline:

git add bitbucket-pipelines.yml package.json
git commit -m "Add parallel test execution"
git push

Resultado esperado:

✅ Pipeline #2 (en progreso)
   ├── Unit Tests (ejecutando) [30s]
   ├── Linting (ejecutando) [15s]
   └── Integration Tests (ejecutando) [45s]

Punto de Control: Los tres pasos de prueba deberían ejecutarse simultáneamente, reduciendo el tiempo total de ejecución.

Paso 3: Implementar Caché Avanzado

El caché reduce drásticamente los tiempos de build. Implementemos caché multicapa.

Estrategia de Caché Mejorada

Actualiza el pipeline con caché avanzado:

image: node:18

definitions:
  caches:
    npm: ~/.npm
    cypress: ~/.cache/Cypress
    jest: .jest-cache

pipelines:
  default:
    - parallel:
      - step:
          name: Unit Tests
          caches:
            - node
            - npm
            - jest
          script:
            - npm ci --cache ~/.npm --prefer-offline
            - npm run test:unit -- --cache --cacheDirectory=.jest-cache
          artifacts:
            - coverage/**
            - test-results/**

Beneficios del caché:

  • Primer build: ~120 segundos (sin caché)
  • Builds subsecuentes: ~35 segundos (con caché)
  • Ahorro: 70% builds más rápidos

💡 Consejo Pro: Cachea capas de Docker para builds aún más rápidos:

- step:
    name: Build Docker Image
    caches:
      - docker
    script:
      - docker build -t myapp:$BITBUCKET_COMMIT .

Verificar que el Caché Funciona

Revisa los logs del pipeline para indicadores de caché:

Restoring caches...
✓ node: Restored successfully (142.3 MB)
✓ npm: Restored successfully (89.1 MB)

Punto de Control: El segundo build debería ser 50-70% más rápido que el primero.

Paso 4: Agregar Cobertura de Pruebas y Quality Gates

Asegura la calidad del código agregando umbrales de cobertura.

Configurar Reportes de Cobertura

Agrega configuración de cobertura a jest.config.js:

// jest.config.js
module.exports = {
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coverageReporters: ['text', 'lcov', 'html'],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  }
};

Actualizar Pipeline con Quality Gates

- step:
    name: Unit Tests with Coverage
    caches:
      - node
    script:
      - npm ci
      - npm run test:unit
      - |
        if [ -f coverage/lcov.info ]; then
          echo "✅ Coverage report generated"
        else
          echo "❌ Coverage report missing"
          exit 1
        fi
    artifacts:
      - coverage/**

Lo que hace esto:

  • Genera reportes de cobertura en múltiples formatos
  • Falla el build si la cobertura cae por debajo del 80%
  • Guarda artefactos de cobertura para revisión posterior

Integración con Herramientas de Cobertura de Código

Agrega integración con Codecov:

- step:
    name: Upload Coverage
    script:
      - pipe: codecov/codecov-upload:1.3.2
        variables:
          CODECOV_TOKEN: $CODECOV_TOKEN

Salida esperada:

✅ Coverage: 87.3% (+2.1%)
✅ All thresholds passed
✅ Uploaded to Codecov

Punto de Control: El build debería fallar si la cobertura cae por debajo del 80%.

Paso 5: Pipelines Específicos por Entorno

Configura diferentes comportamientos para ramas y entornos.

Pipelines Específicos por Rama

pipelines:
  default:
    - step:
        name: Quick Tests
        script:
          - npm ci
          - npm run test:unit

  branches:
    main:
      - step:
          name: Full Test Suite
          script:
            - npm ci
            - npm run test:unit
            - npm run test:integration
            - npm run test:e2e
      - step:
          name: Deploy to Staging
          deployment: staging
          script:
            - npm run deploy:staging

    develop:
      - step:
          name: Development Tests
          script:
            - npm ci
            - npm run test:unit
            - npm run lint

  pull-requests:
    '**':
      - step:
          name: PR Validation
          script:
            - npm ci
            - npm run test:unit
            - npm run lint

Comportamiento del pipeline:

  • Ramas de features: Solo pruebas unitarias rápidas (2 minutos)
  • Pull requests: Pruebas unitarias + linting (3 minutos)
  • Rama develop: Pruebas de desarrollo (4 minutos)
  • Rama main: Suite completa + despliegue (8 minutos)

Variables de Entorno

Agrega secretos en Configuración del Repositorio → Pipelines → Variables del repositorio:

- step:
    name: Integration Tests
    script:
      - export DATABASE_URL=$DATABASE_URL_TEST
      - export API_KEY=$API_KEY_TEST
      - npm run test:integration

💡 Consejo Pro: Usa variables de despliegue para configuraciones específicas del entorno:

- step:
    name: Deploy to Production
    deployment: production
    script:
      - echo "Deploying with API_KEY: ${API_KEY}"
      - npm run deploy

Punto de Control: Diferentes ramas deberían activar diferentes configuraciones de pipeline.

Paso 6: Manejar Despliegue

Despliega automáticamente cuando las pruebas pasan.

Despliegue Condicional

- step:
    name: Deploy to Production
    deployment: production
    trigger: manual
    script:
      - pipe: atlassian/aws-s3-deploy:1.1.0
        variables:
          AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
          AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
          AWS_DEFAULT_REGION: 'us-east-1'
          S3_BUCKET: 'my-production-bucket'
          LOCAL_PATH: 'dist'

Opciones de despliegue:

  • trigger: manual - Requiere aprobación manual
  • trigger: automatic - Despliega automáticamente cuando las pruebas pasan

Despliegue con Rollback

- step:
    name: Deploy with Rollback
    script:
      - export PREVIOUS_VERSION=$(git describe --tags --abbrev=0)
      - npm run deploy
      - npm run healthcheck || (echo "Health check failed, rolling back..." && git checkout $PREVIOUS_VERSION && npm run deploy && exit 1)

Punto de Control: El despliegue solo debería ocurrir después de que todas las pruebas pasen.

Probar Tu Implementación

Ahora verifiquemos que todo funciona correctamente.

Pruebas Manuales

  1. Caso de Prueba 1: Push a Rama de Feature

    Crea y haz push a una rama de feature:

    git checkout -b feature/test-pipeline
    git push origin feature/test-pipeline
    

    Resultado esperado:

    ✅ Quick Tests passed (2m 15s)
    
  2. Caso de Prueba 2: Pull Request

    Crea un PR en la UI de Bitbucket.

    Resultado esperado:

    ✅ PR Validation passed (3m 30s)
    ├── Unit Tests ✅
    └── Linting ✅
    
  3. Caso de Prueba 3: Despliegue a Rama Main

    Merge a main:

    git checkout main
    git merge feature/test-pipeline
    git push origin main
    

    Resultado esperado:

    ✅ Full Test Suite passed (7m 45s)
    ⏸️  Deploy to Staging (trigger manual disponible)
    

Script Automatizado de Verificación de Salud

Crea un script de validación:

#!/bin/bash
# validate-pipeline.sh

echo "🔍 Validando Configuración de Bitbucket Pipeline..."

# Verificar si existe el archivo del pipeline
if [ ! -f "bitbucket-pipelines.yml" ]; then
    echo "❌ bitbucket-pipelines.yml no encontrado"
    exit 1
fi
echo "✅ Configuración del pipeline existe"

# Validar sintaxis YAML
if command -v yamllint &> /dev/null; then
    yamllint bitbucket-pipelines.yml || exit 1
    echo "✅ Sintaxis YAML válida"
fi

# Verificar scripts requeridos en package.json
required_scripts=("test:unit" "lint")
for script in "${required_scripts[@]}"; do
    if grep -q "\"$script\"" package.json; then
        echo "✅ Script '$script' encontrado"
    else
        echo "❌ Script '$script' faltante"
        exit 1
    fi
done

echo "✅ ¡Todas las validaciones pasaron! 🎉"

Ejecútalo:

chmod +x validate-pipeline.sh
./validate-pipeline.sh

Lista de Verificación de Validación

  • Pipeline se ejecuta en cada push
  • Pasos paralelos se ejecutan simultáneamente
  • Caché reduce tiempos de build subsecuentes
  • Reportes de cobertura generados
  • Comportamiento específico por rama funciona
  • Despliegue manual requiere aprobación
  • Pruebas fallidas bloquean despliegue

Solución de Problemas

Problema 1: Pipeline No Se Activa

Síntomas:

  • No se ejecuta ningún pipeline después del push
  • La pestaña “Pipelines” no muestra historial

Causas Posibles:

  1. Pipelines no habilitado en configuración del repositorio
  2. Sintaxis YAML inválida en archivo de configuración

Solución:

# Validar sintaxis YAML localmente
docker run --rm -v $(pwd):/work mikefarah/yq eval bitbucket-pipelines.yml

# Habilitar pipelines en configuración del repositorio
# Navegar a: Configuración del Repositorio → Pipelines → Configuración
# Activar "Enable Pipelines"

Cómo verificar que está arreglado:

git commit --allow-empty -m "Trigger pipeline"
git push
# Revisar pestaña Pipelines en 30 segundos

Problema 2: Errores de Memoria Insuficiente

Mensaje de error:

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

Lo que significa: Tus pruebas están consumiendo más del límite de memoria predeterminado de 2GB.

Solución rápida:

- step:
    name: Memory-Intensive Tests
    size: 2x  # Aumenta a 4GB RAM
    script:
      - npm ci
      - NODE_OPTIONS="--max-old-space-size=3072" npm test

Solución detallada:

  1. Perfila tus pruebas para encontrar fugas de memoria:

    node --inspect-brk node_modules/.bin/jest --runInBand
    
  2. Optimiza configuración de pruebas:

    // jest.config.js
    module.exports = {
      maxWorkers: 2,  // Limita workers paralelos
      clearMocks: true,
      resetMocks: true,
    };
    

Problema 3: Tiempos de Build Lentos

Si los builds toman más de 5 minutos:

  1. Habilita ejecución paralela:

    - parallel:
      - step:
          name: Fast Tests
      - step:
          name: More Tests
    
  2. Optimiza caché:

    definitions:
      caches:
        custom-cache: path/to/cache
    
  3. Usa npm ci en lugar de npm install:

    npm ci  # 40% más rápido que npm install
    
  4. Monitorea métricas de build:

    # Agregar al pipeline
    - time npm ci
    - time npm test
    

Problema 4: Fallos de Conexión al Servicio Docker

Síntomas:

  • Pruebas de integración fallan con “Cannot connect to Docker daemon”

Solución:

- step:
    name: Integration Tests
    services:
      - docker
    script:
      - sleep 10  # Esperar a que Docker inicie
      - docker ps  # Verificar que Docker está ejecutando
      - npm run test:integration

¿Aún Tienes Problemas?

Siguientes Pasos

¡Felicitaciones! Has configurado exitosamente testing automatizado en Bitbucket Pipelines. 🎉

Lo Que Has Construido

Ahora tienes:

  • ✅ Testing automatizado en cada commit
  • ✅ Ejecución de pruebas en paralelo (60% builds más rápidos)
  • ✅ Estrategia de caché multicapa
  • ✅ Reportes de cobertura con quality gates
  • ✅ Comportamiento de pipeline específico por rama
  • ✅ Controles de despliegue manual
  • ✅ Pipeline CI/CD listo para producción

Mejora Tus Habilidades

¿Listo para más? Prueba estas mejoras:

Mejoras Fáciles (30 min cada una)

  1. Agregar Notificaciones de Slack

    - step:
        name: Notify on Failure
        script:
          - pipe: atlassian/slack-notify:2.1.0
            variables:
              WEBHOOK_URL: $SLACK_WEBHOOK
    
  2. Agregar Escaneo de Seguridad

    - step:
        name: Security Audit
        script:
          - npm audit --audit-level=moderate
    

Mejoras Intermedias (1-2 horas cada una)

  1. Agregar Testing de Performance

    • Integrar Lighthouse CI
    • Establecer presupuestos de performance
    • Fallar builds en regresión
  2. Implementar Despliegue Blue-Green

    • Desplegar a entorno staging
    • Ejecutar smoke tests
    • Cambiar a producción

Mejoras Avanzadas (3+ horas)

  1. Despliegue Multi-Cloud
    • Desplegar a AWS, Azure, GCP simultáneamente
    • Enrutamiento geográfico
    • Estrategias de failover

Tutoriales Relacionados

Continúa aprendiendo:

Comparte Tus Resultados

¿Construiste un pipeline impresionante? Compártelo:

  • Tuitea tu configuración con #BitbucketPipelines
  • Escribe sobre tu experiencia en tu blog
  • Contribuye mejoras a proyectos open-source

Conclusión

Lo Que Lograste

En este tutorial:

  1. ✅ Creaste una configuración completa de Bitbucket Pipelines
  2. ✅ Implementaste ejecución de pruebas en paralelo para feedback más rápido
  3. ✅ Configuraste caché multicapa para optimizar tiempos de build
  4. ✅ Agregaste reportes de cobertura y quality gates
  5. ✅ Configuraste comportamientos de pipeline específicos por rama
  6. ✅ Configuraste despliegue condicional con controles manuales

Conclusiones Clave

  • Ejecución paralela puede reducir tiempos de build en 50-70%
  • Estrategias de caché son críticas para ciclos de feedback rápidos
  • Quality gates previenen que código de baja calidad llegue a producción
  • Configuraciones específicas por rama balancean velocidad y exhaustividad
  • Triggers de despliegue manual proporcionan seguridad para releases de producción

Sigue Aprendiendo

¡Esto es solo el comienzo! Consulta:


¿Preguntas o comentarios? Comparte tu configuración de pipeline en los comentarios abajo!

¿Te resultó útil? ¡Compártelo con tu equipo para mejorar vuestro flujo CI/CD!