Changer le thème

Actions composites GitHub Actions : de action.yml à la publication sur le Marketplace

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

Vous fixez l’écran, le quinzième log de workflow en erreur. La cause ? Une étape npm install dans un dépôt privé sans NODE_AUTH_TOKEN.

C’est déjà la troisième fois cette semaine. Huit dépôts, chacun avec une config workflow quasi identique : checkout, setup-node, install, build, test. Modifier un détail, c’est synchroniser huit dépôts. Un jour vous montez la version de Node, vous mettez à jour cinq dépôts, les trois autres oubliés.

À ce moment-là, on comprend : ça ne peut plus continuer. L’Action composite GitHub Actions existe pour ça — emballer les étapes répétées dans un composant réutilisable, comme une fonction appelée dans plusieurs workflows. Cet article vous mène du premier composite à la publication sur le Marketplace, pour maîtriser la modularisation CI/CD.

Chapitre 1 : Concepts clés des Actions composites

1.1 Qu’est-ce qu’une Action composite

Une Action composite est un mécanisme de modularisation de GitHub Actions. Elle encapsule plusieurs étapes (steps) dans une Action autonome, réutilisable dans différents workflows.

Contrairement aux Actions JavaScript ou Docker, elle ne demande pas de code. Vous écrivez du YAML, définissez une série d’étapes, GitHub les exécute. En bref : une « encapsulation fonction » d’un groupe d’étapes.

La définition officielle : une Action composite s’identifie par runs.using: "composite" ; toutes les étapes s’exécutent sur le même Runner. Vous accédez donc au répertoire de travail, aux variables d’environnement, et même à d’autres Actions.

1.2 Comparaison des trois types d’Action

GitHub Actions propose trois types :

TypeImplémentationCas d’usage
Action JavaScriptCode JS/TSLogique complexe, appels API
Action DockerDockerfileEnvironnement ou dépendances spécifiques
Action compositePur YAMLCombiner des étapes existantes, réutilisation rapide

Les avantages sont clairs : zéro code, développement rapide, maintenance simple. Pas de packaging, compilation ni gestion de dépendances — juste du YAML.

1.3 Action composite vs workflow réutilisable

Beaucoup s’y perdent. Les deux « réutilisent », mais ce n’est pas la même chose :

Action composite : groupe d’étapes. Elle s’exécute dans un job, sur le Runner de l’appelant ; les secrets doivent être passés explicitement.

Workflow réutilisable : pipeline complet. Il crée un job indépendant, avec son propre Runner ; les secrets s’héritent automatiquement.

Exemple : pour emballer « installer les dépendances + lancer les tests », utilisez une Action composite. Pour standardiser tout le flux build → test → déploiement, un workflow réutilisable. Le chapitre 4 détaille la comparaison.

Chapitre 2 : Développer votre première Action composite

2.1 Structure de action.yml

Le cœur d’une Action composite est le fichier action.yml. Fichier de métadonnées : nom, entrées, sorties et étapes.

Exemple minimal :

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

Cette Action ne fait qu’afficher une ligne. En pratique, on veut paramétrer et produire des sorties.

2.2 Exemple complet de action.yml

Voici une Action composite utilisable pour build et test d’un projet 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 Détail des champs

inputs : paramètres reçus par l’Action. Pour chaque paramètre :

  • description : explication (affichée sur le Marketplace)
  • required : obligatoire ou non
  • default : valeur par défaut

outputs : sorties de l’Action, via la variable d’environnement $GITHUB_OUTPUT. Format :

echo "name=value" >> $GITHUB_OUTPUT

runs.steps : étapes d’exécution. Comme dans un workflow ordinaire, avec deux différences clés :

  1. shell obligatoire. Chaque commande run doit avoir shell: bash (ou sh, pwsh). Exigence des Actions composites.

  2. uses pour appeler d’autres Actions. Par exemple actions/setup-node@v4 ci-dessus.

2.4 Pièges courants

Quelques écueils rencontrés en pratique :

Piège 1 : pas de champ type sur les inputs

Les inputs d’une Action composite ne supportent que le type string. Pas de type: boolean ou type: number comme dans un workflow réutilisable. Pour un booléen, passez "true" ou "false" en chaîne, puis testez dans les étapes.

Piège 2 : shell obligatoire

Dans un workflow ordinaire, run peut omettre shell — GitHub choisit selon le Runner. En Action composite, c’est obligatoire, sinon erreur.

Piège 3 : outputs via l’id de l’étape

Le champ value d’une sortie doit référencer la sortie d’une étape :

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

L’étape doit avoir un id :

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

Chapitre 3 : Utiliser une Action composite

3.1 Référence locale

Le plus simple : référencer dans le même dépôt. Supposons l’Action dans .github/actions/build-test/action.yml :

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

      # Référence locale
      - uses: ./.github/actions/build-test
        with:
          node-version: '20'
          test-command: 'npm run test:ci'

Le chemin commence par ./, relatif à la racine du dépôt. Idéal pour la réutilisation interne, sans Marketplace.

3.2 Référence inter-dépôts

Pour partager entre plusieurs dépôts, placez l’Action dans un dépôt dédié :

steps:
  # Action partagée au sein de l'organisation
  - uses: your-org/shared-actions/build@v1
    with:
      node-version: '18'

Format : owner/repo/path@version. path est le chemin relatif de l’Action dans le dépôt.

Organisation recommandée d’un dépôt d’Actions :

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

Références claires :

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

3.3 Utilisation depuis le Marketplace

Une fois publiée, recherche et référence directes :

steps:
  # Supposons l'Action publiée sous "build-test-action"
  - uses: your-org/[email protected]
    with:
      node-version: '20'

Le Marketplace offre choix de version, statistiques d’usage, affichage README — adapté aux projets open source ou Actions partagées publiquement.

3.4 Stratégie de version

Trois façons de choisir la version :

# Option 1 : commit SHA (le plus sûr, immuable)
- uses: your-org/action@a1b2c3d4e5f6...

# Option 2 : tag sémantique (recommandé)
- uses: your-org/[email protected]

# Option 3 : major tag (suit le dernier v1.x)
- uses: your-org/action@v1

# Déconseillé : tag latest (mise à jour involontaire)
# - uses: your-org/action@latest

Recommandations de sécurité :

En production, le commit SHA est le plus sûr. Immuable : pas de surprise si le mainteneur met à jour un tag.

En interne, le major tag (ex. @v1) est flexible : il suit le dernier v1.x, avec correctifs et nouvelles fonctionnalités.

Évitez @latest — risque de casser le build.

Chapitre 4 : Action composite vs workflow réutilisable

4.1 Tableau comparatif

Référence pour choisir :

DimensionAction compositeWorkflow réutilisable
Niveau d’exécutionGroupe d’étapes dans un jobJob indépendant
RunnerRunner de l’appelantNouveau Runner (ou spécifié)
SecretsTransmission expliciteHéritage automatique
Types d’entréestring uniquementboolean / number / string
Sorties$GITHUB_OUTPUToutputs + workflow_call
ConcurrenceLimite héritée de l’appelantRéglage indépendant
Variables d’env.Héritage + ajout possiblePortée indépendante
Cas d’usageEncapsulation d’une fonctionStandardisation du pipeline

4.2 Matrice de décision

Action composite :

  • Emballer des étapes build/test/déploiement répétées
  • Interagir avec d’autres étapes dans le même job
  • Garder la flexibilité du workflow, réutiliser seulement une partie
  • Contrôle explicite des secrets, exigence de sécurité élevée

Workflow réutilisable :

  • Standardiser tout le pipeline CI/CD
  • Même flux complet sur plusieurs projets
  • Héritage automatique des secrets (moins de config)
  • Besoin de if, timeout-minutes, etc. au niveau workflow

Combinaison :

La meilleure pratique : combiner. Le workflow réutilisable appelle l’Action composite :

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

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

Configuration standard au niveau workflow, réutilisation des étapes au niveau Action.

Chapitre 5 : Gestion des versions et publication

5.1 Bonnes pratiques Git Tags

La publication repose sur les Git Tags. Stratégie recommandée : version sémantique + major tag :

# Tag de version sémantique
git tag -a v1.0.0 -m "Initial release"
git push origin v1.0.0

# Major tag (suit le dernier v1.x)
git tag -fa v1 -m "Update v1 tag to latest"
git push origin v1 --force

À la sortie de v1.1.0, mettre à jour le major tag :

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

# Mettre v1 sur la dernière version
git tag -fa v1 -m "Update v1 tag to v1.1.0"
git push origin v1 --force

Les utilisateurs peuvent :

  • Verrouiller avec @v1.1.0
  • Suivre les mises à jour v1.x avec @v1

5.2 Publication sur le Marketplace

Prérequis :

1. Préparer README.md

Le README doit inclure :

  • Nom et description de l’Action
  • Documentation inputs et outputs
  • Exemples d’utilisation
  • Licence

2. Préparer action.yml

Champs name, description, author, branding (optionnel) complets.

3. Créer une Release

Sur la page du dépôt GitHub :

  1. « Releases » → « Draft a new release »
  2. Choisir le tag (ex. v1.0.0)
  3. Rédiger les Release Notes
  4. Cocher « Publish this Action to the GitHub Marketplace »
  5. Publier

GitHub valide action.yml et publie sur le Marketplace.

5.3 Workflow de publication automatisée

Workflow possible pour automatiser :

name: Release Action

on:
  push:
    tags:
      - 'v*'

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

      - name: Update major tag
        run: |
          # Extraire le numéro major
          MAJOR=$(echo $GITHUB_REF | sed 's/refs\/tags\/v\([0-9]*\).*/\1/')
          
          # Mettre à jour le 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

Ce workflow met à jour le major tag et crée une Release à chaque push de tag.

Chapitre 6 : Techniques avancées et bonnes pratiques

6.1 Transmission sécurisée des secrets

Une Action composite ne peut pas accéder directement au contexte secrets. Transmission explicite obligatoire :

# Dans le 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 }}
# Dans 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 }}

