Vous avez passé une heure à écrire un workflow GitHub Actions. Vous le poussez, et… échec immédiat. Une erreur de syntaxe. Un nom d'action mal orthographié. Une référence à un secret qui n'existe pas. Ces erreurs auraient pu être détectées avant le push.
actionlint est un linter statique qui analyse vos fichiers de workflow et détecte les erreurs avant qu'elles ne se produisent sur GitHub.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Installer actionlint sur Linux, macOS et Windows
- Valider vos workflows et interpréter les messages d'erreur
- Intégrer actionlint à VS Code et à un hook pre-commit
- Ajouter un workflow de lint qui valide les pull requests
- Configurer les règles et les variables propres à votre organisation
Qu'est-ce que actionlint ?
Section intitulée « Qu'est-ce que actionlint ? »actionlint est un outil en ligne de commande qui analyse statiquement vos workflows GitHub Actions. Il vérifie la syntaxe YAML, les références aux actions, les expressions, les permissions, et bien plus, le tout sans exécuter le workflow.
Concrètement, actionlint détecte :
- Les erreurs de syntaxe YAML (indentation, structure)
- Les propriétés inconnues ou mal orthographiées, y compris les entrées
with:invalides des actions populaires - Les références invalides à des contextes (
${{ github.sha }}) - Les actions inexistantes ou mal référencées
- Les permissions déclarées avec un scope ou une valeur inconnus
- Les problèmes de type dans les expressions
- Les patterns glob invalides
- Et beaucoup d'autres catégories, dont l'injection de script et les identifiants codés en dur
Pourquoi utiliser actionlint ?
Section intitulée « Pourquoi utiliser actionlint ? »Le tableau ci-dessous oppose la boucle de correction habituelle à celle qu'apporte actionlint. La ligne qui pèse le plus est la deuxième : sans linter, chaque coquille dans un workflow coûte un aller-retour complet avec le runner GitHub, plusieurs dizaines de secondes au mieux, et ce cycle se répète tant que l'erreur n'est pas trouvée. actionlint ramène cette boucle à une validation locale en moins d'une seconde, avant même le commit.
| Sans actionlint | Avec actionlint |
|---|---|
| Erreur découverte après le push | Erreur détectée avant le commit |
| Attente du runner (30s à plusieurs min) | Validation instantanée (< 1s) |
| Historique pollué de runs échoués | Runs plus propres |
| Debug par essai-erreur | Messages d'erreur clairs et précis |
Installation
Section intitulée « Installation »Avec Homebrew :
brew install actionlintAvec Homebrew :
brew install actionlintDepuis les releases GitHub, avec vérification de l'empreinte. Le projet publie
un fichier checksums.txt pour chaque version ; on télécharge l'archive et
ce fichier, puis on refuse d'extraire tant que sha256sum --check ne répond pas
OK :
ACTIONLINT_VERSION=1.7.12BASE="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}"curl -sSLO "${BASE}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"curl -sSLO "${BASE}/actionlint_${ACTIONLINT_VERSION}_checksums.txt"sha256sum --ignore-missing --check "actionlint_${ACTIONLINT_VERSION}_checksums.txt"tar -xzf "actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" actionlintsudo install -m 0755 actionlint /usr/local/bin/actionlintAvec Go :
go install github.com/rhysd/actionlint/cmd/actionlint@latestAvec Chocolatey :
choco install actionlintAvec Scoop :
scoop install actionlintVérification de l'installation :
actionlint --versionLa première ligne affiche la version installée (ex: 1.7.12), suivie de deux lignes sur la méthode d'installation et le compilateur Go utilisé.
Utilisation de base
Section intitulée « Utilisation de base »Valider tous les workflows
Section intitulée « Valider tous les workflows »À la racine de votre projet :
actionlintactionlint trouve automatiquement les fichiers dans .github/workflows/ et
les analyse tous.
Exemple de sortie : chaque erreur affiche le fichier, la ligne, la colonne,
puis la catégorie entre crochets ([action], [expression], etc.). C'est la
catégorie qui vous dit à quelle règle vous avez affaire :
.github/workflows/ci.yml:11:11: input "node-verion" is not defined in action "actions/setup-node@v4". available inputs are "always-auth", "architecture", "cache", ..., "node-version", ... [action] |11 | node-verion: 20 | ^~~~~~~~~~~~Ici, actionlint reconnaît actions/setup-node, connaît ses entrées valides et
repère la faute de frappe node-verion au lieu de node-version. Sans ce
linter, l'erreur ne se manifesterait qu'à l'exécution sur GitHub.
Valider un workflow spécifique
Section intitulée « Valider un workflow spécifique »Passer un chemin en argument restreint l'analyse à ce seul fichier, ce qui est pratique quand vous travaillez sur un workflow précis dans un dépôt qui en compte plusieurs. actionlint attend toujours de trouver la racine du dépôt Git au-dessus du fichier, car il détecte le projet par le dossier .github/workflows/ : lancé hors d'un dépôt, il s'arrête avec no project was found.
actionlint .github/workflows/ci.ymlValider depuis stdin
Section intitulée « Valider depuis stdin »Utile pour les scripts ou les pipelines :
cat .github/workflows/ci.yml | actionlint -Comprendre les messages d'erreur
Section intitulée « Comprendre les messages d'erreur »actionlint fournit des messages précis avec le numéro de ligne, la colonne, et une explication. Voici les catégories principales :
Erreurs de syntaxe
Section intitulée « Erreurs de syntaxe ».github/workflows/ci.yml:1:1: "on" section is missing in workflow [syntax-check]Le workflow n'a pas de section on: qui définit quand il se déclenche.
Erreurs de propriété
Section intitulée « Erreurs de propriété ».github/workflows/ci.yml:11:11: input "node-verion" is not defined in action "actions/setup-node@v4" [action]Faute de frappe : node-verion au lieu de node-version. La catégorie [action] indique qu'actionlint a validé la clé with: contre la liste réelle des entrées de l'action.
Erreurs de runner
Section intitulée « Erreurs de runner ».github/workflows/ci.yml:5:14: label "123" is unknown. available labels are "windows-latest", ..., "ubuntu-24.04", ... [runner-label]La valeur de runs-on ne correspond à aucun label de runner connu. Un label personnalisé de runner self-hosted se déclare dans le fichier actionlint.yaml pour éviter ce faux positif.
Erreurs de sécurité
Section intitulée « Erreurs de sécurité ».github/workflows/ci.yml:7:24: "github.event.issue.title" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable [expression]actionlint détecte l'injection de script : une donnée contrôlable par un tiers (github.event.issue.title) interpolée directement dans un run:. La parade est de la passer par un bloc env:. La catégorie [credentials] couvre de son côté les mots de passe de conteneur écrits en clair. actionlint ne signale en revanche pas l'absence d'épinglage par SHA : voir Épinglage SHA et les scanners dédiés.
Erreurs d'expression
Section intitulée « Erreurs d'expression ».github/workflows/ci.yml:9:18: property "secret" is not defined in object type {action: string; ...} [expression]Le contexte github.secret n'existe pas (c'est secrets.X qu'il faut utiliser).
Options utiles
Section intitulée « Options utiles »Format de sortie
Section intitulée « Format de sortie »Le format par défaut est fait pour être lu par un humain dans le terminal. Les trois autres servent à brancher actionlint sur un autre outil : json pour un script qui parse les résultats, sarif pour remonter les alertes dans l'onglet Security de GitHub via Code Scanning, et le gabarit ::error pour que GitHub Actions surligne l'erreur directement dans l'interface du run. Choisissez le format selon le consommateur, pas selon votre préférence.
# Format par défaut (lisible)actionlint
# Format JSON (pour intégration CI)actionlint -format json
# Format SARIF (pour GitHub Code Scanning)actionlint -format sarif > results.sarif
# Format compatible avec les problèmes GitHub Actionsactionlint -format '{{range $err := .}}::error file={{$err.Filepath}},line={{$err.Line}},col={{$err.Column}}::{{$err.Message}}{{end}}'Ignorer certaines erreurs
Section intitulée « Ignorer certaines erreurs »Le drapeau -ignore prend une expression régulière comparée au message d'erreur, pas un identifiant de règle. C'est utile pour taire un avertissement shellcheck connu et assumé : les codes SC2086, SC2129 viennent de l'intégration shellcheck qui analyse vos blocs run:.
# Taire un avertissement shellcheck précis (mots non quotés)actionlint -ignore 'SC2086'
# En taire plusieursactionlint -ignore 'SC2086' -ignore 'SC2129'Vous pouvez aussi neutraliser une catégorie sur un bloc précis, avec un commentaire à l'intérieur du fichier de workflow :
# actionlint: ignore=expression- name: Step with ignored warning run: echo "${{ github.secret }}"Mode verbeux
Section intitulée « Mode verbeux »actionlint -verboseAffiche les fichiers analysés et le temps d'exécution.
Vérification des actions populaires, sans réseau
Section intitulée « Vérification des actions populaires, sans réseau »actionlint valide les entrées with: d'une centaine d'actions populaires
(actions/checkout, actions/setup-node, actions/cache, etc.) grâce à une
base de données embarquée dans le binaire au moment de sa compilation. Il
n'a donc jamais besoin d'accéder au réseau pour ces vérifications, ce qui le
rend utilisable hors ligne et dans un runner isolé. Cette base ne couvre que la
forme en version majeure (actions/checkout@v4) ; une version figée au patch
(@v4.0.1) ou le suivi de @main ne sont pas validés.
Intégration dans VS Code
Section intitulée « Intégration dans VS Code »actionlint s'intègre avec les éditeurs pour afficher les erreurs en temps réel.
Extension VS Code
Section intitulée « Extension VS Code »- Installez l'extension GitHub Actions de GitHub
- Elle utilise automatiquement actionlint s'il est installé
Ou utilisez l'extension dédiée actionlint :
- Ouvrez VS Code
- Extensions → Recherchez "actionlint"
- Installez l'extension
Les erreurs apparaissent directement dans l'éditeur avec des soulignements.
Configuration VS Code
Section intitulée « Configuration VS Code »Dans .vscode/settings.json :
{ "actionlint.executable": "/usr/local/bin/actionlint", "yaml.schemas": { "https://json.schemastore.org/github-workflow.json": ".github/workflows/*.yml" }}Intégration dans la CI
Section intitulée « Intégration dans la CI »Workflow de validation
Section intitulée « Workflow de validation »Créez un workflow qui valide vos autres workflows :
name: Lint Workflows
on: push: paths: - '.github/workflows/**' pull_request: paths: - '.github/workflows/**'
# Aucun droit par défaut : le job demande le minimumpermissions: {}
jobs: actionlint: runs-on: ubuntu-24.04 permissions: contents: read steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false
- name: Install actionlint env: ACTIONLINT_VERSION: 1.7.12 run: | BASE="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}" curl -sSLO "${BASE}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" curl -sSLO "${BASE}/actionlint_${ACTIONLINT_VERSION}_checksums.txt" sha256sum --ignore-missing --check "actionlint_${ACTIONLINT_VERSION}_checksums.txt" tar -xzf "actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" actionlint sudo install -m 0755 actionlint /usr/local/bin/actionlint
- name: Validate workflows run: actionlint -colorAvec l'action officielle
Section intitulée « Avec l'action officielle »name: Lint Workflows
on: pull_request: paths: - '.github/workflows/**'
# Aucun droit par défaut : le job demande le minimumpermissions: {}
jobs: actionlint: runs-on: ubuntu-24.04 permissions: contents: read pull-requests: write # Pour que reviewdog commente la PR steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false
- uses: reviewdog/action-actionlint@50842263c20a7c46bd0065b9e624d3c569db061e # v1.73.0 with: reporter: github-pr-reviewCette action utilise reviewdog pour commenter directement les PRs avec les erreurs détectées.
Hook pre-commit
Section intitulée « Hook pre-commit »Validez avant chaque commit avec pre-commit :
repos: - repo: https://github.com/rhysd/actionlint rev: v1.7.12 hooks: - id: actionlintPuis :
pip install pre-commitpre-commit installRègles de validation
Section intitulée « Règles de validation »actionlint vérifie de nombreuses règles. Le mot entre crochets à la fin de chaque message d'erreur est la catégorie de la règle déclenchée, et c'est cette catégorie que le drapeau -ignore ou le commentaire # actionlint: ignore= ciblent. Les tableaux ci-dessous regroupent les catégories les plus fréquentes par thème.
Syntaxe et structure
Section intitulée « Syntaxe et structure »Ce sont les erreurs qu'actionlint attrape en premier, avant même de comprendre la logique du workflow : un YAML mal indenté, une expression ${{ }} mal formée, ou une commande de workflow que GitHub a retirée. La catégorie deprecated-commands est utile lors des migrations, elle repère les vieux ::set-output:: que GitHub ne supporte plus.
| Catégorie | Description |
|---|---|
syntax-check | Erreurs YAML de base et clés manquantes |
expression | Expressions ${{ }} invalides ou types incompatibles |
deprecated-commands | Commandes de workflow obsolètes (set-output, save-state) |
Sécurité
Section intitulée « Sécurité »Ces trois catégories couvrent ce qu'actionlint sait détecter côté sécurité sans recouper les scanners de supply chain. L'injection de script n'a pas de catégorie propre : elle est reportée sous expression, avec un message explicite invitant à passer la donnée par env:. Rappel : l'épinglage par SHA n'en fait pas partie.
| Catégorie | Description |
|---|---|
permissions | Scope ou valeur de permissions: inconnus |
credentials | Mot de passe de conteneur écrit en clair |
expression | Donnée non fiable interpolée dans run: (injection de script) |
Actions et références
Section intitulée « Actions et références »actionlint connaît la structure attendue des événements et des dépendances entre jobs, ce qui lui permet de repérer un needs: qui pointe vers un job inexistant ou un nom d'événement mal orthographié. La catégorie action couvre les entrées with: invalides des actions populaires vues plus haut.
| Catégorie | Description |
|---|---|
action | Entrées with: invalides, action obsolète (runner trop ancien) |
events | Événements de déclenchement invalides |
job-needs | Dépendances needs: incorrectes |
Types et valeurs
Section intitulée « Types et valeurs »Ces catégories vérifient que les valeurs correspondent à ce que GitHub attend réellement : un label de runner qui existe, un motif glob valide dans un filtre paths:, une matrice bien formée. Le contrôle runner-label est celui qui déclenche le plus de faux positifs sur les runners self-hosted, d'où l'intérêt du fichier de configuration décrit plus bas.
| Catégorie | Description |
|---|---|
runner-label | Labels de runner inconnus |
glob | Patterns glob invalides dans paths: |
matrix | Erreurs dans la définition de matrice |
Combinaison avec act
Section intitulée « Combinaison avec act »Pour une validation complète de vos workflows :
- actionlint : validation statique (syntaxe, types, références)
- act : exécution locale (logique, scripts, comportement)
#!/usr/bin/env bash# Script de validation completset -euo pipefail
echo "Validation statique avec actionlint..."actionlint
echo "Test d'execution a blanc avec act..."act -n
echo "Workflows valides."Avec set -euo pipefail, le script s'arrête à la première commande qui échoue :
inutile de tester $? après chaque étape, un actionlint ou un act -n en
erreur interrompt tout et renvoie un code non nul à la CI.
Voir le guide act pour les tests d'exécution locale.
Configuration avancée
Section intitulée « Configuration avancée »Fichier de configuration
Section intitulée « Fichier de configuration »Créez un fichier .github/actionlint.yaml :
# Configuration actionlintself-hosted-runner: labels: - my-runner - gpu-runner
config-variables: - MY_ORG_VAR - DEPLOYMENT_ENV
paths: ignore: - '.github/workflows/deprecated-*.yml'Variables d'organisation
Section intitulée « Variables d'organisation »Si vous utilisez des variables au niveau organisation (${{ vars.ORG_VAR }}),
déclarez-les pour éviter les faux positifs :
config-variables: - ORG_CONFIG - COMPANY_NAMEDépannage
Section intitulée « Dépannage »"command not found: actionlint"
Section intitulée « "command not found: actionlint" »Symptôme : le terminal ne trouve pas la commande.
Solutions :
# Vérifier l'installationwhich actionlint
# Si installé via Go, ajouter au PATHexport PATH="$PATH:$(go env GOPATH)/bin"Faux positifs sur des actions personnalisées
Section intitulée « Faux positifs sur des actions personnalisées »Symptôme : actionlint signale des actions locales comme inexistantes.
Solution : les actions locales (./actions/my-action) sont validées si
elles existent dans le repo. Vérifiez le chemin.
"no project was found"
Section intitulée « "no project was found" »Symptôme : actionlint s'arrête avec no project was found in any parent directories.
Cause : actionlint cherche la racine d'un dépôt Git au-dessus des fichiers analysés. Lancé hors d'un dépôt (ou dans un dossier extrait sans .git), il ne trouve pas de projet.
Solution : lancez-le depuis la racine du dépôt, ou passez le workflow via stdin :
cat ci.yml | actionlint -Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »Validation instantanée
Détectez les erreurs en moins d'une seconde, avant le push.
50+ règles
Syntaxe, sécurité, types, références, tout est vérifié.
Intégration IDE
Erreurs affichées directement dans VS Code pendant l'écriture.
CI/CD ready
Formats JSON, SARIF, et intégration reviewdog pour les PRs.
Points clés :
- Installez actionlint et utilisez-le avant chaque push
- Intégrez-le dans VS Code pour une validation en temps réel
- Ajoutez un workflow de lint pour valider les PRs automatiquement
- Combinez avec act pour une validation complète
- Configurez les règles et variables spécifiques à votre organisation
Le dépôt actionlint documente toutes les règles, et le playground en ligne permet de tester un workflow dans le navigateur.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- pre-commit : Le cadre qui déclenche actionlint et les autres linters à chaque commit, sur tout le dépôt et pas seulement sur les workflows.
- MegaLinter : L'agrégateur qui étend la même logique de lint aux 100 langages du dépôt, là où actionlint s'arrête au YAML de GitHub Actions.
- OpenSSF Scorecard : La note de posture qui mesure ce qu'un linter ne voit pas, de la protection de branche à la signature des releases.