Si tu proyecto no tiene integración continua, cada push es una apuesta: "en mi máquina funciona". Con GitHub Actions puedes ejecutar tu linter y tus tests automáticamente en cada push y en cada pull request, gratis en repositorios públicos. En este tutorial armamos un workflow para Node.js que prueba tu código en dos versiones de Node a la vez, y explico cada línea para que lo adaptes a cualquier lenguaje.
1. Dónde va el archivo
GitHub busca workflows en .github/workflows/ dentro de tu repositorio. Cualquier archivo .yml ahí se convierte en un workflow. Crea .github/workflows/node-ci.yml.
2. El workflow completo
name: Node.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
node-version: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm run lint
- run: npm test
3. Qué hace cada parte
on: define cuándo se ejecuta. Aquí, en cada push a main y en cada PR dirigido a main. Si tu rama principal se llama master, cámbialo.
concurrency: si haces tres push seguidos a un PR, no tiene sentido terminar las dos primeras ejecuciones. Esta sección agrupa las ejecuciones por workflow y rama, y cancela las viejas. Ahorras minutos y obtienes feedback más rápido.
permissions: por defecto, el token del workflow puede tener permisos de escritura. Un CI solo necesita leer el código, así que lo limitamos a contents: read. Si alguna dependencia maliciosa intenta usar el token, no podrá modificar tu repo.
strategy.matrix: el truco más útil. GitHub crea un job por cada valor de la matriz, en paralelo. Con [20, 22] pruebas en ambas versiones LTS sin duplicar código. fail-fast: false evita que, si falla Node 20, se cancele Node 22: quieres ver ambos resultados para saber si el problema depende de la versión.
timeout-minutes: el límite por defecto es de 6 horas. Un test colgado puede consumir tus minutos gratuitos. 15 minutos es un tope razonable para la mayoría de los proyectos.
cache: npm: setup-node guarda la caché de npm usando el hash de tu package-lock.json como clave. Si el lockfile no cambia, la instalación es mucho más rápida.
npm ci en lugar de npm install: npm ci instala exactamente lo que dice el lockfile y falla si no coincide con package.json. Es reproducible, que es justo lo que quieres en CI.
4. Siguiente paso: protege tu rama
Una vez que el workflow pase, ve a Settings > Branches (o Rules) y exige que los checks pasen antes de hacer merge. A partir de ahí, nadie (ni tú con prisa un viernes) podrá fusionar código que rompe los tests.
El mismo patrón sirve para Python (setup-python o setup-uv con matriz ["3.11", "3.12", "3.13"], ¡entre comillas!) o Go (setup-go con go-version-file: go.mod).
¿Te sirvió? Este ejemplo es parte del Pack GitHub Actions CI en Español: paga lo que quieras, desde 2 USD. Más recursos gratis en GitHub.
Top comments (0)