🔴 Le workflow ne se déclenche pas
Le workflow existe mais rien ne se passe quand vous poussez du code.
Mise à jour :
Votre workflow CI échoue. Vous regardez les logs… et vous ne comprenez rien. Ou pire : le workflow ne se déclenche même pas, sans aucun message d’erreur. Comment savoir ce qui ne va pas ?
Ce guide vous donne les techniques de détective pour comprendre ce qui se passe dans vos workflows GitHub Actions et résoudre les problèmes efficacement.
Contrairement au code local que vous pouvez exécuter pas à pas avec un débogueur, les workflows GitHub Actions s’exécutent sur des machines distantes auxquelles vous n’avez pas accès direct.
Les défis spécifiques :
| Défi | Conséquence |
|---|---|
| Exécution distante | Pas de console.log en temps réel |
| Environnement éphémère | La VM disparaît après le run |
| Logs limités | Par défaut, seuls les messages standards sont visibles |
| Pas de breakpoints | Impossible de mettre le workflow en pause |
Avant de debugger, identifiez le type de problème :
🔴 Le workflow ne se déclenche pas
Le workflow existe mais rien ne se passe quand vous poussez du code.
🟠 Le workflow échoue
Le workflow démarre mais un ou plusieurs jobs échouent.
🟡 Le workflow est trop lent
Le workflow fonctionne mais prend beaucoup trop de temps.
Chaque type de problème nécessite une approche différente.
C’est souvent le plus frustrant : vous poussez du code, mais rien ne se passe dans l’onglet Actions.
Le workflow doit être dans .github/workflows/ et avoir l’extension .yml
ou .yaml.
# Vérifier la structurels -la .github/workflows/
# Vous devez voir vos fichiers de workflow# ci.yml deploy.yml etc.Erreur courante : le fichier est dans .github/workflow/ (sans le “s”)
ou dans un autre dossier.
Une erreur de syntaxe empêche GitHub de charger le workflow. Utilisez actionlint pour valider :
# Installer actionlintbrew install actionlint
# Valider tous les workflowsactionlint
# Valider un fichier spécifiqueactionlint .github/workflows/ci.ymlErreurs courantes :
# ❌ Mauvaise indentation (2 espaces attendus)jobs: build: # 1 espace au lieu de 2 runs-on: ubuntu-latest
# ❌ Guillemets manquants autour des caractères spéciauxon: push: branches: - feature/* # Le * doit être entre guillemets : "feature/*"
# ❌ Deux-points manquantjobs: build runs-on: ubuntu-latest # Erreur : "build" sans ":"Votre workflow peut être configuré pour ne réagir qu’à certains événements ou certaines branches.
# Ce workflow ne se déclenche que sur mainon: push: branches: - main # Si vous êtes sur develop, rien ne se passe !
# Ce workflow ne se déclenche que si des fichiers .py changenton: push: paths: - '**/*.py' # Un changement dans package.json est ignoréComment vérifier ?
on: de votre workflowpaths: et paths-ignore:Parfois le workflow est désactivé ou en attente d’approbation :
Certains événements ont des comportements particuliers :
| Événement | Piège courant |
|---|---|
pull_request | Ne se déclenche pas sur les PRs de forks (pour les secrets) |
pull_request_target | Se déclenche sur le repo cible, pas le fork |
schedule | Peut être retardé si GitHub est surchargé |
workflow_dispatch | Doit être déclenché manuellement via l’interface |
Le workflow démarre mais un step échoue. Voici comment trouver la cause.
Quand vous cliquez sur un run échoué, vous voyez une hiérarchie :
Run (ensemble du workflow)└── Job (ex: build, test, deploy) └── Step 1: Checkout code ✅ └── Step 2: Setup Node.js ✅ └── Step 3: Install dependencies ✅ └── Step 4: Run tests ❌ ← Le problème est ici └── Step 5: Upload coverage (skipped)Cliquez sur le step qui a échoué pour voir les détails.
Par défaut, GitHub n’affiche que les messages standards. Pour voir plus de détails, activez le mode debug.
Méthode 1 : Re-run avec debug
Méthode 2 : Variables d’environnement
Ajoutez ces variables à votre workflow :
name: CI
on: push
env: # Active les logs détaillés du runner (la machine qui exécute) ACTIONS_RUNNER_DEBUG: true # Active les logs détaillés de chaque step ACTIONS_STEP_DEBUG: true
jobs: build: runs-on: ubuntu-latest steps: # ...GitHub Actions reconnaît des commandes spéciales dans les logs. Utilisez-les pour créer des messages visibles :
- name: Diagnostic run: | # Message de debug (visible seulement en mode debug) echo "::debug::Variable PATH = $PATH"
# Notice (information visible dans les logs) echo "::notice::Compilation réussie en 45 secondes"
# Warning (triangle jaune dans l'interface) echo "::warning::La dépendance lodash est obsolète"
# Error (croix rouge, fait échouer le step) echo "::error::Fichier de configuration manquant"Résultat dans l’interface :
::debug:: → Visible uniquement avec ACTIONS_STEP_DEBUG: true::notice:: → Annotation bleue dans le résumé du run::warning:: → Annotation jaune, n’échoue pas le workflow::error:: → Annotation rouge, fait échouer le stepLes contexts (github, env, secrets, etc.) contiennent les informations
disponibles pendant l’exécution. Affichez-les pour comprendre l’état :
- name: Afficher le contexte GitHub run: | echo "Repository: ${{ github.repository }}" echo "Branche: ${{ github.ref }}" echo "Commit: ${{ github.sha }}" echo "Événement: ${{ github.event_name }}" echo "Acteur: ${{ github.actor }}"Pour tout voir d’un coup (utile en debug) :
- name: Dump tous les contexts env: # On passe par une variable pour éviter les problèmes d'échappement ALL_CONTEXTS: | github: ${{ toJSON(github) }} env: ${{ toJSON(env) }} job: ${{ toJSON(job) }} steps: ${{ toJSON(steps) }} run: echo "$ALL_CONTEXTS"Les secrets sont masqués dans les logs (remplacés par ***). Pour vérifier
qu’un secret est bien configuré sans l’exposer :
- name: Vérifier les secrets run: | if [ -n "${{ secrets.NPM_TOKEN }}" ]; then echo "✅ NPM_TOKEN est configuré" else echo "❌ NPM_TOKEN est vide ou non configuré" exit 1 fiQuand un test échoue, les fichiers de log sont perdus avec la VM. Configurez un upload automatique :
- name: Exécuter les tests run: npm test
- name: Sauvegarder les logs en cas d'échec if: failure() # Ne s'exécute que si le step précédent a échoué uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: debug-logs-${{ github.run_id }} path: | logs/ coverage/ npm-debug.log test-results/ retention-days: 5 # Garde les logs 5 joursLes artifacts sont téléchargeables depuis la page du run.
Parfois vous voulez voir ce qui se passe après une erreur :
- name: Step qui peut échouer id: risky-step run: ./script-instable.sh continue-on-error: true # Le workflow continue même si ce step échoue
- name: Analyser le résultat run: | echo "Résultat du step précédent: ${{ steps.risky-step.outcome }}" # outcome = 'success' ou 'failure'
if [ "${{ steps.risky-step.outcome }}" == "failure" ]; then echo "Le script a échoué, mais on continue pour collecter des infos" fiVotre workflow fonctionne, mais il prend 15 minutes au lieu de 3. Voici comment identifier les goulots d’étranglement.
GitHub affiche la durée de chaque step dans l’interface. Cliquez sur un job pour voir le détail :
✓ Checkout (2s)✓ Setup Node.js (5s)✓ Install dependencies (4m 30s) ← Suspect !✓ Run tests (1m 15s)✓ Build (45s)Dans cet exemple, l’installation des dépendances prend 4 minutes 30. C’est probablement un problème de cache.
Cherchez ces messages dans les logs :
# ✅ Cache utiliséCache restored from key: npm-linux-abc123def456
# ❌ Cache non trouvéCache not found for input keys: npm-linux-xyz789Si le cache n’est pas trouvé, vérifiez :
Voir le guide Artifacts vs Cache pour optimiser.
Pour les opérations longues, ajoutez des mesures :
- name: Début du timer run: echo "START_TIME=$(date +%s)" >> $GITHUB_ENV
- name: Opération longue run: npm ci
- name: Fin du timer run: | END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) echo "::notice::Installation des dépendances : ${DURATION} secondes"Les téléchargements lents sont une cause fréquente de lenteur :
- name: Diagnostic réseau run: | echo "=== Test DNS ===" time nslookup registry.npmjs.org
echo "=== Test de téléchargement ===" time curl -s -o /dev/null -w "Temps: %{time_total}s\n" https://registry.npmjs.orgPour éviter les workflows qui tournent indéfiniment :
jobs: build: runs-on: ubuntu-latest timeout-minutes: 30 # Le job entier ne peut pas dépasser 30 min
steps: - name: Opération risquée timeout-minutes: 5 # Ce step spécifique ne peut pas dépasser 5 min run: ./script-potentiellement-long.shError: Resource not accessible by integrationCe que ça signifie : Le workflow n’a pas la permission de faire ce qu’il essaie de faire (commenter une PR, créer un label, etc.).
Solution : Ajouter les permissions nécessaires :
permissions: contents: read # Lire le code pull-requests: write # Commenter les PRs issues: write # Créer/modifier les issuesCe que ça signifie : Similaire au précédent, mais au niveau du repository.
Solution :
Ce que ça signifie : Erreur de syntaxe YAML.
Solution : Utilisez actionlint pour trouver l’erreur exacte.
Ce que ça signifie : Vous essayez d’accéder à une propriété qui n’existe peut-être pas.
# ❌ Risqué si le step n'a pas d'outputs- run: echo ${{ steps.build.outputs.version }}
# ✅ Plus sûr avec une valeur par défaut- run: echo ${{ steps.build.outputs.version || 'unknown' }}Voici un workflow complet à déclencher manuellement pour diagnostiquer votre environnement :
name: Diagnostic
on: workflow_dispatch: # Déclenchement manuel uniquement
permissions: contents: read
jobs: diagnostic: runs-on: ubuntu-latest
steps: - name: Informations système run: | echo "=== Système d'exploitation ===" uname -a cat /etc/os-release
echo "=== Ressources ===" echo "CPU: $(nproc) cores" free -h df -h
echo "=== Outils installés ===" echo "Node: $(node --version 2>/dev/null || echo 'non installé')" echo "Python: $(python3 --version 2>/dev/null || echo 'non installé')" echo "Docker: $(docker --version 2>/dev/null || echo 'non installé')" echo "Git: $(git --version)"
- name: Contexte GitHub Actions run: | echo "Repository: ${{ github.repository }}" echo "Branche/Tag: ${{ github.ref }}" echo "Commit SHA: ${{ github.sha }}" echo "Acteur: ${{ github.actor }}" echo "Événement: ${{ github.event_name }}" echo "Run ID: ${{ github.run_id }}" echo "Run Number: ${{ github.run_number }}"
- name: Test réseau run: | echo "=== DNS ===" nslookup github.com
echo "=== Connectivité ===" curl -s -o /dev/null -w "GitHub API: %{http_code}\n" https://api.github.com curl -s -o /dev/null -w "npm Registry: %{http_code}\n" https://registry.npmjs.org curl -s -o /dev/null -w "PyPI: %{http_code}\n" https://pypi.org
- name: Variables d'environnement run: | echo "=== Variables GitHub ===" env | grep GITHUB_ | sort
echo "=== PATH ===" echo $PATH | tr ':' '\n'Pour l’exécuter : Actions → Diagnostic → Run workflow.
Plutôt que de pousser et attendre à chaque modification, utilisez act pour exécuter vos workflows sur votre machine.
# Installer actbrew install act
# Exécuter le workflow par défautact
# Exécuter un job spécifiqueact -j build
# Mode verbeux pour le debugact -vVoir le guide complet act.
Valider la syntaxe
Utilisez actionlint avant de pousser pour éviter les erreurs évidentes.
Activer le debug
Les variables ACTIONS_RUNNER_DEBUG et ACTIONS_STEP_DEBUG révèlent les détails cachés.
Sauvegarder les artifacts
Utilisez if: failure() pour uploader les logs quand ça échoue.
Tester localement
act vous fait gagner du temps en évitant les allers-retours avec GitHub.
Checklist de debug :
.github/workflows/on:, branches:, paths:)