Workflow reutilizable GitHub Actions: CI sin copiar
En pocas palabras: Un workflow reutilizable de GitHub Actions es un YAML en .github/workflows con el trigger on: workflow_call. Escribís el CI de Node una vez y lo llamás con uses desde cada job, pasando datos con with, por ejemplo working-directory: packages/api y packages/web con Node 22.
Un workflow reutilizable de GitHub Actions es un archivo YAML con el trigger on: workflow_call que otros workflows invocan con uses a nivel de job. Escribís el CI de Node una vez, lo llamás desde cada paquete del monorepo y cambiás los pasos en un solo lugar.
Un workflow reutilizable de GitHub Actions es un archivo YAML guardado en .github/workflows cuyo bloque on incluye workflow_call. Eso lo vuelve invocable desde otros workflows, llamados “caller”, que lo referencian con la palabra clave uses dentro de un job. Sirve para no copiar y pegar los mismos pasos de CI entre repositorios o paquetes de un monorepo.
En este artículo:
- En 30 segundos
- ¿Cómo se crea un workflow reutilizable en GitHub Actions con workflow_call?
- ¿Cómo llamar un workflow reutilizable con uses desde otro workflow?
- ¿Cómo configurar CI en un monorepo con varios paquetes?
- ¿Se puede combinar un workflow reutilizable con una matriz multi-OS?
- ¿Cuándo conviene un workflow reutilizable y cuándo una composite action?
- ¿Cómo verificar que la migración al workflow reutilizable funciona?
- Errores comunes
- Preguntas Frecuentes
- Conclusión
- Fuentes
En 30 segundos
- Para que un workflow sea invocable, su bloque
ontiene que incluirworkflow_call; sinpushnipull_request, nunca corre solo. - Se llama con
uses: ./.github/workflows/reusable-workflow.ymly se le pasan datos conwith. - En un monorepo se llama una vez por paquete con
working-directory; el tutorial de dev.to usapackages/apiypackages/web(este último con Node 22). - La documentación de GitHub permite hasta diez niveles de anidamiento (el caller más nueve niveles reutilizables).
- El tutorial lo publicó el autor de un pack de pago y lo declara en un disclosure; la referencia técnica es la documentación oficial.
¿Cómo se crea un workflow reutilizable en GitHub Actions con workflow_call?
Se crea agregando workflow_call al bloque on de un archivo dentro de .github/workflows. Según la documentación de GitHub, los subdirectorios de esa carpeta no son compatibles. Como el archivo no tiene otro trigger, el que decide cuándo corre es el workflow que lo llama.
El ejemplo del tutorial de dev.to (publicado el 15 de octubre de 2026) es un CI de Node con dos inputs de tipo string: node-version (por defecto “20”) y working-directory (por defecto “.”).
name: Reusable Node CI
on:
workflow_call:
inputs:
node-version:
type: string
default: "20"
working-directory:
type: string
default: "."
permissions:
contents: read
jobs:
ci:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: npm
cache-dependency-path: ${{ inputs.working-directory }}/package-lock.json
- run: npm ci
- run: npm test --if-presentEl permissions: contents: read deja el token del job en solo lectura, que alcanza para un CI.
¿Cómo llamar un workflow reutilizable con uses desde otro workflow?

