|

Distribuir herramientas github actions sin npm

En pocas palabras: Usá Composite Actions con shell: bash y rutas absolutas vía ${ github.action_path }. Distribuí tu CLI Node sin npm ni build, ejecutándola directamente en el runner. Ideal para herramientas internas o open source que priorizan simplicidad sobre aislamiento de contenedores.

Si tenés una CLI en Node y querés distribuir acciones de GitHub sin usar npm, las Composite Actions son la solución más limpia. A diferencia de las JavaScript Actions, no requieren bundling ni build previo, y a diferencia de las Docker Actions, evitan el overhead de arranque del contenedor. Esta estrategia permite que cualquier usuario ejecute tu script con una sola línea en su workflow, siempre que configures correctamente los paths absolutos y los códigos de salida. Para más detalles técnicos, mirá riesgos de seguridad en pipelines.

En 30 segundos

  • Sin npm ni build: Las Composite Actions usan el entorno del runner directamente; solo necesitás subir los archivos fuente al repo.
  • Error crítico evitado: Debés especificar shell: bash en cada paso o la acción fallará silenciosamente, algo que no pasa en workflows normales.
  • Rutas absolutas obligatorias: Usá ${ github.action_path } para ejecutar scripts, porque el directorio actual es el repo del usuario, no el de tu herramienta.
  • Exit codes mandan: El código de salida de tu script define si el CI pasa o falla; diseñá esto (ej: 1 para errores) desde el inicio.
  • Verificación de tags: Nunca uses @main; crea un job interno que pruebe los tags publicados (ej: v1) antes de dar soporte a usuarios externos.

Claude Code y otras herramientas modernas de desarrollo suelen apoyarse en este tipo de automatizaciones ligeras para integrarse en pipelines existentes sin fricción de instalación. Pero ojo, “distribuir acciones de GitHub” mediante composite actions tiene sus mañas técnicas que pueden romper todo si no las conocés. Más contexto en evitar caídas por DNS mal configurado.

¿Por qué elegir Composite Actions sobre JavaScript o Docker para herramientas Node?

Para scripts simples en Node.js, las Composite Actions son la opción por defecto porque eliminan dos dolores de cabeza enormes: el pre-compilado y el aislamiento innecesario. Una JavaScript Action te obliga a mantener un proceso de build (npm run build) y commitear el bundle resultante, lo cual ensucia el historial y complica los diffs. Por otro lado, usar una Docker Action para una herramienta que solo corre en Node implica pagar el costo de arranque del contenedor y gestionar imágenes, algo totalmente desproporcionado si no necesitás aislar dependencias del sistema operativo. La ejecución en el entorno del runner es nativa y rápida. Como señala el artículo técnico de referencia de QuintetKit, “usando Docker para una herramienta que completa con solo Node no hay retorno sobre el costo de arranque”. Es decir, estás pagando un precio alto por una ventaja que no necesitás. Además, las Composite Actions permiten mezclar pasos de shell, acciones reutilizables y scripts locales en un solo archivo YAML, dándote flexibilidad sin salir del repositorio.
CaracterísticaJavaScript ActionDocker ActionComposite Action
Necesidad de BuildSí (bundle)No (imagen)No
AislamientoBajoAltoNinguno (usa runner)
Complejidad de SetupMediaAltaBaja
Ideal para…Acciones complejas JSHerramientas binarias/systemCLI tools en Node/Python
distribuir herramientas github actions diagrama explicativo

Estructura básica de una Composite Action sin publicar en npm

El corazón de esta distribución es el archivo action.yml ubicado en la raíz del repositorio. No necesitás un package.json publicado ni crear una cuenta en el registry de npm. Solo definís los inputs que tu herramienta acepta y los pasos que ejecuta. La estructura mínima incluye la definición de inputs (como path o format) y luego una lista de steps. Lo interesante es que podés instalar dependencias temporalmente usando actions/setup-node@v4 seguido de un npm ci, pero todo queda contenido en la ejecución de la acción. Los usuarios finales solo escriben: uses: your-name/tool-name@v1 Con esa única línea, la herramienta se vuelve usable. No hay configuración extra, no hay variables de entorno globales que limpiar después. Es tan simple como listar pasos de shell que corren secuenciales. Sin embargo, la simplicidad termina ahí: la gestión de rutas y shells requiere precisión quirúrgica.

El error crítico: olvidar ‘shell: bash’ en cada paso

Este es el pitfall número uno y probablemente el que más horas de debugging te va a costar si no lo tenés presente. En los workflows normales de GitHub Actions, podés omitir el shell y el runner asume un default (generalmente bash en Linux). Pero en las Composite Actions, NO PODES OMITIRLO. Cada step que use run: DEBE especificar explícitamente shell: bash (o sh/pwsh). Si no lo hacés, la acción falla con un error críptico o simplemente no ejecuta el comando como esperabas. ¿Y qué pasó cuando alguien olvidó esto? Exacto, el pipeline se rompió y nadie entendió por qué. El motor de ejecución de las composite actions es más estricto con el contexto de los pasos individuales. Acordate: si ves un run:, poné el shell: debajo. Sin excepciones.

Uso correcto de ${ github.action_path } para rutas absolutas

Acá viene lo bueno, y también donde la mayoría se confunde. Cuando una Composite Action se ejecuta, el directorio de trabajo inicial (cwd) es el repositorio del USUARIO, no el repositorio de tu acción. Esto significa que si intentás hacer cd ./bin o correr node index.js, vas a buscar esos archivos en el repo ajeno, y obvio que no van a estar ahí. Tenés que usar la variable ${ github.action_path }, que apunta a la ruta absoluta donde vive tu acción dentro del workspace del runner. Para instalar dependencias, hacés: working-directory: ${ github.action_path } Y para ejecutar el script final: node "${ github.action_path }/bin/mdlinkcheck.js" ... Si ignorás esto, vas a intentar ejecutar npm ci en el repo del usuario (generando conflictos o errores de package.json inexistente) o fallar al no encontrar tu propio binario. Es un detalle técnico menor pero fatal.

Gestión de exit codes y validación de tags publicados

Los códigos de salida (exit codes) de tus scripts determinan directamente el éxito o fracaso del CI. Si tu herramienta encuentra un problema, debe devolver un código distinto de cero (ej: 1). Si devuelve 0, GitHub asume que todo está bien, aunque internamente haya habido warnings. Diseñá tus exit codes con criterio: 0 para éxito, 1 para errores encontrados (CI debería fallar), 2 para errores de uso (argumentos mal pasados). Ahora, hablemos de versionado. NUNCA digas a los usuarios que usen @main. Eso expone a la gente a cambios bruscos sin avisar. La estrategia correcta es usar tags semánticos. Creá un tag “funcional” como v1 que apunte siempre a la última versión estable 1.x, y dejá que los usuarios hagan pinning a versiones específicas si necesitan estabilidad extrema. ¿Alguien verificó que los tags funcionen? Muchas veces no. Agregá un job en tu propia CI que intente usar la acción referenciada por el tag publicado (your-name/your-tool@v1). Así, si rompés el retagging, tu CI falla antes de que los usuarios reporten bugs. Es una red de seguridad barata y efectiva.

Errores comunes al distribuir acciones de GitHub

Más allá de los issues técnicos de sintaxis, hay errores conceptuales que hacen que la distribución sea un infierno para quien la usa.
  • Ignorar las dependencias del sistema: Si tu tool necesita Python o librerías C++, tenés que instalarlas en los steps previos. Una Composite Action no trae un entorno mágico; hereda lo que tiene el runner. Si el runner cambia de imagen base, tu acción puede dejar de funcionar.
  • Falta de documentación en el README: Aunque el action.yml defina inputs, si no explicás ejemplos de uso en el README, la gente no sabe cómo llamar a tu acción. Incluí snippets copiables.
  • Publicar prematuramente en el Marketplace: No hace falta. Podés tener miles de usuarios usando uses: user/repo@v1 sin haber pasado por la revisión del Marketplace. Publicalo solo cuando tengas el repo pulido, con topics y descripción clara.

Preguntas Frecuentes

¿Puedo usar mi propio script de Node en GitHub Actions sin publicarlo en npm?

Sí, absolutamente. Mediante una Composite Action, GitHub clona tu repositorio privado o público durante la ejecución del workflow, permitiendo que accedas a los archivos fuente localmente sin necesidad de que estén registrados en ningún paquete externo.

¿Qué es una Composite Action y cuándo debo usarla en lugar de una Docker Action?

Una Composite Action es un conjunto de pasos de workflow empaquetados en un único archivo YAML. Debes usarla en lugar de una Docker Action cuando tu herramienta corre en lenguajes interpretados como Node o Python y no requiere aislamiento de sistema operativo, ya que evita el overhead de construir y tirar imágenes Docker.

¿Cómo accedo a los archivos de mi acción si el directorio actual es el repo del usuario?

Utilizando la variable de contexto ${ github.action_path }, que proporciona la ruta absoluta al directorio donde reside tu acción. Esto te permite referenciar scripts, configuraciones y node_modules instalados específicamente para tu herramienta sin interferir con el workspace del usuario.

¿Necesito compilar o hacer build si uso una Composite Action con Node?

No, no necesitás compilar ni hacer bundling como en las JavaScript Actions. Solo necesitás ejecutar npm ci o npm install dentro del directorio de la acción para traer las dependencias declaradas en tu package.json, y luego ejecutar el script directamente con Node.

Conclusión

Distribuir acciones de GitHub vía Composite Actions es la forma más eficiente de compartir utilidades internas o open-source sin la burocracia de npm ni la pesadez de Docker. La clave está en respetar tres reglas de oro: especificar siempre el shell, usar rutas absolutas con github.action_path y verificar rigurosamente los tags publicados mediante CI interna. Si lográs dominar estos detalles, tendrás una herramienta robusta, fácil de mantener y accesible para cualquier desarrollador con una sola línea de configuración.

Fuentes

Te puede interesar...