DevOps··11 min de lectura

GitHub Actions desde cero: tu primer pipeline CI/CD en 15 minutos

Cómo funcionan los workflows, jobs y steps de GitHub Actions, con un ejemplo completo para Node.js con tests, build y deploy.

Qué es GitHub Actions y por qué usarlo

GitHub Actions es la plataforma de CI/CD integrada en GitHub. No requiere servidores propios, se factura por minuto de ejecución (con una cuota gratuita generosa en repos públicos y bastante en privados) y se configura con archivos YAML dentro de .github/workflows/. Frente a Jenkins, GitLab CI o CircleCI, su ventaja es que los eventos (push, pull_request, release, schedule) se disparan sin webhooks manuales y el marketplace tiene miles de acciones reutilizables.

Anatomía de un workflow

Un archivo bajo .github/workflows/ci.yml contiene:

  • name — cómo aparece en la pestaña Actions.
  • on — qué evento dispara el workflow (push, pull_request, workflow_dispatch manual, schedule cron).
  • jobs — uno o varios trabajos. Por defecto se ejecutan en paralelo; usa needs: para encadenar.
  • runs-on — el runner (ubuntu-latest, macos-latest, windows-latest o self-hosted).
  • steps — acciones o comandos shell secuenciales dentro del job.

Un pipeline mínimo para Node.js:


name: CI
on:
  push:
    branches: [main]
  pull_request:
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

Si no quieres pelearte con la indentación YAML, el generador de GitHub Actions produce este esqueleto en segundos.

Secretos y variables

Nunca pongas API keys en el YAML. Guárdalos en Settings → Secrets and variables → Actions y refe­réncialos como ${{ secrets.MI_TOKEN }}. Los secretos están cifrados en reposo y solo se descifran en el runner durante la ejecución. Las variables (no cifradas) valen para configuración pública como versiones o URLs.

Cache: la diferencia entre 30s y 4 min

Instalar dependencias es lo más lento del pipeline. Usa cache en la acción de setup o actions/cache@v4 manual con una key basada en el lockfile:


- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

Matriz de builds

Para probar contra varias versiones de Node o Python usa una matrix:


strategy:
  matrix:
    node: [18, 20, 22]
steps:
  - uses: actions/setup-node@v4
    with:
      node-version: ${{ matrix.node }}

GitHub lanzará tres jobs en paralelo, uno por versión.

Deploy condicional a main

El paso de deploy solo debe ejecutarse cuando el push va a la rama principal, no en cada PR:


- name: Deploy
  if: github.ref == 'refs/heads/main' && github.event_name == 'push'
  run: ./scripts/deploy.sh

Buenas prácticas rápidas

  • Pinning por SHA: en workflows sensibles, usa uses: actions/checkout@a12345... en vez de @v4. Bloquea supply-chain attacks si alguien compromete una tag mutable.
  • Timeouts: añade timeout-minutes: 15 a cada job para evitar workflows colgados que agotan tu cuota.
  • Concurrency: usa concurrency: { group: ${{ github.ref }}, cancel-in-progress: true } para cancelar builds antiguas de la misma PR.
  • Artifacts para propagar resultados entre jobs; outputs para pasar variables.

Con estos ingredientes tienes CI/CD serio en el mismo repo donde vive el código, sin infraestructura adicional.

Herramientas relacionadas

Sigue leyendo