mrkeyoor.com_
Tue 01 Sept 17:42 UTC
Automationevaluationupdated 26 Aug 2026

actionlint review

actionlint is a static checker for GitHub Actions workflow YAML. It catches workflow syntax errors, invalid expressions, incorrect action inputs, dependency mistakes, unsafe script interpolation, and some embedded shell or Python problems before GitHub runs the workflow.

+15stars / 7d
Verdict

Our actionlint build took 17 seconds, but its 5-group test run ended 4 passed and 1 failed in the popular-actions generator. The core linter remains an easy recommendation for fast workflow feedback, provided you pin a release and treat new GitHub syntax as a possible false-positive source. Pair it with zizmor for deeper security rules and with an actual Actions run for behavior static analysis cannot prove.

We ran it

Lab card: what happened when we ran actionlintScreenshot of actionlint (rhysd.github.io/actionlint)
Install✓ · 9s18 packages
Build✓ · 17s
Tests✗ · 7s4 passed · 1 failed of 5 (go test)
Repo850 files~34,778 lines of source · 3.6 MB · 6 CI workflows · Dockerfile

Answers from our run

Does actionlint build from source?

Dependencies installed in 9 seconds (18 packages), and the build succeeded in 17 seconds. We cloned commit 011a6d1 into a clean Debian container with 3 CPUs and no project-specific setup.

Do actionlint's tests pass?

Not all of them: 4 of 5 passed and 1 failed when we ran the project's own test command (go test). Some failures need services or credentials a bare container does not have.

Who should not use actionlint?

Authors seeking to lint action.yml metadata for custom or composite actions: issue 46 has requested that separate file type since 2021.

What are the alternatives to actionlint?

zizmor, Super-Linter, act. Our actionlint build took 17 seconds, but its 5-group test run ended 4 passed and 1 failed in the popular-actions generator.

Setup5/5Single binary and 9-second dependency install in our sandbox
Docs5/5Checks, install, configuration, CI, editor, and API use are clear
Community3/54,172 stars and active PRs, but maintainer inactivity is questioned
Maturity4/5v1.7.12 is established; one generator test failed in our run

Who it’s for

Teams maintaining more than a handful of GitHub Actions workflows.
Repositories that want a fast local or CI check with editor-friendly diagnostics.
Developers who need type checking for expressions, matrices, reusable workflows, and action inputs.
Security reviewers looking for direct interpolation of untrusted event data into scripts.
Go applications that want to call the linter as a library.

Who it’s NOT for

Authors seeking to lint action.yml metadata for custom or composite actions: issue 46 has requested that separate file type since 2021.
Teams that need every new GitHub permission on day one: open issues cover copilot-requests, code-quality, and vulnerability-alerts.
Workflows using the destroyed activity for merge_group: issue 726 reports a false error because actionlint accepts only checks_requested.
Organizations that need an explicit missing-permissions warning: issue 728 requests a check GitHub itself already surfaces elsewhere.
Buyers requiring a passing full repository suite: our run failed TestDetectErrorBadRequest in a generator script.

Setup reality

Our sandbox installed 18 Go packages in 9 seconds. The build passed in 17 seconds. Tests failed after 7 seconds: 4 passed and 1 failed out of 5; TestDetectErrorBadRequest expected exit status 1 but received 0 in scripts/generate-popular-actions.

The released binary can run without credentials against local workflow files. ShellCheck and pyflakes are optional external integrations for embedded scripts, while action metadata checks may fetch remote action definitions depending on use. CI and editor integrations require their own configuration.

Prebuilt binaries, package managers, Docker, WebAssembly, and go install are documented. Custom runner labels and repository variables need an actionlint.yaml file. New GitHub Actions syntax can temporarily produce false positives until actionlint's bundled knowledge is updated.

actionlint checks workflow structure before GitHub runs it

actionlint reads files under .github/workflows and reports mistakes with file, line, column, source context, and a named rule. Its scope goes beyond YAML parsing. It understands GitHub's workflow keys, expression types, job dependencies, matrix values, runner labels, reusable workflow inputs, action inputs, glob patterns, and cron expressions. It also flags untrusted event values inserted directly into shell commands and hard-coded credentials.

That breadth makes it useful in an editor and in pull-request CI. A misspelled node-version input, undefined matrix property, invalid runner label, or wrong event key can be caught before a remote runner starts. ShellCheck and pyflakes can inspect embedded Bash and Python when those tools are installed. Diagnostics can be formatted for reviewdog and problem matchers, while the Go package is available to applications that want to embed checking.

The 17-second build was cleaner than the full test result

Our sandbox cloned commit 011a6d1 and installed 18 Go packages in 9 seconds. The build completed successfully in 17 seconds. The checkout contained 850 files, about 34,778 lines of source, and 3.6 MB before installation. This is a small local tool compared with the CI systems it checks, and the repository includes a Dockerfile plus 6 workflow files.

The package can also be installed as a release binary, through Homebrew and other package managers, with go install, or as a Docker image. An online WebAssembly playground provides a no-install trial. Normal local linting needs no GitHub token. Remote action metadata and surrounding CI integrations may add network or configuration requirements, so a locked-down environment should test the exact flags it plans to use.

What happened when we ran it

Our Go test command ended with exit code 1 after 7 seconds. The harness counted 4 passing groups and 1 failure out of 5. The failure was TestDetectErrorBadRequest under scripts/generate-popular-actions: the test expected exit status 1 and received 0. Other listed packages, including the main github.com/rhysd/actionlint package, passed in the supplied log.

The log does not say why that command returned 0, so we cannot label it a network problem or a product regression. It is still a failed complete suite at the measured commit. Our scan found no top-level tests directory, which is normal for Go packages that keep _test.go files beside source. These results come from an unprivileged Go 1.24 Debian container with 3 CPUs, 6 GB of RAM, and no secrets.

Workflow linting stops before action metadata

The tool checks how a workflow invokes an action, including whether with inputs and referenced outputs match known metadata. It does not lint the action's own action.yml or action.yaml definition. Issue 46 has asked for action metadata support since composite actions were new. Teams that build private JavaScript, Docker, or composite actions therefore need another schema check for those files.

Execution is another boundary. actionlint can reason about syntax and types, but it does not run containers, contact services, prove credentials work, or reproduce runner-specific behavior. nektos/act covers part of that local execution need, while a real GitHub Actions run remains the final environment check. Keeping these stages separate avoids treating a clean static result as proof that deployment permissions or external APIs are correct.

GitHub syntax can move faster than the bundled rules

GitHub adds events, runner labels, expression properties, and permission names over time. Issue 726 reports actionlint rejecting the destroyed activity for merge_group, even though GitHub documents it for the webhook. Open requests also cover the copilot-requests, code-quality, and vulnerability-alerts permission keys. A valid new workflow can therefore fail lint until the project updates its definitions.

The practical response is to pin actionlint, review a new diagnostic against current GitHub documentation, and use the narrowest ignore possible when the tool is behind. Broadly suppressing an entire file throws away the checks that still work. Custom self-hosted runner labels and repository variables belong in actionlint.yaml; without that project configuration, local names can look invalid even when GitHub accepts them.

Security checks are useful but not a full policy audit

One of actionlint's best rules detects potentially untrusted values, such as commit messages, embedded directly into an inline script. Moving the expression into an environment variable prevents the shell from parsing attacker-controlled text as code. Hard-coded credential detection adds another useful check, and ShellCheck can find mistakes inside the resulting script. These are concrete protections that fit naturally into every workflow change.

Issue 728 asks for a warning when a workflow omits a top-level permissions block. That check is not present today, so a clean actionlint run does not prove least privilege. Zizmor is the better companion when permissions, dangerous triggers, mutable action references, and other workflow security rules drive the review. Neither tool can decide whether a granted cloud role is too broad outside GitHub.

Community work continued after the July push

GitHub showed 4,172 stars, 187 combined issues and pull requests, and a last repository push on July 16, 2026. Release v1.7.12 was published on March 30. Issue and pull request activity continued through August 26, including new permissions, event types, dependency updates, runner labels, and popular-action data. The repository is not devoid of work, but merged source activity trails the incoming queue.

Issue 719 directly asks whether the author is inactive and whether an active fork exists. That short report is a community concern, not proof of abandonment. The sensible adoption plan is to pin v1.7.12, watch compatibility with GitHub's evolving syntax, and avoid depending on an unmerged feature. Even with that caveat, actionlint catches enough cheap mistakes to justify a place before every workflow commit.

Alternatives

ProjectWhat it isPick it when
zizmor gh↗A GitHub Actions static analyzer focused on security findings and audit rules.pick this instead when workflow security is the primary concern and broad syntax checking is secondary.
Super-LinterA containerized collection of linters for many source and configuration formats.pick this instead when one CI job should lint an entire polyglot repository, not only Actions workflows.
actA tool for running many GitHub Actions workflows locally in containers.pick this instead when you need execution behavior and integration feedback rather than static analysis alone.

What people are saying

  1. [github-trending] rhysd/actionlint

Sources

  1. actionlint README
  2. actionlint v1.7.12 release
  3. merge_group activity issue
  4. action metadata linting request
  5. missing permissions warning request
  6. maintainer activity discussion

More automation reviews

rclone · lego · OpenCLI · web-access · Karabiner-Elements · WiiUDownloader · the whole board →