Aller au contenu
CI/CD & Automatisation medium

Contexts et expressions GitHub Actions

39 min de lecture

Vous écrivez un workflow GitHub Actions et vous voulez savoir sur quelle branche le code s'exécute, qui a déclenché le pipeline, ou récupérer la valeur d'un secret. Comment faire ? C'est là qu'interviennent les contexts et les expressions.

Ce guide vous explique comment accéder à toutes ces informations dynamiquement, sans jamais coder en dur des valeurs qui changeraient selon le contexte d'exécution.

  • Lire les informations d'exécution d'un workflow via le context github
  • Faire circuler des données entre steps et entre jobs avec $GITHUB_OUTPUT, outputs et needs
  • Manipuler secrets et variables d'environnement sans les exposer dans les logs
  • Écrire des expressions : opérateurs, fonctions de statut, toJSON(), hashFiles()
  • Réutiliser des patterns prêts à l'emploi pour le déploiement conditionnel et le filtrage d'événements

Ce guide suppose que vous savez déjà ce qu'est un workflow. Sinon, commencez par le guide Workflows GitHub Actions.

Qu'est-ce qu'un context ? (l'essentiel à comprendre)

Section intitulée « Qu'est-ce qu'un context ? (l'essentiel à comprendre) »

Imaginez que votre workflow s'exécute dans une pièce. Dans cette pièce, il y a plusieurs boîtes étiquetées contenant des informations utiles :

  • La boîte github contient tout ce qui concerne le repository, la branche, l'auteur du commit, l'événement déclencheur...
  • La boîte secrets contient vos clés API et tokens sensibles
  • La boîte env contient vos variables d'environnement
  • La boîte matrix contient les valeurs de votre stratégie de test (si vous en utilisez une)
  • Et ainsi de suite...

Un context est simplement une de ces boîtes. Vous y accédez avec une syntaxe spéciale : ${{ nom_de_la_boite.ce_que_vous_cherchez }}.

Les contexts sont des boîtes d'informations accessibles depuis n'importe quel step de votre workflow

Voici un workflow minimal qui lit trois informations différentes depuis le context github et les affiche dans les logs d'exécution.

.github/workflows/exemple-context.yml
name: Mon premier workflow avec contexts
on: push
permissions:
contents: read # Permissions minimales
jobs:
afficher-infos:
runs-on: ubuntu-24.04
steps:
- name: Qui a déclenché ce workflow ?
run: |
echo "Déclenché par ${{ github.actor }}"
# Affiche : "Déclenché par stephane-robert"
- name: Sur quelle branche ?
run: |
echo "Branche : ${{ github.ref_name }}"
# Affiche : "Branche : main" (ou le nom de votre branche)
- name: Quel événement ?
run: |
echo "Événement : ${{ github.event_name }}"
# Affiche : "Événement : push"

Avant d'aller plus loin, comprenons la syntaxe. Une expression GitHub Actions suit toujours ce format :

Anatomie d'une expression : délimiteurs, context et propriété

ÉlémentRôle
${{ et }}Délimiteurs — indiquent à GitHub Actions qu'il doit évaluer ce qui est entre les deux
githubContext — la "boîte" dans laquelle chercher
.actorPropriété — la donnée spécifique à récupérer

Vous pouvez accéder à des propriétés imbriquées avec des points successifs :

# Propriété simple
${{ github.actor }}
# Propriété imbriquée (dans un événement pull_request)
${{ github.event.pull_request.title }}
# Propriété encore plus profonde
${{ github.event.pull_request.user.login }}

Voici tous les contexts que vous pouvez utiliser. Ne vous inquiétez pas, vous n'aurez pas besoin de tous les connaître par cœur — nous détaillerons les plus utiles juste après.

ContextCe qu'il contientQuand l'utiliser
githubRepository, branche, événement, auteurPresque partout — c'est le plus utilisé
envVariables d'environnementPasser des valeurs entre steps
varsVariables de configuration (repo/org)Configuration non sensible partagée
secretsSecrets (clés API, tokens)Authentification, déploiement
stepsRésultats des steps précédentsRécupérer un output d'un step
needsRésultats des jobs précédentsRécupérer un output d'un job
matrixValeurs de la matrix strategyTests multi-versions, multi-OS
jobInfos sur le job en coursRarement utilisé directement
runnerInfos sur la machine d'exécutionChemins, OS du runner
strategyConfiguration de la matrixRarement utilisé directement
inputsInputs des workflows réutilisablesWorkflows appelés par d'autres

C'est le context que vous utiliserez le plus souvent. Il contient toutes les informations sur :

  • Le repository (nom, propriétaire, URL)
  • L'événement qui a déclenché le workflow (push, pull_request, etc.)
  • La branche ou le tag concerné
  • L'utilisateur qui a déclenché l'exécution
  • L'exécution en cours (numéro, ID unique)

Propriétés courantes du context github organisées par catégorie

Le context github expose des dizaines de propriétés. Voici celles que vous manipulerez au quotidien, regroupées par thème dans les onglets ci-dessous.

steps:
- name: Informations sur le repo et le code
run: |
echo "Repository : ${{ github.repository }}"
# → "stephane-robert/mon-projet"
echo "Propriétaire : ${{ github.repository_owner }}"
# → "stephane-robert"
echo "Branche : ${{ github.ref_name }}"
# → "main" ou "feature/ma-branche"
echo "Ref complète : ${{ github.ref }}"
# → "refs/heads/main" ou "refs/tags/v1.0.0"
echo "Commit SHA : ${{ github.sha }}"
# → "a1b2c3d4e5f6..." (40 caractères)

Un cas d'usage très courant est de tagger vos images Docker avec le SHA du commit pour garantir la traçabilité :

.github/workflows/build-docker.yml
name: Build Docker
on:
push:
branches: [main]
permissions:
contents: read # Lecture du code uniquement
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build et push
run: |
# Tag avec SHA court pour la traçabilité.
# GitHub Actions n'a pas de fonction de découpe : on tronque
# la variable shell GITHUB_SHA à 7 caractères.
IMAGE_TAG="${{ github.repository }}:${GITHUB_SHA::7}"
echo "Construction de $IMAGE_TAG"
docker build -t $IMAGE_TAG .
docker push $IMAGE_TAG

Le context github.event contient le payload JSON complet de l'événement webhook. Sa structure dépend du type d'événement :

steps:
# Afficher tout l'événement (utile pour le debug)
- name: Debug - Voir l'événement complet
run: echo '${{ toJSON(github.event) }}'
# Pour un push : accéder aux commits
- name: Liste des commits (sur un push)
run: echo '${{ toJSON(github.event.commits) }}'
# Pour une release : récupérer le tag
- name: Tag de release
if: github.event_name == 'release'
run: echo "Release ${{ github.event.release.tag_name }}"

Les variables d'environnement permettent de stocker des valeurs réutilisables dans votre workflow. Elles peuvent être définies à trois niveaux différents, du plus global au plus local :

Les 3 niveaux de variables d'environnement
env:
NIVEAU_WORKFLOW: "accessible partout" # ① Niveau workflow
jobs:
build:
runs-on: ubuntu-24.04
env:
NIVEAU_JOB: "accessible dans ce job" # ② Niveau job
steps:
- name: Premier step
env:
NIVEAU_STEP: "accessible dans ce step uniquement" # ③ Niveau step
run: |
# Les 3 sont accessibles ici
echo "Workflow: ${{ env.NIVEAU_WORKFLOW }}"
echo "Job: ${{ env.NIVEAU_JOB }}"
echo "Step: ${{ env.NIVEAU_STEP }}"
- name: Deuxième step
run: |
# Seuls workflow et job sont accessibles
echo "Workflow: ${{ env.NIVEAU_WORKFLOW }}"
echo "Job: ${{ env.NIVEAU_JOB }}"
# NIVEAU_STEP n'existe pas ici !

Vous pouvez accéder aux variables d'environnement de deux façons :

SyntaxeQuand l'utiliser
${{ env.MA_VAR }}Dans les paramètres YAML (with, if, etc.)
$MA_VAR ou ${MA_VAR}Dans les scripts shell (run)
steps:
- name: Exemple des deux syntaxes
env:
VERSION: "1.2.3"
run: |
# Syntaxe shell (recommandée dans run:)
echo "Version: $VERSION"
# Syntaxe expression (fonctionne aussi)
echo "Version: ${{ env.VERSION }}"

Parfois, vous voulez calculer une valeur dans un step et la réutiliser plus tard. C'est possible grâce au fichier spécial $GITHUB_OUTPUT :

Passer des valeurs entre steps
steps:
- name: Calculer la version
id: version # L'ID est obligatoire pour référencer ce step
run: |
# Lire la version depuis un fichier
VERSION=$(cat VERSION)
echo "Version trouvée: $VERSION"
# Écrire dans GITHUB_OUTPUT pour que les autres steps puissent lire
echo "value=$VERSION" >> $GITHUB_OUTPUT
# Vous pouvez écrire plusieurs valeurs
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Utiliser les valeurs calculées
run: |
echo "Version: ${{ steps.version.outputs.value }}"
echo "SHA court: ${{ steps.version.outputs.sha_short }}"

Exemple pratique : version sémantique automatique

Section intitulée « Exemple pratique : version sémantique automatique »

Cet exemple combine un id:, le fichier $GITHUB_OUTPUT et le bloc outputs: du job pour calculer une version à partir du dépôt Git et la transmettre aux jobs suivants.

Calcul automatique de version
permissions:
contents: read
jobs:
version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.calc.outputs.version }} # Exposer pour d'autres jobs
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0 # Nécessaire pour compter les commits
- name: Calculer la version
id: calc
run: |
# Version = tag + nombre de commits depuis
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
COMMITS_SINCE=$(git rev-list ${LATEST_TAG}..HEAD --count)
VERSION="${LATEST_TAG}-${COMMITS_SINCE}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Version calculée: $VERSION"
build:
needs: version
runs-on: ubuntu-24.04
steps:
- name: Build avec la version
run: |
echo "Construction de la version ${{ needs.version.outputs.version }}"

