⚙️ Jutsus Automatizados: GitHub Actions
“El ninja sabio clona su chakra para realizar mil tareas simultáneas. GitHub Actions es ese jutsu en el mundo del código.” - Maestro de la Automatización
🎯 La Filosofía de la Automatización
Imagina tener robots ninjas que trabajen para ti 24/7:
- ✅ Ejecutan tests cada vez que haces push
- ✅ Despliegan tu app automáticamente cuando fusionas a
main - ✅ Revisan tu código buscando vulnerabilidades
- ✅ Envían notificaciones a Slack cuando alguien abre un PR
- ✅ Publican tu paquete npm cuando creas una release
GitHub Actions es el motor de automatización nativo de GitHub. Sin servidores externos, sin configuración compleja. Todo vive en archivos YAML dentro de tu repo.
📜 El Camino del Conocimiento
Parte 1: Anatomía de un Workflow
Un workflow es un proceso automatizado definido en un archivo .yml o .yaml.
Ubicación obligatoria:
tu-repo/
└── .github/
└── workflows/
├── ci.yml
├── deploy.yml
└── tests.yml
Estructura básica:
name: CI Pipeline # Nombre descriptivo
on: # Eventos que activan el workflow
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs: # Tareas a ejecutar
test: # Nombre del job
runs-on: ubuntu-latest # Máquina virtual
steps: # Pasos del job
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
Conceptos clave:
- Evento (on): ¿Cuándo se activa? (push, PR, schedule, manual)
- Job: Tarea independiente (pueden correr en paralelo)
- Runner: Máquina virtual (ubuntu, windows, macos)
- Step: Acción individual dentro de un job
- Action: Bloque reutilizable (de GitHub o comunidad)
Parte 2: Tu Primer Workflow - Tests Automáticos
Objetivo: Ejecutar tests cada vez que alguien hace push o abre PR.
Archivo .github/workflows/tests.yml:
name: Run Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22] # Probar en múltiples versiones
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v4
- name: 🟢 Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: 📦 Install dependencies
run: npm ci
- name: 🧪 Run tests
run: npm test
- name: 📊 Upload coverage to Codecov
if: success()
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
Explicación:
strategy.matrix: Ejecuta el job 3 veces (Node 18, 20, 22)npm ci: Instalación limpia (más rápido quenpm install)if: success(): Solo ejecuta si pasos anteriores pasaronsecrets.CODECOV_TOKEN: Variable secreta (la defines en Settings)
Resultado: Badge en tu README

