actionlint
Catches broken workflow YAML before a push burns a CI minute proving it.
Homebrew formula Direct download
What it does
actionlint type-checks workflow files: unknown runs-on labels, invalid ${{ }} expressions and undefined contexts, misspelled event names, needs: referring to nonexistent jobs, action inputs that do not exist, and shell scripts inside run: blocks (it shells out to ShellCheck and pyflakes when present).
actionlint # every workflow in the repo
actionlint .github/workflows/pages.ymlWhy linting workflows is not optional
Workflow files fail in ways that do not look like failures. A required status check on a protected branch is matched by job name, so renaming a job silently detaches the protection rule rather than erroring. A typo in an if: expression evaluates to false and skips a step quietly. Neither shows up until something that should have been blocked goes through.
Alternative to
| Alternative | Type | Trade-off |
|---|---|---|
| zizmor | Open source | Audits the same files for security problems rather than correctness |
| yamllint | Open source | Catches malformed YAML, but knows nothing about Actions schemas |
| GitHub’s web editor | — | Validates as you type, but only one file at a time |
Install
brew install actionlint