Syntax check
Checks workflow files for unexpected or missing keys following the workflow syntax.
An actively maintained fork of rhysd/actionlint. Catch mistakes in your workflows before they run, with as few false positives as possible.
mise installs jactionlint from the GitHub releases of this repository.
mise use -g jactionlint
jactionlint --versionThen run it in your repository. jactionlint finds all workflow files and checks them.
jactionlintOther ways to install are described in the installation document. You can also try it in the online playground; your browser runs jactionlint through WebAssembly.
on:
push:
branch: main
tags:
- 'v\d+'
jobs:
test:
strategy:
matrix:
os: [macos-latest, linux-latest]
runs-on: ${{ matrix.os }}
steps:
- run: echo "Checking commit '${{ github.event.head_commit.message }}'"
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node_version: 18.x
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ matrix.platform }}-node-${{ hashFiles('**/package-lock.json') }}
if: ${{ github.repository.permissions.admin == true }}
- run: npm install && npm testtest.yaml:3:5: unexpected key "branch" for "push" section. expected one of "branches", "branches-ignore", "paths", "paths-ignore", "tags", "tags-ignore", "types", "workflows" [workflow-syntax]
|
3 | branch: main
| ^~~~~~~
test.yaml:5:11: character '\' is invalid for branch and tag names. only special characters [, ?, +, *, \, ! can be escaped with \. see `man git-check-ref-format` for more details. note that regular expression is unavailable. note: filter pattern syntax is explained at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet [invalid-glob]
|
5 | - 'v\d+'
| ^~~~
test.yaml:10:28: label "linux-latest" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2025-vs2026", windows-2022", "windows-11-arm", "windows-11-vs2026-arm", "ubuntu-slim", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-26.04", "ubuntu-26.04-arm", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xlarge", "macos-latest-large", "macos-26-intel", "macos-26-xlarge", "macos-26-large", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xlarge", "macos-14-large", "macos-14", "xcode-27", "xcode-27-xlarge", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in jactionlint.yaml config file [unknown-runner-label]
|
10 | os: [macos-latest, linux-latest]
| ^~~~~~~~~~~~~
test.yaml:13:41: "github.event.head_commit.message" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/reference/security/secure-use#good-practices-for-mitigating-script-injection-attacks for more details [template-injection]
|
13 | - run: echo "Checking commit '${{ github.event.head_commit.message }}'"
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.yaml:17:11: input "node_version" is not defined in action "actions/setup-node@v4". available inputs are "always-auth", "architecture", "cache", "cache-dependency-path", "check-latest", "node-version", "node-version-file", "registry-url", "scope", "token" [unknown-action-input]
|
17 | node_version: 18.x
| ^~~~~~~~~~~~~
test.yaml:21:20: property "platform" is not defined in object type {os: string} [undefined-property]
|
21 | key: ${{ matrix.platform }}-node-${{ hashFiles('**/package-lock.json') }}
| ^~~~~~~~~~~~~~~
test.yaml:22:17: receiver of object dereference "permissions" must be type of object but got "string" [expression-type]
|
22 | if: ${{ github.repository.permissions.admin == true }}
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~See the full list of checks, or learn how to use jactionlint locally and on GitHub Actions.