Parte 3: CI/CD Completo - Deploy Automático
Workflow que despliega a producción al fusionar a main:
name: Deploy to Production
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout code
uses: actions/checkout@v4
- name: 🟢 Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: 📦 Install dependencies
run: npm ci
- name: 🏗️ Build project
run: npm run build
env:
VITE_API_URL: ${{ secrets.PRODUCTION_API_URL }}
- name: 🧪 Run tests
run: npm test
- name: 🚀 Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
- name: 📢 Notify Slack
if: success()
uses: slackapi/slack-github-action@v1.24.0
with:
channel-id: '#deployments'
slack-message: |
✅ Deploy exitoso a producción
Commit: ${{ github.sha }}
Autor: ${{ github.actor }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
Servicios populares de deploy:
# Vercel
- uses: amondnet/vercel-action@v25
# Netlify
- uses: nwtgck/actions-netlify@v2.0
# AWS S3
- uses: aws-actions/configure-aws-credentials@v4
- run: aws s3 sync ./dist s3://mi-bucket --delete
# GitHub Pages
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
# Docker Hub
- uses: docker/build-push-action@v5
with:
push: true
tags: user/repo:latest
Parte 4: Eventos y Triggers Avanzados
1. Ejecutar workflow manualmente:
on:
workflow_dispatch: # Botón "Run workflow" en la UI
inputs:
environment:
description: 'Environment to deploy'
required: true
type: choice
options:
- staging
- production
version:
description: 'Version tag'
required: false
default: 'latest'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to ${{ github.event.inputs.environment }}
run: |
echo "Deploying version ${{ github.event.inputs.version }}"
echo "to ${{ github.event.inputs.environment }}"
2. Cron jobs (schedule):
on:
schedule:
- cron: '0 2 * * *' # Todos los días a las 2am UTC
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Delete old artifacts
run: |
# Script para limpiar archivos antiguos
Sintaxis de cron:
┌───────────── minuto (0 - 59)
│ ┌─────────── hora (0 - 23)
│ │ ┌───────── día del mes (1 - 31)
│ │ │ ┌─────── mes (1 - 12)
│ │ │ │ ┌───── día de la semana (0 - 6) (domingo = 0)
│ │ │ │ │
* * * * *
Ejemplos:
0 0 * * *- Diario a medianoche0 9 * * 1- Lunes a las 9am*/15 * * * *- Cada 15 minutos
3. Filtrar por paths:
on:
push:
paths:
- 'src/**' # Solo si cambió código fuente
- '!src/**/*.test.js' # Excepto archivos de test
4. Múltiples eventos:
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened]
release:
types: [published]
Parte 5: Actions Reutilizables del Marketplace
Top Actions imprescindibles:
1. Checkout:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Clonar todo el historial
2. Setup de lenguajes:
# Node.js
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
# Python
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
# Go
- uses: actions/setup-go@v5
with:
go-version: '1.21'
3. Cache de dependencias:
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
4. Análisis de código:
# ESLint
- name: Run ESLint
run: npm run lint
# SonarCloud
- uses: SonarSource/sonarcloud-github-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# CodeQL (seguridad)
- uses: github/codeql-action/analyze@v3
5. Notificaciones:
# Slack
- uses: slackapi/slack-github-action@v1.24.0
# Discord
- uses: sarisia/actions-status-discord@v1
# Email
- uses: dawidd6/action-send-mail@v3
Parte 6: Secrets y Variables de Entorno
Crear secrets:
- Repo > Settings > Secrets and variables > Actions
- New repository secret
- Name:
VERCEL_TOKEN, Value:tu-token-secreto
Usar secrets en workflows:
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: |
echo "Deploying with API key"
# El secret NO se imprime en logs
Variables de entorno globales:
env:
NODE_ENV: production
CACHE_VERSION: v1
jobs:
build:
runs-on: ubuntu-latest
env:
BUILD_ID: ${{ github.run_number }}
steps:
- run: echo "Build #$BUILD_ID in $NODE_ENV"
Contexts disponibles:
${{ github.repository }} # user/repo
${{ github.actor }} # Usuario que triggereó
${{ github.ref }} # refs/heads/main
${{ github.sha }} # Hash del commit
${{ github.event_name }} # push, pull_request, etc.
${{ runner.os }} # Linux, Windows, macOS
${{ secrets.MY_SECRET }} # Secreto definido en Settings
Parte 7: Workflows Avanzados
Matriz de múltiples dimensiones:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20]
include:
- os: ubuntu-latest
node: 22
exclude:
- os: macos-latest
node: 18
# Genera 6 jobs: ubuntu(18,20,22), windows(18,20), macos(20)
Jobs dependientes:
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
test:
needs: build # Solo corre si 'build' pasa
runs-on: ubuntu-latest
steps:
- run: npm test
deploy:
needs: [build, test] # Necesita que AMBOS pasen
runs-on: ubuntu-latest
steps:
- run: npm run deploy
Artifacts (compartir archivos entre jobs):
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: dist
- run: ls -la dist/
💡 Jutsu Secreto: Self-Hosted Runners
Si necesitas más control (ej: acceso a recursos internos), puedes usar runners propios:
# En tu servidor
curl -o actions-runner.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
tar xzf actions-runner.tar.gz
./config.sh --url https://github.com/user/repo --token TOKEN
./run.sh
En el workflow:
jobs:
deploy:
runs-on: self-hosted # En lugar de ubuntu-latest
Casos de uso:
- Deploy a servidores internos
- Tests que requieren hardware específico (GPUs)
- Builds de apps nativas (iOS en Mac físico)
🎯 Reto Ninja del Tema
Misión: Crear un pipeline CI/CD completo
-
Crea un repositorio con un proyecto React/Vite simple
-
Implementa 3 workflows:
Workflow 1: Tests (
tests.yml)- Trigger: push y PR a main
- Jobs: lint + test
- Usa matriz de Node 18, 20
Workflow 2: Deploy Preview (
preview.yml)- Trigger: PR a main
- Job: build + deploy a Vercel preview
- Comenta el URL en el PR
Workflow 3: Deploy Prod (
deploy.yml)- Trigger: push a main
- Jobs: build → test → deploy a producción
- Envía notificación (Slack o Discord)
-
Añade badge del workflow de tests al README
-
Configura al menos 1 secret (VERCEL_TOKEN o similar)
-
Haz que falle un workflow (a propósito) y corrígelo
Criterios de éxito:
- ✅ Los 3 workflows existen y están activos
- ✅ Tests pasan en múltiples versiones de Node
- ✅ Deploy automático funciona
- ✅ Badge visible en README
- ✅ Al menos 1 ejecución exitosa de cada workflow
📚 Recursos Adicionales
- GitHub Actions Documentation
- Awesome Actions - Galería de acciones
- GitHub Actions Marketplace
- Act - Ejecutar Actions localmente
- Workflow Syntax Reference
Boss Fight Final: El Guardián del Historial - Reto Integrador
¿Automatizaste tu repo? Comparte el link de tus Actions en Discord con #JutsuAutomatizado! ⚙️🥷