Recommandations de sécurité :

  • Évitez les informations sensibles dans inputs (visibles dans les logs)
  • Préférez env pour les secrets (masqués)
  • Documentez dans le README quels secrets sont requis

6.2 Scripts locaux

La logique complexe n’a pas sa place dans le YAML. Placez des scripts dans le répertoire de l’Action :

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

Appel dans action.yml :

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

$GITHUB_ACTION_PATH est la racine de l’Action composite.

6.3 Dépôt d’Actions au niveau organisation

Pour une équipe, centralisez les Actions partagées :

your-org/shared-actions/
├── .github/
│   └── workflows/
│       └── test.yml       # Tester toutes les Actions
├── build/
│   ├── action.yml
│   └── README.md
├── deploy/
│   ├── action.yml
│   └── README.md
├── lint/
│   ├── action.yml
│   └── README.md
└── README.md

Chaque sous-répertoire est une Action indépendante, avec README et tests.

6.4 Pièges et débogage

Piège 1 : limite de profondeur d’imbrication

Une Action composite peut en appeler une autre, maximum 10 niveaux. Au-delà, erreur. Recommandation : pas plus de 3 — le débogage devient pénible.

Piège 2 : portée des variables d’environnement

Le env dans une Action composite ne vaut que pour l’étape concernée. Pour partager entre étapes, utilisez GITHUB_ENV :

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

Astuces de débogage :

  1. ACTIONS_STEP_DEBUG=true pour des logs détaillés
  2. echo dans les étapes pour afficher les variables
  3. Action tmate pour déboguer en SSH (déconseillé en production)

Conclusion

L’Action composite est l’outil central de modularisation GitHub Actions : fini la config dupliquée, encapsulez vos étapes CI comme des fonctions.

Trois points à retenir :

Structure claire : action.yml définit inputs/outputs/steps, comme une signature de fonction. Paramétrer rend l’Action flexible ; les sorties permettent à l’appelant de récupérer des résultats.

Bon choix : Action composite pour une fonction unique (build, test, déploiement) ; workflow réutilisable pour standardiser tout le pipeline. Combinez les deux.

Versions sûres : commit SHA en production ; major tag en interne. Évitez latest.

Prochaine étape : créez votre première Action composite, emballez vos étapes build-test répétées, puis publiez-la sur le Marketplace pour votre équipe ou la communauté.

Développer une Action composite GitHub Actions

Créer une Action composite réutilisable qui encapsule build et test

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Créer la structure de l'Action

    Créez le répertoire de l'Action composite dans le dépôt :

    • mkdir -p .github/actions/build-test
    • Créez le fichier action.yml
  2. 2

    Step 2: Rédiger action.yml

    Définissez inputs, outputs et étapes d'exécution :

    • inputs pour les paramètres (node-version, test-command)
    • outputs pour les sorties (build-path, coverage)
    • runs.steps doit toujours spécifier shell: bash
  3. 3

    Step 3: Tester en référence locale

    Référencez et testez dans un workflow :

    • uses: ./.github/actions/build-test
    • with: node-version: '20'
    • Publiez seulement après validation locale
  4. 4

    Step 4: Créer des Git Tags

    Version sémantique + 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: Publier sur le Marketplace

    Publication via l'interface GitHub :

    • Releases → Draft a new release
    • Choisissez le tag (ex. v1.0.0)
    • Cochez Publish to Marketplace
    • GitHub valide et publie automatiquement

FAQ

Quelle différence entre Action composite et workflow réutilisable ?
L'Action composite est un groupe d'étapes dans un job, sur le Runner de l'appelant ; les secrets doivent être passés explicitement. Le workflow réutilisable crée un job indépendant avec héritage automatique des secrets. Utilisez l'Action composite pour une fonction unique, le workflow réutilisable pour standardiser tout le pipeline.
Pourquoi les inputs d'une Action composite n'ont-ils pas de champ type ?
Les inputs d'une Action composite ne supportent que le type string. Contrairement aux workflows réutilisables, pas de boolean ou number. Pour un booléen, passez 'true' ou 'false' en chaîne et testez dans les étapes.
Comment transmettre des secrets dans une Action composite ?
L'Action composite ne peut pas accéder directement au contexte secrets — transmission explicite obligatoire. Via inputs (masqués dans les logs) ou via env (plus sûr, valeur non affichée dans les logs).
Référencer une Action par commit SHA ou par tag ?
En production, commit SHA (le plus sûr, immuable). En interne, major tag (ex. @v1, suit la dernière version). Évitez @latest — risque de mise à jour involontaire cassant le build.
Quelle profondeur d'imbrication maximale pour une Action composite ?
Une Action composite peut en appeler une autre, jusqu'à 10 niveaux. Recommandation : ne pas dépasser 3 — trop profond, le débogage devient difficile.
Faut-il toujours spécifier shell dans une Action composite ?
Oui. Chaque commande run doit avoir shell: bash (ou sh, pwsh). Obligatoire pour les Actions composites ; les workflows ordinaires peuvent l'omettre.

10 min de lecture · Publié le: 6 mai 2026 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog