GitHub Actions: fundamentos
GitHub Actions: fundamentos
Un workflow es un proceso automatizado configurable, definido en YAML, que vive en .github/workflows/ y ejecuta uno o más jobs. Es el corazón de todo lo que .github te permite automatizar: correr tests, buildear, publicar releases o cualquier tarea que se dispare por actividad en el repositorio. En este capítulo desarmamos su anatomía; los eventos que lo disparan quedan para el capítulo 3.
Estructura mínima
Todo workflow necesita tres claves: name (etiqueta legible en la UI), on (qué lo dispara) y jobs (qué ejecuta). Este ejemplo corre los tests de un proyecto Node en cada push:
# .github/workflows/ci.yml
name: CI
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm test
Con solo ese archivo en la rama por defecto, GitHub ya corre el pipeline en cada push, sin instalar nada más.
Jobs: la unidad de ejecución
Un job es un conjunto de steps que corren en un mismo runner (una máquina virtual limpia). Un dato importante: los jobs de un mismo workflow corren en paralelo por defecto. Si definís tres jobs sin dependencias entre ellos, GitHub los arranca a la vez, cada uno en su propio runner aislado. Para forzar un orden secuencial se usa needs, que vemos en el capítulo 4.
Cada job arranca desde cero: el filesystem, las variables y las herramientas instaladas en un job no están disponibles en otro salvo que las pases explícitamente (vía artifacts u outputs).
Steps: run vs uses
Dentro de un job, los steps se ejecutan en orden, uno tras otro, en el mismo runner. Hay dos tipos:
| Tipo | Qué hace | Ejemplo |
|---|---|---|
run: | Ejecuta un comando de shell en el runner | run: npm test |
uses: | Invoca una Action reusable (empaquetada) | uses: actions/checkout@v4 |
Un step uses: puede recibir parámetros con el bloque with::
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
actions/checkout clona tu repo dentro del runner (casi siempre es el primer step, porque el runner arranca vacío). Las Actions llevan una referencia de versión con @ (@v4, un tag, o un SHA de commit para fijarla de forma inmutable).
Runners: dónde corre todo
Un runner es la máquina que ejecuta un job. Hay dos familias:
- Hosted por GitHub: VMs efímeras que GitHub provee y destruye tras cada job. Se seleccionan con
runs-on:ubuntu-latest,windows-latest,macos-latest(y sus variantes con versión fija, p. ej.ubuntu-22.04). Son la opción por defecto y no requieren mantenimiento. - Self-hosted: máquinas propias (on-premise o en tu nube) que registrás contra el repo u organización. Útiles cuando necesitás hardware específico, acceso a una red interna o control total del entorno. Requieren que vos los mantengas y asegures.
Claves top-level del workflow
Además de name, on y jobs, un workflow admite estas claves de primer nivel. Las mencionamos aquí y las profundizamos en los capítulos siguientes:
| Clave | Para qué |
|---|---|
name | Nombre legible del workflow en la UI |
on | Evento(s) que disparan el workflow (cap. 3) |
jobs | Los jobs a ejecutar |
permissions | Permisos del GITHUB_TOKEN (cap. 6) |
env | Variables de entorno visibles para todo el workflow |
defaults | Valores por defecto para los steps (p. ej. shell o working-directory) |
concurrency | Agrupa runs para cancelar o encolar los que se solapan |
El flujo completo
flowchart TD
E["Evento<br/>(push, PR, schedule...)"] --> WR["Workflow run"]
WR --> J1["Job: test<br/>runs-on: ubuntu-latest"]
WR --> J2["Job: lint<br/>runs-on: ubuntu-latest"]
WR --> J3["Job: build<br/>runs-on: ubuntu-latest"]
J1 --> S1["step: checkout"] --> S2["step: npm ci"] --> S3["step: npm test"]
J2 --> L1["step: checkout"] --> L2["step: npm run lint"]
J3 --> B1["step: checkout"] --> B2["step: npm run build"]
El evento genera un workflow run; dentro de él, los jobs corren en paralelo; dentro de cada job, los steps corren en secuencia.
Nota: cada job estrena un runner limpio. No asumas que un archivo generado en el job
buildestá disponible en el jobtest— para eso existen los artifacts, que vemos en el capítulo 4.
Anterior → Capítulo 1: Introducción · Siguiente → Capítulo 3: Triggers y eventos