Lo llamás con uses directamente dentro de un job, no dentro de steps. Para el mismo repositorio la sintaxis es ./.github/workflows/reusable-workflow.yml, y el workflow llamado sale del mismo commit que el caller. Los datos se pasan con with. En ajustes para el CI de Node.js profundizamos sobre esto.
jobs:
ci:
uses: ./.github/workflows/reusable-workflow.yml
with: { node-version: "20" }Para un workflow de otro repositorio, la forma es {owner}/{repo}/.github/workflows/{archivo}@{ref}. El ref puede ser un SHA, un tag de release o una rama. La documentación dice que el SHA es la opción más segura para estabilidad y seguridad. Con una rama o un tag tenés que confiar en quien los mueve.
¿Cómo paso inputs y secrets a un workflow reutilizable?
Los inputs se pasan con with y los secrets con secrets, y ambos se declaran antes en on.workflow_call del workflow llamado. El tipo del valor tiene que coincidir con el declarado (boolean, number o string). Dentro de la misma organización o empresa, secrets: inherit pasa todos los secrets de golpe.
Ojo con los secrets de entorno. Si el caller no pasa uno, el workflow llamado lo recibe como string vacío y no muestra ningún error. Marcar el secret con required: true hace fallar la corrida, aunque solo verifica que el caller lo pase, no que tenga valor.
¿Cómo configurar CI en un monorepo con varios paquetes?
Llamás al mismo workflow una vez por paquete y cambiás working-directory. En el ejemplo del tutorial, el job api apunta a packages/api con los valores por defecto, y el job web apunta a packages/web con node-version: "22". Más contexto en comparativa entre GitHub Actions, GitLab y Jenkins.
jobs:
api:
uses: ./.github/workflows/reusable-workflow.yml
with: { working-directory: "packages/api" }
web:
uses: ./.github/workflows/reusable-workflow.yml
with: { working-directory: "packages/web", node-version: "22" }Tres detalles del workflow importan acá:
defaults.run.working-directoryaplica a cadarun:. Asínpm ciynpm testcorren dentro del paquete elegido. No afecta a los steps conuses, que no son comandos de shell.cache-dependency-pathapunta al lockfile del paquete. Sin eso, según el tutorial,setup-nodebusca el lockfile en la raíz y falla o cachea cualquier cosa.npm test --if-presentsaltea paquetes sin scripttest. Un paquete sin tests no rompe el pipeline.
Mi lectura: este diseño asume un package-lock.json por paquete. Si tu monorepo usa un único lockfile en la raíz (workspaces), el cache-dependency-path del ejemplo no te sirve tal cual y hay que adaptarlo. El tutorial no cubre ese caso.
¿Se puede combinar un workflow reutilizable con una matriz multi-OS?
Sí, con una aclaración. La documentación de GitHub confirma que un job con estrategia matrix puede llamar a un workflow reutilizable (su ejemplo corre tres jobs con target: [dev, stage, prod]). El ejemplo del tutorial es otra cosa: un job común con su propia matriz, que el autor presenta como complemento de la idea.
test:
needs: lint
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
exclude:
- os: macos-latest
node: 18Son 3 sistemas por 3 versiones de Node, o sea 9 combinaciones, y el exclude saca macOS con Node 18 para dejar 8. Con fail-fast: false terminan todas las combinaciones y ves cada falla en un solo push, en vez de enterarte de una plataforma rota por vez. Con needs: lint, el test solo corre si el lint pasó.
¿Cuándo conviene un workflow reutilizable y cuándo una composite action?
Un workflow reutilizable conviene cuando querés compartir un proceso entero, con varios jobs y runners propios. Una composite action conviene cuando querés agrupar steps que corren dentro de un job. Así lo plantea la documentación sobre cómo evitar duplicación.
- Jobs y runners. El workflow reutilizable puede tener varios jobs, cada uno con su máquina. La composite action no contiene jobs.
- Logs. En el workflow reutilizable cada job y step se registra por separado. La composite action aparece como un único step.
- Posición en el job. El reutilizable se llama desde el job y no podés agregar steps después. La composite action corre como un step más, con pasos antes y después.
- Publicación. La composite action se puede publicar en el marketplace; el workflow reutilizable no.
- Secrets. La tabla de la documentación indica que los workflows reutilizables pueden usar secrets y las composite actions no.
Los límites también están documentados. El anidamiento llega a diez niveles de workflows, sin bucles, y los permisos solo pueden mantenerse o reducirse a lo largo de la cadena. Los secrets se pasan solo a la llamada directa: en una cadena A, B, C, el workflow C recibe lo que B le pase, aunque A le haya dado todo a B. Para estandarizar la creación de workflows en una organización existen además los workflow templates, que pueden referenciar workflows reutilizables.
Una advertencia sobre la fuente: el tutorial de dev.to lo escribe el autor de un pack de pago y lo aclara en su disclosure. El YAML es coherente con la documentación, pero para decidir tu diseño la referencia es la doc oficial. Tema relacionado: agentes de IA que revisan cada pull request.
¿Cómo verificar que la migración al workflow reutilizable funciona?
Esta es una propuesta editorial, no un procedimiento de las fuentes ni algo que hayamos medido. Abrí un pull request de prueba que llame al workflow desde dos paquetes, uno con script test y otro sin él. Revisá tres cosas: que ambos jobs terminen en verde, que el paso de caché use el lockfile de cada paquete y que los logs muestren los jobs del workflow llamado por separado. Si el paquete sin tests falla, revisá el --if-present.
Si querés ver cómo evitar que se rompan las rutas al renombrar archivos, armamos un workflow reutilizable de CI que lo resuelve paso a paso.
Errores comunes
- Poner
usesdentro desteps. Los workflows reutilizables se llaman a nivel de job. Para invocar un workflow desde un step no hay camino; ahí corresponde una action. - Guardar el archivo en un subdirectorio. GitHub no admite subdirectorios dentro de
.github/workflows. Dejalo en la raíz de esa carpeta. - Olvidar pasar un secret de entorno. Llega vacío y sin error. Declaralo con
required: truey pasalo por nombre o consecrets: inherit. - Referenciar otro repositorio con
@main. Cualquier cambio en esa rama te llega sin aviso. Fijá un SHA, que es lo que la doc califica como lo más seguro. - Pasar un número como string o al revés. El tipo del input en
withtiene que coincidir con el declarado en el workflow llamado.
Preguntas Frecuentes
¿Cómo reutilizo un workflow en GitHub Actions?
Agregás workflow_call al bloque on del workflow que querés compartir y lo llamás desde otro con uses a nivel de job. En el mismo repositorio la ruta es ./.github/workflows/archivo.yml. Para otro repositorio usás {owner}/{repo}/.github/workflows/archivo.yml@{ref}.
¿Qué hace el trigger workflow_call en GitHub Actions?
Convierte el workflow en invocable por otros workflows. Un archivo que solo tiene workflow_call no corre por sí mismo, porque no tiene push ni pull_request. También es donde declarás los inputs, secrets y outputs que el caller puede usar.
¿Cuál es la diferencia entre un workflow reutilizable y una composite action?
El workflow reutilizable puede tener varios jobs y se llama desde un job; la composite action agrupa steps y corre como un step dentro de un job. Según la documentación de GitHub, la composite action se registra como un único step en el log y se puede publicar en el marketplace. Lo explicamos a fondo en cuál conviene elegir entre Jenkins y Actions.
¿Cómo paso inputs a un workflow reutilizable?
Declarás los inputs con su tipo en on.workflow_call.inputs y los pasás con with en el job del caller. El tipo tiene que coincidir (boolean, number o string). Si definís un valor por defecto, el caller solo manda lo que cambia.
¿Cómo paso secrets a un workflow reutilizable?
Con la clave secrets en el job del caller, nombrando cada secret, o con secrets: inherit si ambos workflows están en la misma organización o empresa. En workflows anidados, los secrets llegan solo al workflow que el caller llama de forma directa.
Conclusión
El patrón es simple y está respaldado por la documentación oficial: un archivo con workflow_call, inputs con defaults y un job por paquete en el caller. Si tenés el mismo checkout, setup, install y test copiado en varios lugares, migrarlo te ahorra editar cada copia cada vez que cambia algo.
Mi recomendación: empezá por el CI de un solo paquete, verificá con un pull request como el que propuse y recién después replicá el llamado al resto. Si el workflow vive en otro repositorio, fijá un SHA. Y si lo que querés compartir son steps sueltos dentro de un job, mirá primero las composite actions.