Les secrets stockent vos informations sensibles : clés API, tokens, mots de passe. Ils sont chiffrés et jamais affichés dans les logs (GitHub les masque automatiquement avec ***).

La création d'un secret se fait dans l'interface GitHub du dépôt, en quatre étapes rapides.

  1. Allez dans SettingsSecrets and variablesActions
  2. Cliquez sur New repository secret
  3. Donnez un nom (ex: DOCKER_PASSWORD) et une valeur
  4. Le secret est maintenant utilisable via ${{ secrets.DOCKER_PASSWORD }}

La règle d'or : un secret transite par une variable d'environnement, jamais directement dans une commande où il resterait visible.

Bonne pratique : passer via env
steps:
- name: Se connecter à Docker Hub
env:
DOCKER_USER: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASS: ${{ secrets.DOCKER_PASSWORD }}
run: |
echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin

GitHub crée automatiquement un token pour chaque exécution de workflow. Ce token permet d'interagir avec le repository sans configurer de secret :

steps:
- name: Créer une release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create v1.0.0 --title "Version 1.0.0"

Le context matrix est utilisé avec la matrix strategy, qui permet d'exécuter le même job plusieurs fois avec des valeurs différentes. C'est idéal pour tester sur plusieurs OS ou versions.

Tester sur plusieurs versions de Node.js
permissions:
contents: read
jobs:
test:
strategy:
matrix:
node-version: [18, 20, 22] # 3 valeurs = 3 exécutions parallèles
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.node-version }} # Utilise la valeur de la matrix
- run: npm test

