Cambiar tema

Desarrollo de composite Actions en GitHub Actions: guía completa de action.yml al Marketplace

Easton editorial illustration: action.yml package assembled from inputs, steps, outputs, and secrets then shipped to a marketplace shelf

Mirando el log del workflow con el decimoquinto error. ¿La causa? En algún repositorio privado, el paso npm install olvidó incluir NODE_AUTH_TOKEN.

Ya es la tercera vez esta semana. Ocho repositorios, cada uno con una configuración de workflow casi idéntica copiada y pegada: checkout, setup-node, install, build, test. Cambiar un detalle implica sincronizar ocho repos. Un día actualicé la versión de Node en cinco repositorios y me olvidé de los otros tres.

En ese momento lo tuve claro: no podía seguir así. La composite Action de GitHub Actions existe precisamente para esto: empaquetar pasos repetidos en un componente reutilizable e invocarlo en varios workflows como si fuera una función. Este artículo te lleva desde tu primera composite Action hasta publicarla en Marketplace, para dominar la componentización de CI/CD.

1. Conceptos centrales de la composite Action

1.1 Qué es una composite Action

Una composite Action es un mecanismo de componentización que ofrece GitHub Actions. Encapsula varios pasos (steps) en una Action independiente que puedes reutilizar en distintos workflows.

A diferencia de una JavaScript Action o una Docker Action, no necesitas escribir código. Solo defines una configuración YAML con una serie de pasos y GitHub los ejecuta. En pocas palabras, una composite Action es el «encapsulado tipo función» de un grupo de pasos.

La definición oficial: una composite Action se identifica con runs.using: "composite" y todos los pasos se ejecutan en el mismo runner. Eso significa que puedes acceder al directorio de trabajo, a variables de entorno e incluso invocar otras Actions.

1.2 Comparación de los tres tipos de Action

GitHub Actions admite tres tipos de Action:

TipoImplementaciónCaso de uso
JavaScript ActionCódigo JS/TSLógica compleja, llamadas a API
Docker ActionDockerfileEntorno o dependencias específicas
Composite ActionSolo YAMLCombinar pasos existentes, reutilización rápida

Las ventajas de la composite Action son claras: cero código, desarrollo rápido y mantenimiento sencillo. No hace falta empaquetar, compilar ni gestionar dependencias; solo escribes YAML.

1.3 Composite Action vs workflow reutilizable

Aquí mucha gente se confunde. A simple vista, ambos «reutilizan», pero son cosas distintas:

Composite Action: grupo de pasos. Se ejecuta dentro de un job, usa el runner del invocador y requiere pasar secrets explícitamente.

Workflow reutilizable: pipeline completo. Crea un job independiente, puede tener su propio runner y hereda secrets automáticamente.

Ejemplo: si quieres empaquetar «instalar dependencias + ejecutar tests» para reutilizarlo, usa composite Action. Si quieres estandarizar todo el flujo «build → test → deploy», usa workflow reutilizable. El capítulo 4 lo compara en detalle.

2. Desarrollar tu primera composite Action

2.1 Estructura de action.yml

El núcleo de una composite Action es el archivo action.yml. Es un archivo de metadatos que define el nombre, entradas, salidas y pasos de ejecución de la Action.

Un ejemplo mínimo:

name: 'Hello World'
description: 'A simple composite action'
runs:
  using: "composite"
  steps:
    - run: echo "Hello from composite action!"
      shell: bash

Esta Action solo imprime una línea. En proyectos reales necesitamos parametrización y salidas.

2.2 Ejemplo completo de action.yml

Aquí tienes una composite Action usable para build y test en proyectos Node.js:

name: 'Build and Test'
description: 'Install dependencies, build project, and run tests'
author: 'Your Name'

inputs:
  node-version:
    description: 'Node.js version to use'
    required: true
    default: '20'
  install-command:
    description: 'Command to install dependencies'
    required: false
    default: 'npm ci'
  build-command:
    description: 'Command to build the project'
    required: false
    default: 'npm run build'
  test-command:
    description: 'Command to run tests'
    required: false
    default: 'npm test'

outputs:
  build-path:
    description: 'Path to the build output'
    value: ${{ steps.build.outputs.path }}
  test-coverage:
    description: 'Test coverage percentage'
    value: ${{ steps.coverage.outputs.value }}

runs:
  using: "composite"
  steps:
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'npm'

    - name: Install dependencies
      run: ${{ inputs.install-command }}
      shell: bash

    - name: Build project
      id: build
      run: |
        ${{ inputs.build-command }}
        echo "path=dist" >> $GITHUB_OUTPUT
      shell: bash

    - name: Run tests
      id: coverage
      run: |
        ${{ inputs.test-command }}
        echo "value=85" >> $GITHUB_OUTPUT
      shell: bash

