Concepto clave
Los workflows avanzados de GitHub Actions para builds y tests automatizados son secuencias de tareas que se ejecutan automáticamente cuando ocurren eventos específicos en tu repositorio, como un push o un pull request. Piensa en esto como una cadena de montaje en una fabrica: cada paso procesa el codigo de manera ordenada, desde la compilacion hasta la ejecucion de pruebas, asegurando calidad sin intervencion manual.
Estos workflows permiten integrar continuamente cambios de codigo, detectando errores temprano y reduciendo el riesgo en produccion. A nivel intermedio, no solo automatizan tareas basicas, sino que optimizan flujos con paralelizacion, caching y matrices de jobs, similar a como un equipo de DevOps coordina multiples entornos de desarrollo simultaneamente.
Como funciona en la practica
Imagina que trabajas en una aplicacion web con Node.js. Cuando un desarrollador envia cambios al repositorio, GitHub Actions activa un workflow que:
- Verifica el codigo en un entorno limpio usando una action de checkout.
- Configura Node.js con una version especifica.
- Instala dependencias desde un cache para acelerar el proceso.
- Ejecuta el build para compilar la aplicacion.
- Corre tests unitarios y de integracion en paralelo.
- Genera un reporte de cobertura de codigo.
Si algun paso falla, el workflow se detiene y notifica al equipo, evitando que codigo defectuoso avance. Esto es como un inspector de calidad en la linea de produccion que revisa cada pieza antes del ensamblaje final.
Codigo en accion
Aqui tienes un ejemplo funcional de un workflow avanzado para una aplicacion Node.js que usa caching y matrices para tests:
name: CI Build and Test
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
test:
runs-on: ubuntu-latest
needs: build
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm test
env:
CI: true
- name: Run integration tests
run: npm run test:integration
- name: Generate coverage report
run: npm run coverage
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.node-version }}
path: test-results/Ahora, mejora este codigo agregando un paso para notificaciones en Slack despues de que los tests completen:
- name: Notify Slack on test completion
if: always()
uses: slackapi/[email protected]
with:
channel-id: 'C1234567890'
slack-message: "Tests completed for Node.js ${{ matrix.node-version }}: ${{ job.status }}"
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}Errores comunes
- No usar caching para dependencias: Esto ralentiza los workflows significativamente. Siempre configura cache para package managers como npm o pip.
- Ignorar el manejo de secrets Exponer claves API o tokens en el codigo YAML. Usa GitHub Secrets para almacenar credenciales de forma segura.
- Falta de paralelizacion en tests Ejecutar todos los tests secuencialmente aumenta el tiempo de CI. Usa matrices o jobs paralelos para dividir la carga.
- No validar el YAML Errores de sintaxis en el archivo .github/workflows/*.yml pueden romper el CI. Usa herramientas como actionlint o valida localmente antes de commit.
- Omitir condiciones de ejecucion Ejecutar workflows en cada push a todas las ramas desperdicia recursos. Limita con ramas especificas o paths usando on: push: paths.
Checklist de dominio
- Puedo configurar un workflow que se active en push y pull request a ramas especificas.
- Se implementar caching para dependencias y optimizar tiempos de ejecucion.
- Utilizo matrices para ejecutar tests en multiples versiones de runtime o SO.
- Manejo secrets de forma segura y no los expongo en logs.
- Genero y almaceno artifacts como builds o reportes de tests.
- Configuro notificaciones en canales como Slack o email basado en resultados.
- Valido y depuro workflows usando actionlint y logs de GitHub Actions.
Optimiza un workflow existente con caching y paralelizacion
En este ejercicio, mejoraras un workflow de GitHub Actions que actualmente es ineficiente. Sigue estos pasos:
- Clona un repositorio de ejemplo desde https://github.com/example/ci-cd-demo (simulado para practica).
- Revisa el archivo
.github/workflows/build-test.ymlque tiene un workflow basico sin caching y con tests secuenciales. - Modifica el workflow para agregar caching de dependencias usando npm. Usa
actions/cache@v4con una clave basada enpackage-lock.json. - Refactoriza la seccion de tests para usar una matriz que ejecute pruebas en Node.js versiones 16, 18, y 20 en paralelo.
- Agrega un paso que suba los artifacts de build a GitHub Actions usando
actions/upload-artifact@v4. - Prueba los cambios haciendo un push a una rama feature y verifica que el workflow se ejecute mas rapido y en paralelo.
Entrega un enlace a tu fork del repositorio con los cambios implementados.
Pistas- Recuerda que la clave del cache debe ser unica pero permitir restauracion parcial con restore-keys.
- Usa strategy.matrix en el job de test para definir las versiones de Node.js y necesitara needs: build para dependencias.
- Verifica que los paths en upload-artifact coincidan con la salida de tu comando de build.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.