Ce workflow crée 3 jobs parallèles :

  • Un avec Node.js 18
  • Un avec Node.js 20
  • Un avec Node.js 22

Vous pouvez combiner plusieurs axes :

Tester sur plusieurs OS ET versions
permissions:
contents: read
jobs:
test:
strategy:
matrix:
os: [ubuntu-24.04, windows-2022, macos-14] # 3 OS différents
node: [18, 20]
# = 3 OS × 2 versions = 6 jobs parallèles !
runs-on: ${{ matrix.os }} # OS dynamique
steps:
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.node }}
- run: npm test

Parfois, vous voulez tester une configuration spéciale :

jobs:
test:
strategy:
matrix:
os: [ubuntu-24.04, windows-2022]
node: [18, 20]
include:
# Ajouter un cas spécial : Node 22 uniquement sur Ubuntu
- os: ubuntu-24.04
node: 22
experimental: true # Propriété personnalisée
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.node }}
- name: Test expérimental
if: matrix.experimental == true
run: echo "⚠️ Ceci est un build expérimental"
- run: npm test

Pour en savoir plus sur la matrix strategy, consultez le guide dédié : Matrix strategy

Ces deux contexts permettent de transmettre des données d'une partie du workflow à une autre. C'est essentiel pour créer des workflows où les jobs communiquent entre eux.

