MCPcopy Index your code
hub / github.com/rhysd/actionlint

github.com/rhysd/actionlint @v1.7.12 sqlite

repository ↗ · DeepWiki ↗ · release v1.7.12 ↗
1,111 symbols 4,137 edges 130 files 466 documented · 42% 6 cross-repo links
README

actionlint

CI Status API Document

actionlint is a static checker for GitHub Actions workflow files. Try it online!

Features:

  • Syntax check for workflow files to check unexpected or missing keys following workflow syntax
  • Strong type check for ${{ }} expressions to catch several semantic errors like access to not existing property, type mismatches, ...
  • Actions usage check to check that inputs at with: and outputs in steps.{id}.outputs are correct
  • Reusable workflow check to check inputs/outputs/secrets of reusable workflows and workflow calls
  • shellcheck and pyflakes integrations for scripts at run:
  • Security checks; script injection by untrusted inputs, hard-coded credentials
  • Other several useful checks; glob syntax validation, dependencies check for needs:, runner label validation, cron syntax validation, ...

See the full list of checks done by actionlint.

actionlint reports 7 errors

Example of broken workflow:

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 test

actionlint reports 7 errors:

test.yaml:3:5: unexpected key "branch" for "push" section. expected one of "branches", "branches-ignore", "paths", "paths-ignore", "tags", "tags-ignore", "types", "workflows" [syntax-check]
  |
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 [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", "ubuntu-slim", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "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", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file [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 [expression]
   |
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" [action]
   |
17 |           node_version: 18.x
   |           ^~~~~~~~~~~~~
test.yaml:21:20: property "platform" is not defined in object type {os: string} [expression]
   |
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]
   |
22 |         if: ${{ github.repository.permissions.admin == true }}
   |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Quick start

Install actionlint command by downloading the released binary or by Homebrew or by go install. See the installation document for more details like how to manage the command with several package managers or run via Docker container.

go install github.com/rhysd/actionlint/cmd/actionlint@latest

Basically all you need to do is run the actionlint command in your repository. actionlint automatically detects workflows and checks errors. actionlint focuses on finding out mistakes. It tries to catch errors as much as possible and make false positives as minimal as possible.

actionlint

Another option to try actionlint is the online playground. Your browser can run actionlint through WebAssembly.

See the usage document for more details.

Documents

  • Checks: Full list of all checks done by actionlint with example inputs, outputs, and playground links.
  • Installation: Installation instructions. Prebuilt binaries, a Docker image, building from source, a download script (for CI), supports by several package managers are available.
  • Usage: How to use actionlint command locally or on GitHub Actions, the online playground, an official Docker image, and integrations with reviewdog, Problem Matchers, super-linter, pre-commit, VS Code.
  • Configuration: How to configure actionlint behavior. Currently, the labels of self-hosted runners, the configuration variables, and ignore patterns of errors for each file paths can be set.
  • Go API: How to use actionlint as Go library.
  • References: Links to resources.

Bug reporting

When you see some bugs or false positives, it is helpful to file a new issue with a minimal example of input. Giving me some feedbacks like feature requests or ideas of additional checks is also welcome.

See the contribution guide for more details.

License

actionlint is distributed under the MIT license.

Extension points exported contracts — how you extend this code

ExprNode (Interface)
ExprNode is a node of expression syntax tree. To know the syntax, see https://docs.github.com/en/actions/learn-github-ac [13 …
expr_ast.go
Event (Interface)
Event interface represents workflow events in 'on' section [6 implementers]
ast.go
ExprType (Interface)
Types ExprType is interface for types of values in expression. [7 implementers]
expr_type.go
Pass (Interface)
Pass is an interface to traverse a workflow syntax tree [4 implementers]
pass.go
Rule (Interface)
Rule is an interface which all rule structs must meet. [1 implementers]
rule.go
ActionlintError (Interface)
(no doc)
playground/lib.d.ts
VisitExprNodeFunc (FuncType)
VisitExprNodeFunc is a visitor function for VisitExprNode(). The entering argument is set to true when it is called befo
expr_ast.go
Exec (Interface)
Exec is an interface how the step is executed. Step in workflow runs either an action or a script [5 implementers]
ast.go

Core symbols most depended-on inside this repo

Errorf
called by 273
rule.go
Error
called by 129
error.go
String
called by 127
ast.go
NewStrictObjectType
called by 106
expr_type.go
Contains
called by 82
scripts/generate-availability/main.go
NewObjectType
called by 55
expr_type.go
NewUntrustedInputMap
called by 53
expr_insecure.go
parseString
called by 53
parse.go

Shape

Method 508
Function 411
Struct 155
TypeAlias 23
Interface 9
Class 4
FuncType 1

Languages

Go97%
TypeScript3%

Modules by API surface

ast.go94 symbols
parse.go69 symbols
expr_type.go51 symbols
rule_expression.go46 symbols
expr_sema.go40 symbols
expr_ast.go36 symbols
expr_lexer.go34 symbols
reusable_workflow.go27 symbols
scripts/generate-popular-actions/main_test.go23 symbols
rule.go23 symbols
linter_test.go23 symbols
expr_insecure.go23 symbols

Dependencies from manifests, versioned

github.com/bmatcuk/doublestar/v4v4.10.0 · 1×
github.com/clipperhouse/uax29/v2v2.7.0 · 1×
github.com/mattn/go-colorablev0.1.14 · 1×
github.com/mattn/go-isattyv0.0.20 · 1×
github.com/mattn/go-runewidthv0.0.21 · 1×
github.com/mattn/go-shellwordsv1.0.12 · 1×
go.yaml.in/yaml/v4v4.0.0-rc.3 · 1×
golang.org/x/netv0.52.0 · 1×

For agents

$ claude mcp add actionlint \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact