Configuración de Pipelines CI/CD
Configura pipelines CI/CD automatizados para testing, building y deployment de aplicaciones con GitHub Actions y lo que funciona.
Visión General
Continuous Integration y Continuous Deployment (CI/CD) automatizan el viaje desde el commit de código hasta el deploy en producción. Un pipeline bien configurado ejecuta tests, construye artifacts, escanea vulnerabilidades y despliega a staging o producción sin intervención manual. Esto elimina errores humanos, acelera releases y provee feedback rápido a los desarrolladores.
Cuándo Usar
Usa este recurso cuando:
- configures un nuevo proyecto y quieras testing automatizado desde el día uno. Consulta Unit Testing para fundamentos de testing.
- Migres de deploys manuales a releases automatizados. Consulta GitHub Actions para automatización de workflows.
- Agregues scanning de seguridad, linting o gates de calidad de código a tu workflow. Consulta Container Security Scanning para gates de seguridad en CI.
- Construyas una estrategia de deploy multi-ambiente (dev → staging → prod). Consulta Blue-Green Deployment para releases sin downtime.
Solución
Workflow de GitHub Actions
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test:ci
- run: npm run build
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm audit --audit-level=moderate
deploy:
needs: [test, security]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
run: |
npm run build
npm run deploy:staging
Configuración de GitLab CI
stages:
- test
- build
- deploy
variables:
NODE_VERSION: "20"
test:
stage: test
image: node:$NODE_VERSION
script:
- npm ci
- npm run test:ci
deploy_prod:
stage: deploy
script:
- npm run deploy:production
only:
- main
environment:
name: production
url: https://api.example.com
Explicación
Un pipeline de CI/CD de producción típicamente incluye:
- Trigger: Push, pull request o job programado por cron
- Build: Compila, bundlea y crea artifacts
- Test: Tests unitarios, tests de integración, linting, type checking
- Seguridad: Auditoría de dependencias, SAST, escaneo de secretos
- Deploy: Push a staging, smoke tests, promoción a producción
- Notificación: Slack, email o sistema de incident management
Estrategias de deploy:
- Básico: Deploy directo a producción
- Blue-Green: Dos ambientes idénticos; switch de tráfico instantáneo
- Canary: Rutea 1% de tráfico a nueva versión; incrementa gradualmente
- Rolling: Reemplaza instancias una a una con zero downtime
Variantes
| Plataforma | Ideal Para | Notas |
|---|---|---|
| GitHub Actions | Open source, repos GitHub | Gratis para repos públicos; marketplace de actions |
| GitLab CI | Proyectos GitLab-hosted | Built-in; excelente para monorepos |
| CircleCI | Testing paralelo rápido | Excelente soporte de Docker |
| Jenkins | On-premise, plugins custom | Self-hosted; alto mantenimiento |
| ArgoCD | Kubernetes GitOps | Declarativo; sincroniza cluster con estado Git |
Lo que funciona
- Fail fast: Ejecuta linting y tests unitarios rápidos antes de tests de integración costosos
- Paraleliza jobs: Divide tests por archivo o módulo para reducir tiempo wall-clock
- Cachea dependencias: Cachea node_modules, pip cache y capas Docker entre ejecuciones
- Usa secrets management: Nunca commitees API keys; usa secrets de GitHub/GitLab o Vault
- Requiere reviews para prod: Usa branch protection y CODEOWNERS
Errores Comunes
- Sin promoción de artifacts: Reconstruir en cada stage introduce no-determinismo
- Testear solo en CI: Los desarrolladores hacen push de código roto y esperan feedback de CI
- Secrets en variables de entorno: Visibles en logs de jobs; usa secrets enmascarados
- Sin plan de rollback: Deploys fallidos necesitan revert instantáneo vía blue-green o imagen anterior
- Ignorar tests flaky: Fallos aleatorios erosionan la confianza en el pipeline
Tips de Rendimiento
- Cachea agresivamente. Cachea dependencias, Docker layers y outputs de build:
- uses: actions/cache@v4
with:
path: |
node_modules
.next/cache
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- Usa jobs condicionales. Salta jobs innecesarios según archivos cambiados:
test:
steps:
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
src:
- 'src/**'
docs:
- 'docs/**'
- if: steps.changes.outputs.src == 'true'
run: npm test
- Usa workflows reutilizables. DRY tus definiciones de pipeline:
# .github/workflows/test.yml (reutilizable)
on:
workflow_call:
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm ci && npm test
# .github/workflows/main.yml
jobs:
test:
uses: ./.github/workflows/test.yml
- Setea timeouts de jobs. Previene jobs colgados que bloqueen el pipeline:
test:
timeout-minutes: 15
runs-on: ubuntu-latest Preguntas frecuentes
¿Esta solución está lista para producción?
Sí. Los ejemplos de código arriba muestran implementaciones probadas. Adapta el manejo de errores y la configuración a tu entorno específico antes de desplegar.
¿Cuáles son las características de rendimiento?
El rendimiento depende de tu volumen de datos e infraestructura. Las soluciones mostradas priorizan claridad. Para escenarios de alto throughput, añade caching, batching y connection pooling según sea necesario.
¿Cómo depuro problemas con este enfoque?
Empieza con el ejemplo mínimo de arriba. Añade logging en cada paso. Prueba con entradas pequeñas primero, luego escala. Usa el debugger de tu lenguaje para revisar los edge cases.
Deploy Multi-Entorno con Gates
# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [main, staging]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test:ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm audit --audit-level=moderate
- name: Run SAST
uses: github/codeql-action/init@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
deploy-staging:
needs: [test, security]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/staging'
environment:
name: staging
url: https://staging.example.com
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
- name: Deploy a staging
run: |
aws s3 sync dist/ s3://staging-bucket --delete
aws cloudfront create-invalidation --distribution-id ${{ secrets.STAGING_DIST_ID }} --paths "/*"
deploy-production:
needs: [test, security]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://example.com
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
- name: Deploy a producción
run: |
aws s3 sync dist/ s3://prod-bucket --delete
aws cloudfront create-invalidation --distribution-id ${{ secrets.PROD_DIST_ID }} --paths "/*"
Docker Build y Push en CI
# .github/workflows/docker.yml
name: Docker Build and Push
on:
push:
tags: ['v*']
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:${{ github.ref_name }}
ghcr.io/${{ github.repository }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
Deploy Blue-Green
# .github/workflows/blue-green.yml
deploy:
needs: [test, security]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Determinar entorno activo
id: active
run: |
ACTIVE=$(kubectl get service app -o jsonpath='{.spec.selector.color}')
echo "active=$ACTIVE" >> $GITHUB_OUTPUT
if [ "$ACTIVE" = "blue" ]; then
echo "target=green" >> $GITHUB_OUTPUT
else
echo "target=blue" >> $GITHUB_OUTPUT
fi
- name: Deploy al entorno inactivo
run: |
kubectl set image deployment/app-${{ steps.active.outputs.target }} \
app=ghcr.io/org/app:${{ github.sha }}
kubectl rollout status deployment/app-${{ steps.active.outputs.target }}
- name: Cambiar tráfico
run: |
kubectl patch service app -p \
'{"spec":{"selector":{"color":"${{ steps.active.outputs.target }}"}}}'
- name: Ejecutar smoke tests
run: |
./scripts/smoke-test.sh https://example.com/health
if [ $? -ne 0 ]; then
kubectl patch service app -p \
'{"spec":{"selector":{"color":"${{ steps.active.outputs.active }}"}}}'
exit 1
fi
Deploy Canary con Argo Rollouts
# rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: api-server
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10
- pause: { duration: 5m }
- setWeight: 25
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
selector:
matchLabels:
app: api-server
template:
metadata:
labels:
app: api-server
spec:
containers:
- name: api
image: ghcr.io/org/api:v2.0.0
ports:
- containerPort: 8080
Estrategia de Caching en Pipeline
# .github/workflows/cached-build.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v5
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=max
pip:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- run: pip install -r requirements.txt
- run: pytest
Recursos Relacionados
Guía de Pipelines CI/CD
Una guía práctica para construir pipelines CI/CD con GitHub Actions, testing, estrategias de deployment y procedimientos de rollback.
RecipeGitHub Actions: CI/CD
Cómo construir y desplegar con GitHub Actions usando workflows, matrices, caching y secrets.
RecipeScripting en Bash para Automatizacion DevOps y Tareas de
Como escribir scripts Bash robustos para automatizar despliegues, monitoreo de sistemas, rotacion de logs y tareas de mantenimiento rutinarias
RecipeTareas programadas con Cron
Cómo programar y gestionar tareas recurrentes usando sintaxis cron en Linux, Python y Node.js.
DocPlantilla de Página de Estado de API
Una plantilla para una página de estado de API pública que comunica uptime, incidentes y ventanas de mantenimiento a los consumidores.
RecipeScript de Rotación de Backups en Bash
Backups automatizados con políticas de retención usando bash y find.