Flux des données entre jobs avec needs et entre steps avec steps

Quand vous voulez qu'un step utilise une valeur calculée par un step précédent dans le même job :

jobs:
build:
runs-on: ubuntu-24.04
steps:
- name: Générer un numéro de build
id: build-number # ID obligatoire
run: |
BUILD_NUM=$(date +%Y%m%d%H%M%S)
echo "number=$BUILD_NUM" >> $GITHUB_OUTPUT
- name: Utiliser le numéro
run: |
echo "Build #${{ steps.build-number.outputs.number }}"

Propriétés disponibles sur steps.<id> :

PropriétéDescription
outputs.<name>Valeurs écrites dans $GITHUB_OUTPUT
outcomeRésultat avant continue-on-error (success, failure)
conclusionRésultat final (success, failure, skipped)

Quand vous voulez qu'un job utilise une valeur calculée par un job précédent, c'est plus complexe car les jobs tournent sur des runners différents.

Étape 1 : Le job source doit déclarer ses outputs

jobs:
build:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.value }} # Exposer l'output
sha: ${{ steps.version.outputs.sha }}
steps:
- name: Calculer version
id: version
run: |
echo "value=1.2.3" >> $GITHUB_OUTPUT
echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT

Étape 2 : Le job consommateur utilise needs

deploy:
needs: build # Obligatoire pour accéder aux outputs
runs-on: ubuntu-24.04
steps:
- name: Déployer
run: |
echo "Déploiement version ${{ needs.build.outputs.version }}"
echo "Commit: ${{ needs.build.outputs.sha }}"
# Vérifier si le build a réussi
echo "Statut build: ${{ needs.build.result }}"

Cet exemple assemble tout ce qui précède : quatre jobs enchaînés par needs, avec passage d'outputs et une notification finale conditionnelle.

Workflow CI/CD complet
name: CI/CD
on:
push:
branches: [main]
permissions:
contents: read
packages: write # Pour pousser sur ghcr.io
jobs:
# ① Build et calcul de version
build:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.meta.outputs.version }}
image: ${{ steps.meta.outputs.image }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Métadonnées
id: meta
run: |
VERSION="1.0.${{ github.run_number }}"
IMAGE="ghcr.io/${{ github.repository }}:${VERSION}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "image=$IMAGE" >> $GITHUB_OUTPUT
- name: Build image
run: docker build -t ${{ steps.meta.outputs.image }} .
# ② Tests (dépend du build)
test:
needs: build
runs-on: ubuntu-24.04
steps:
- name: Tester l'image
run: |
echo "Test de ${{ needs.build.outputs.image }}"
# docker run ${{ needs.build.outputs.image }} npm test
# ③ Déploiement (dépend du build ET des tests)
deploy:
needs: [build, test]
runs-on: ubuntu-24.04
steps:
- name: Déployer
run: |
echo "✅ Build: ${{ needs.build.result }}"
echo "✅ Tests: ${{ needs.test.result }}"
echo "🚀 Déploiement de ${{ needs.build.outputs.image }}"
# ④ Notification (toujours, même si échec)
notify:
needs: [build, test, deploy]
if: always() # S'exécute même si un job a échoué
runs-on: ubuntu-24.04
steps:
- name: Notifier
run: |
if [ "${{ needs.deploy.result }}" == "success" ]; then
echo "🎉 Déploiement réussi !"
else
echo "❌ Échec - Build: ${{ needs.build.result }}, Tests: ${{ needs.test.result }}"
fi

Les expressions ne servent pas seulement à lire des valeurs. Vous pouvez aussi faire des comparaisons, des calculs logiques et utiliser des fonctions intégrées.

Les expressions acceptent les opérateurs habituels de comparaison et de logique, surtout utiles dans les conditions if:.

# Égalité
if: github.ref == 'refs/heads/main'
if: github.event_name != 'pull_request'
# Comparaison numérique
if: matrix.node >= 20
if: github.run_number > 100
# Opérateurs logiques
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
if: github.actor == 'dependabot[bot]' || github.actor == 'renovate[bot]'
# Négation (attention aux guillemets !)
if: "!contains(github.event.head_commit.message, '[skip ci]')"

GitHub Actions ne supporte pas directement condition ? valeur1 : valeur2. Mais vous pouvez simuler ce comportement avec && et || :

env:
# Si main → "production", sinon → "staging"
ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
# Si PR → numéro de PR, sinon → "N/A"
PR_NUMBER: ${{ github.event.pull_request.number || 'N/A' }}

Ces fonctions sont utilisées dans les conditions if: pour réagir au résultat des étapes précédentes :

FonctionQuand elle retourne true
success()Les étapes/jobs précédents ont réussi (par défaut)
failure()Au moins une étape/job précédent a échoué
always()Toujours (même si annulé ou échoué)
cancelled()Le workflow a été annulé
steps:
- name: Tests
run: npm test
- name: Notification d'échec
if: failure() # S'exécute seulement si npm test a échoué
run: echo "Les tests ont échoué !"
- name: Nettoyage
if: always() # S'exécute toujours, peu importe le résultat
run: rm -rf temp/

GitHub Actions fournit des fonctions intégrées pour tester le contenu d'une chaîne ou la formater dynamiquement.

# contains() - Recherche dans une chaîne ou un tableau
if: contains(github.event.head_commit.message, '[skip ci]')
if: contains(github.event.pull_request.labels.*.name, 'urgent')
# startsWith() / endsWith() - Vérifie le début ou la fin
if: startsWith(github.ref, 'refs/tags/') # C'est un tag
if: endsWith(github.repository, '-demo') # Repo de démo
# format() - Formater une chaîne
run: echo ${{ format('Bonjour {0} !', github.actor) }}
# → "Bonjour stephane-robert !"

Deux fonctions convertissent les données entre objets et texte JSON — indispensables pour le debug et pour manipuler des structures de données.

# toJSON() - Convertir en JSON (parfait pour le debug)
- name: Debug du context
run: echo '${{ toJSON(github) }}'
# fromJSON() - Parser du JSON
- name: Utiliser des données JSON
run: |
DATA='{"version": "1.2.3", "stable": true}'
echo "$DATA" > data.json
- name: Lire le JSON
id: data
run: echo "json=$(cat data.json)" >> $GITHUB_OUTPUT
- name: Utiliser
run: |
echo "Version: ${{ fromJSON(steps.data.outputs.json).version }}"

Cette fonction calcule un hash de fichiers. Elle est essentielle pour invalider les caches quand les dépendances changent :

- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.npm
# Le cache est invalidé si package-lock.json change
key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}

Voici les cas d'usage les plus fréquents. Copiez-collez et adaptez !

Le cas le plus fréquent : déclencher un déploiement différent selon la branche qui a reçu le commit.

Déploiement conditionnel
jobs:
deploy:
runs-on: ubuntu-24.04
steps:
- name: Déployer en staging
if: github.ref == 'refs/heads/develop'
run: ./deploy.sh staging
- name: Déployer en production
if: github.ref == 'refs/heads/main'
run: ./deploy.sh production
# Alternative avec variable d'environnement
- name: Déployer (version dynamique)
env:
TARGET: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
run: ./deploy.sh $TARGET

Cette condition évite de lancer un build quand le message de commit contient le marqueur [skip ci] — pratique pour les commits de documentation.

Skip CI dans le message de commit
jobs:
build:
# Ne s'exécute PAS si le message contient [skip ci]
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-24.04
steps:
- run: npm build

Pour ne pas relancer toute la CI à chaque mise à jour automatique de dépendances, filtrez les comptes des bots avec une condition sur github.actor.

Ignorer Dependabot et Renovate
jobs:
build:
# Ignore les PR créées par des bots de mise à jour
if: github.actor != 'dependabot[bot]' && github.actor != 'renovate[bot]'
runs-on: ubuntu-24.04
steps:
- run: npm test