2.3 Detalle de los campos

inputs: parámetros que recibe la Action. Cada uno puede tener:

  • description: descripción (visible en Marketplace)
  • required: si es obligatorio
  • default: valor por defecto

outputs: salidas de la Action. Se pasan con la variable de entorno $GITHUB_OUTPUT. Formato:

echo "name=value" >> $GITHUB_OUTPUT

runs.steps: pasos de ejecución. Similares a un workflow normal, con dos diferencias clave:

  1. Debes indicar shell explícitamente. Cada comando run necesita shell: bash (o sh, pwsh). Es obligatorio en composite Actions.

  2. Puedes usar uses para invocar otras Actions. Por ejemplo actions/setup-node@v4 arriba.

2.4 Errores típicos

Durante el desarrollo me topé con varios:

Error 1: inputs sin campo type

Los inputs de composite Action solo admiten string. No puedes definir type: boolean o type: number como en workflows reutilizables. Para un booleano, pasa "true" o "false" como cadena y evalúalo en los pasos.

Error 2: shell obligatorio

En workflows normales puedes omitir shell en run y GitHub elige según el runner. En composite Actions debes indicarlo o fallará.

Error 3: outputs deben referenciar el id del paso

El campo value de una salida debe referenciar la salida del paso:

outputs:
  my-output:
    value: ${{ steps.my-step.outputs.result }}

Y el paso debe tener id:

- id: my-step
  run: echo "result=hello" >> $GITHUB_OUTPUT

3. Usar composite Actions

3.1 Referencia local

La forma más simple es referenciarla dentro del mismo repositorio. Si tu Action está en .github/actions/build-test/action.yml:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Referencia local
      - uses: ./.github/actions/build-test
        with:
          node-version: '20'
          test-command: 'npm run test:ci'

La ruta empieza por ./ respecto a la raíz del repo. Ideal para reutilización interna del equipo sin publicar en Marketplace.

3.2 Referencia entre repositorios

Para compartir entre varios repos, pon la Action en un repositorio dedicado:

steps:
  # Action compartida de la organización
  - uses: your-org/shared-actions/build@v1
    with:
      node-version: '18'

El formato es owner/repo/path@version, donde path es la ruta relativa de la Action en el repo.

Diseño recomendado de repo de Actions a nivel organización:

shared-actions/
├── build/
│   └── action.yml        # Build
├── deploy/
│   └── action.yml        # Deploy
├── lint/
│   └── action.yml        # Lint
└── README.md

Referencias claras:

  • your-org/shared-actions/build@v1
  • your-org/shared-actions/deploy@v1

3.3 Uso desde Marketplace

Tras publicar en Marketplace, los usuarios pueden buscarla e invocarla:

steps:
  # Suponiendo que tu Action se publicó como "build-test-action"
  - uses: your-org/[email protected]
    with:
      node-version: '20'

Marketplace ofrece selección de versión, estadísticas de uso y README, ideal para Actions open source o compartidas en público.

3.4 Estrategia de versionado al referenciar

Hay tres formas de fijar la versión:

# Opción 1: commit SHA (más seguro, inmutable)
- uses: your-org/action@a1b2c3d4e5f6...

# Opción 2: tag semántico (recomendado)
- uses: your-org/[email protected]

# Opción 3: major tag (sigue el último v1.x)
- uses: your-org/action@v1

# No recomendado: tag latest (puede actualizarse sin aviso)
# - uses: your-org/action@latest

Recomendaciones de seguridad:

En producción, commit SHA es lo más seguro: es inmutable y no cambia si el mantenedor mueve un tag.

En proyectos internos, major tag (p. ej. @v1) es flexible: sigue el último v1.x con correcciones y mejoras.

Evita @latest: puede provocar actualizaciones inesperadas y romper el build.

4. Composite Action vs workflow reutilizable

4.1 Tabla comparativa

Referencia central para elegir:

DimensiónComposite ActionWorkflow reutilizable
Nivel de ejecuciónGrupo de pasos dentro del jobJob independiente
RunnerUsa el del invocadorCrea uno nuevo (o el indicado)
SecretsPaso explícitoHerencia automática
Tipos de inputSolo stringboolean / number / string
Salidas$GITHUB_OUTPUToutputs + workflow_call
ConcurrenciaHereda la del invocadorConfigurable por separado
Variables de entornoHereda + puede añadirÁmbito independiente
Caso de usoEncapsular una funciónEstandarizar todo el pipeline

4.2 Matriz de decisión

Usa composite Action cuando:

  • Empaquetas pasos repetidos de build/test/deploy
  • Necesitas interactuar con otros pasos dentro del mismo job
  • Quieres flexibilidad en el workflow y reutilizar solo parte
  • Controlas el paso de secrets y la seguridad importa

Usa workflow reutilizable cuando:

  • Estandarizas todo el pipeline CI/CD
  • Varios proyectos comparten el mismo flujo completo
  • Quieres herencia automática de secrets (menos configuración)
  • Necesitas configuración a nivel workflow: if, timeout-minutes, etc.

Combinar ambos:

La mejor práctica suele ser combinarlos: el workflow reutilizable invoca composite Actions:

# .github/workflows/ci.yml (workflow reutilizable)
on:
  workflow_call:
    inputs:
      node-version:
        type: string
        default: '20'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      # Invocar composite Action
      - uses: ./.github/actions/build-test
        with:
          node-version: ${{ inputs.node-version }}

Así tienes estándar a nivel workflow y reutilización a nivel pasos.

5. Versionado y publicación

5.1 Buenas prácticas con Git Tags

Publicar una Action depende de Git Tags. Se recomienda versionado semántico + major tag:

# Tag de versión semántica
git tag -a v1.0.0 -m "Initial release"
git push origin v1.0.0

# Major tag (sigue el último v1.x)
git tag -fa v1 -m "Update v1 tag to latest"
git push origin v1 --force

Al publicar v1.1.0, actualiza el major tag:

git tag -a v1.1.0 -m "Add new feature"
git push origin v1.1.0

# Actualizar v1 al último
git tag -fa v1 -m "Update v1 tag to v1.1.0"
git push origin v1 --force

El usuario puede elegir:

  • @v1.1.0 para fijar versión concreta
  • @v1 para recibir actualizaciones v1.x

5.2 Publicar en Marketplace

Para publicar en GitHub Marketplace necesitas:

1. Preparar README.md

Debe incluir:

  • Nombre y descripción de la Action
  • Inputs y Outputs
  • Ejemplo de uso
  • Licencia

2. Preparar action.yml

Completa name, description, author y opcionalmente branding.

3. Crear Release

En el repositorio de GitHub:

  1. Clic en “Releases” → “Draft a new release”
  2. Elige el tag (p. ej. v1.0.0)
  3. Escribe las Release Notes
  4. Marca “Publish this Action to the GitHub Marketplace”
  5. Publica

GitHub valida action.yml y publica en Marketplace.

5.3 Workflow de publicación automatizada

Puedes automatizar la publicación:

name: Release Action

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Update major tag
        run: |
          # Extraer versión major
          MAJOR=$(echo $GITHUB_REF | sed 's/refs\/tags\/v\([0-9]*\).*/\1/')
          
          # Actualizar major tag
          git config user.name github-actions
          git config user.email [email protected]
          git tag -fa v$MAJOR -m "Update v$MAJOR tag"
          git push origin v$MAJOR --force

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          generate_release_notes: true

Este workflow actualiza el major tag y crea el Release al hacer push de un tag.

6. Técnicas avanzadas y buenas prácticas

6.1 Paso seguro de secrets

Una composite Action no accede al contexto secrets directamente. Debes pasarlos explícitamente:

# En el workflow
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: ./.github/actions/deploy
        with:
          token: ${{ secrets.DEPLOY_TOKEN }}
        env:
          AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
# En action.yml
inputs:
  token:
    description: 'Deploy token'
    required: true

runs:
  using: "composite"
  steps:
    - run: deploy --token ${{ inputs.token }}
      shell: bash
      env:
        AWS_ACCESS_KEY: ${{ env.AWS_ACCESS_KEY }}

Recomendaciones de seguridad:

  • Evita datos sensibles en inputs (pueden verse en logs)
  • Usa env para secretos (se enmascaran)
  • Documenta en el README qué secrets hacen falta

6.2 Scripts locales

La lógica compleja no encaja bien en YAML. Puedes poner scripts en el directorio de la Action:

.github/actions/build-test/
├── action.yml
└── scripts/
    └── build.sh

En action.yml:

runs:
  using: "composite"
  steps:
    - run: $GITHUB_ACTION_PATH/scripts/build.sh
      shell: bash

$GITHUB_ACTION_PATH es la ruta raíz de la composite Action.

6.3 Diseño de repo de Actions a nivel organización

Para equipos, conviene centralizar Actions compartidas:

your-org/shared-actions/
├── .github/
│   └── workflows/
│       └── test.yml       # Probar todas las Actions
├── build/
│   ├── action.yml
│   └── README.md
├── deploy/
│   ├── action.yml
│   └── README.md
├── lint/
│   ├── action.yml
│   └── README.md
└── README.md

Cada subdirectorio es una Action con README y tests.

6.4 Trampas habituales y depuración

Trampa 1: límite de profundidad de anidamiento

Una composite Action puede invocar otra hasta 10 niveles. Más allá, error. Se recomienda no superar 3; anidar mucho complica la depuración.

Trampa 2: ámbito de variables de entorno

env en un paso solo vale dentro de ese paso. Para compartir entre pasos, usa GITHUB_ENV:

steps:
  - run: echo "MY_VAR=value" >> $GITHUB_ENV
    shell: bash
  - run: echo $MY_VAR  # Accesible
    shell: bash

Consejos de depuración:

  1. ACTIONS_STEP_DEBUG=true para logs detallados
  2. echo en pasos para inspeccionar variables
  3. Action tmate para depuración SSH (no en producción)

Conclusión

La composite Action es la herramienta central de componentización en GitHub Actions: dejas de repetir configuración y encapsulas pasos de CI como funciones.

Tres puntos clave:

Estructura clara: action.yml define inputs/outputs/steps como la firma de una función. Parametrizar da flexibilidad; las salidas permiten al invocador obtener resultados.

Elige bien: composite Action para una función concreta (build, test, deploy); workflow reutilizable para estandarizar todo el pipeline. Combinarlos funciona mejor.

Versionado seguro: commit SHA en producción; major tag en proyectos internos. Evita latest.

Siguiente paso: crea tu primera composite Action, empaqueta los pasos build-test repetidos e intenta publicarla en Marketplace para tu equipo o la comunidad.

Desarrollar una composite Action en GitHub Actions

Crear desde cero una composite Action reutilizable que empaquete pasos de build y test

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Crear la estructura de directorios de la Action

    Crea el directorio de la composite Action en el repositorio:

    • mkdir -p .github/actions/build-test
    • Crea el archivo action.yml
  2. 2

    Step 2: Escribir la configuración de action.yml

    Define inputs, outputs y pasos de ejecución:

    • inputs define parámetros (node-version, test-command)
    • outputs define salidas (build-path, coverage)
    • runs.steps debe indicar shell: bash explícitamente
  3. 3

    Step 3: Probar con referencia local

    Referencia y prueba en el workflow:

    • uses: ./.github/actions/build-test
    • with: node-version: '20'
    • Publica solo después de pasar las pruebas locales
  4. 4

    Step 4: Crear Git Tags

    Usa versionado semántico + major tag:

    • git tag -a v1.0.0 -m 'Initial release'
    • git tag -fa v1 -m 'Update v1 tag'
    • git push origin v1.0.0 v1
  5. 5

    Step 5: Publicar en Marketplace

    Publica desde la UI de GitHub:

    • Releases → Draft a new release
    • Selecciona el tag (p. ej. v1.0.0)
    • Marca Publish to Marketplace
    • GitHub valida y publica automáticamente

FAQ

¿Cuál es la diferencia entre una composite Action y un workflow reutilizable?
Una composite Action es un grupo de pasos dentro de un job, usa el runner del invocador y los secrets deben pasarse explícitamente. Un workflow reutilizable crea un job independiente y hereda secrets automáticamente. Usa composite Action para encapsular una función concreta; usa workflow reutilizable para estandarizar todo el pipeline.
¿Por qué los inputs de una composite Action no tienen campo type?
Los inputs de composite Action solo admiten tipo string. No puedes definir boolean o number como en workflows reutilizables. Si necesitas un booleano, pasa la cadena 'true' o 'false' y evalúala en los pasos.
¿Cómo pasar secrets en una composite Action?
Una composite Action no puede acceder al contexto secrets directamente; debes pasarlos explícitamente. Por inputs (enmascarados en logs) o por env (más seguro, el valor no aparece en logs).
¿Debo referenciar una Action con commit SHA o con tag?
En producción usa commit SHA (más seguro, inmutable). En proyectos internos usa major tag (p. ej. @v1, sigue la última versión). Evita @latest: puede actualizarse sin aviso y romper el build.
¿Cuál es la profundidad máxima de anidamiento de composite Actions?
Una composite Action puede invocar otra composite Action hasta 10 niveles de profundidad. Se recomienda no superar 3 niveles; anidar demasiado complica la depuración.
¿Es obligatorio indicar shell explícitamente en composite Actions?
Sí. Cada paso run en una composite Action debe tener shell: bash (o sh, pwsh). Es un requisito obligatorio; en workflows normales puedes omitirlo, pero en composite Actions no.

10 min de lectura · Publicado el: 6 may 2026 · Actualizado el: 21 ago 2026

Comentarios

Inicia sesión con GitHub para dejar un comentario

Easton BlogEaston Blog