Un même workflow peut réagir aux deux événements et réserver certaines étapes — publication, commentaire de PR — à l'un ou à l'autre.

Actions différentes selon l'événement
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build
run: npm run build
# Seulement sur push (merge dans main)
- name: Publier
if: github.event_name == 'push'
run: npm publish
# Seulement sur PR
- name: Commenter la PR
if: github.event_name == 'pull_request'
run: |
echo "Build réussi pour la PR #${{ github.event.pull_request.number }}"

La fonction failure() permet d'envoyer une alerte uniquement quand une étape précédente a échoué, sans polluer les exécutions réussies.

Alerter sur Slack si échec
jobs:
build:
runs-on: ubuntu-24.04
steps:
- name: Tests
run: npm test
- name: Notifier l'échec
if: failure()
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
run: |
curl -X POST "$SLACK_WEBHOOK" \
-H 'Content-type: application/json' \
-d '{
"text": "❌ Build échoué !",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Build échoué* sur `${{ github.repository }}`\n• Branche: `${{ github.ref_name }}`\n• Auteur: ${{ github.actor }}\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Voir les logs>"
}
}
]
}'

Le filtre paths ne déclenche le pipeline que si certains fichiers ont changé ; paths-ignore fait l'inverse. Les deux ne se combinent pas pour un même événement — choisissez l'un ou l'autre.

Build seulement si le code source change
on:
push:
paths:
- 'src/**'
- 'package.json'
jobs:
build:
runs-on: ubuntu-24.04
steps:
- run: npm build

Quand quelque chose ne fonctionne pas comme prévu, la première étape est de voir ce que contiennent réellement les contexts.

La fonction toJSON() sérialise un context entier — c'est le réflexe numéro un pour découvrir ce qui est réellement disponible à l'exécution.

Step de debug
steps:
- name: Debug - Voir tous les contexts
run: |
echo "=== GITHUB ===" && echo '${{ toJSON(github) }}'
echo ""
echo "=== ENV ===" && echo '${{ toJSON(env) }}'
echo ""
echo "=== JOB ===" && echo '${{ toJSON(job) }}'
echo ""
echo "=== RUNNER ===" && echo '${{ toJSON(runner) }}'

Vous pouvez activer un mode verbose en définissant des variables :

Mode debug complet
env:
ACTIONS_RUNNER_DEBUG: true # Logs détaillés du runner
ACTIONS_STEP_DEBUG: true # Logs détaillés des steps
jobs:
debug:
runs-on: ubuntu-24.04
steps:
- run: echo "Les logs seront plus détaillés"

Voici les pièges les plus fréquents rencontrés avec les contexts, leur cause et leur résolution.

SymptômeCause probableSolution
null ou videPropriété inexistanteVérifier le nom exact avec toJSON()
Erreur YAMLExpression commence par !Entourer de guillemets "!contains(...)"
Secret non trouvéNom incorrect ou pas de permissionsVérifier le nom exact dans Settings → Secrets
needs.job.outputs videPas de outputs: déclaréAjouter le bloc outputs: dans le job source
Step ID introuvablePas d'id: sur le stepAjouter id: mon-step
  1. Les contexts sont des boîtes d'informations

    Chaque context (github, env, secrets, matrix, needs, steps) contient des données accessibles via ${{ context.propriété }}.

  2. github est le context le plus utilisé

    Il contient tout sur le repository, l'événement déclencheur, la branche et l'utilisateur.

  3. Pour passer des données entre steps : $GITHUB_OUTPUT

    Écrivez echo "clé=valeur" >> $GITHUB_OUTPUT et lisez avec ${{ steps.<id>.outputs.clé }}.

  4. Pour passer des données entre jobs : outputs + needs

    Déclarez outputs: dans le job source, puis accédez via ${{ needs.<job>.outputs.<nom> }}.

  5. Les fonctions de statut contrôlent l'exécution

    success(), failure(), always() et cancelled() permettent de réagir aux résultats des étapes précédentes.

  6. Débuggez avec toJSON()

    En cas de doute, affichez le contenu complet d'un context avec echo '${{ toJSON(github) }}'.

Pour la référence exhaustive de chaque context et de chaque fonction, la documentation officielle GitHub reste l'ancrage à garder sous la main :

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn