Skip to content

Releases: jdx/jactionlint

v1.8.2: Maintenance release

Choose a tag to compare

@jdx jdx released this 05 Oct 03:12
Immutable release. Only release title and notes can be modified.
e330e2a

This release has no user-facing changes; it only fixes the release workflow.

Full Changelog: v1.8.1...v1.8.2

💚 Sponsor jactionlint

jactionlint is a fork of rhysd/actionlint, maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.

If jactionlint has a place in your development workflow, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep jactionlint fast, free, and independent.

v1.8.0: Renamed to jactionlint, with opt-in policy rules, parallel steps and inline ignore comments

Choose a tag to compare

@jdx jdx released this 05 Oct 02:59
Immutable release. Only release title and notes can be modified.
d62e090

This is the first release of jactionlint, jdx's fork of rhysd/actionlint. The project, binary and Go module are renamed. The release adds a set of opt-in policy checks, inline ignore comments, a user-wide config file, and support for new GitHub Actions syntax such as parallel steps, cache-mode and $/ self-repository references. It also imports fixes from open upstream pull requests.

Highlights

  • New name and distribution: the binary is now jactionlint. It is published from jdx/jactionlint, and the Docker image is at ghcr.io/jdx/jactionlint. Existing actionlint.yaml config files and # actionlint ignore= comments still work. See Breaking Changes.
  • Opt-in policy rules: you can enforce commit-hash pinning, explicit permissions:, job timeouts, explicit shells, script length limits, required actions, and more. Every one of these rules is off until you enable it in the config file.
  • Newer workflow syntax: parallel steps, cache-mode, $/path references, concurrency.queue, service container entrypoint/command, and new runner labels and permission scopes.

Added

Opt-in checks

All of these are off by default. Turn them on in .github/jactionlint.yaml:

require-commit-hash: true          # actions, reusable workflows and docker:// must be pinned to a full SHA / @sha256 digest
require-permissions: true          # every job needs workflow- or job-level permissions: ({} counts)
require-shell: true                # every run: step needs shell: or defaults.run.shell
max-run-lines: 50                  # limit non-blank lines in run: scripts (0 disables)
timeout-minutes:
  required: true                   # every job must set timeout-minutes
  max: 60                          # upper limit (works without required)
required-actions:
  - action: actions/checkout
    version: v4                    # optional; exact string match
self-hosted-runner:
  labels: [my-runner-*]
  strict-labels: true              # only listed labels are accepted, including built-in ones
check-workflow-run-names: true     # on.workflow_run.workflows must match a workflow in .github/workflows
require-checkout-before-local-action: true  # flag uses: ./path before any checkout step in the job
require-expression-wrapping: true  # if: conditions must be wrapped in ${{ }}
check-falsy-ternary: true          # flag cond && '' || other (and 0/false/null), which always yields other
  • require-commit-hash checks for a full 40-character SHA, or image@sha256:<64 hex> for Docker images. Local ./ and $/ references and dynamic uses: are skipped (#19).
  • required-actions matches action names case-insensitively. A requirement passes if any use in the workflow matches. Reusable workflow calls count. Composite action.yml files are not checked (#17).
  • require-checkout-before-local-action uses a loose definition of a checkout step: any action whose name contains checkout, or a git clone/fetch/checkout-style run: line (#29).
  • Related PRs: #32, #26, #24, #21, #30, #25. All by @jdx.

Configuration and suppression

  • Inline ignore comments. Put # jactionlint ignore=<regex>[,<regex>...] on its own line to suppress matching errors in the next line and everything nested under it, for example a whole step. You can stack several of these comments. An invalid regex is reported as an error. Trailing comments on the same line are not supported (#23 by @jdx).
  • User-wide config file. jactionlint now reads $XDG_CONFIG_HOME/jactionlint/jactionlint.yaml (or ~/.config/...), then the legacy actionlint/ directory, when the repository has no config file. Precedence is -config-file, then the repository config, then the user-wide config. Configs are not merged (#15 by @jdx).
  • config-secrets option. This allow-lists the names you can use as secrets.NAME, like config-variables does for variables. secrets.GITHUB_TOKEN is always allowed (#16 by @jdx).

Reusable workflow permission checks

  • When a local reusable workflow's jobs need token scopes the calling job doesn't grant, jactionlint now reports an error. GitHub rejects these calls with startup_failure. If the caller declares no permissions:, jactionlint assumes GitHub's restricted default token. If your org's default token is permissive, set assume-default-permissions: permissive (#13 by @jdx).

New workflow syntax

  • Parallel steps: background, wait, wait-all, cancel and parallel. A new parallel-steps rule checks that wait and cancel refer to earlier background steps, and that parallel groups contain only run/uses steps. Expressions in these keys are type-checked, and wait-all accepts a boolean (#12, #31 by @jdx).
  • cache-mode at workflow and job level (read, write, write-only, none), the $/path self-repository syntax in uses:, and the github.job_workflow_sha property (#11 by @jdx).
  • concurrency.queue, entrypoint and command on service containers, merge_group activity type destroyed, jobs.<job_id>.result in on.workflow_call.outputs, and the job.workflow_repository, job.workflow_ref, job.workflow_sha and job.workflow_file_path properties.
  • Permission scopes: code-quality, copilot-requests and vulnerability-alerts.
  • Runner labels: ubuntu-26.04, ubuntu-26.04-arm, xcode-27, xcode-27-xlarge and windows-11-vs2026-arm.

Security

  • The script injection check now flags more attacker-controlled fields when they are used directly in run:. These include committer name and email on head_commit and commits.*, pull_request.head.repo.description, and several workflow_run fields: display_title, head_branch, head_commit.message/author/committer, head_repository.owner.login, head_repository.description and pull_requests.*.head.ref. Existing workflows may get new errors (#11, #22 by @jdx).

Fixed

  • Shellcheck errors in run: | literal blocks now point at the line inside the script instead of the run: key. The column still points at run: (#18 by @jdx).
  • Expression errors inside literal blocks (run: |, script: |) now report the correct line and column, including for expressions that span several lines (#28 by @jdx).
  • Matrix exclude: values are now checked only against matrix: rows. GitHub applies include: after exclude:, so excluding a value that only include: adds has no effect. jactionlint now reports it, along with an exclude: that has no matrix rows (#20 by @jdx).
  • container.volumes was parsed as ports. Reusable workflow call jobs now reject services, config ignore: entries must be strings, and project and local reusable workflow paths are matched by directory instead of by string prefix (#11 by @jdx).
  • secrets.* is no longer reported as undefined in workflows that workflow_call and other events can both trigger.
  • Number literals with a + sign in the exponent, and integers too large for 32 bits, are now accepted. A matrix scalar tagged !!str is treated as a string.
  • Fixed a deadlock in the shellcheck integration on macOS.

Breaking Changes

The project was renamed from actionlint to jactionlint (#34, #36 by @jdx).

  • Binary: actionlint is now jactionlint. Install it with go install github.com/jdx/jactionlint/cmd/jactionlint@latest. Release archives are named jactionlint_<version>_<os>_<arch>, and the Homebrew cask is jactionlint.
  • Docker: the image moved from rhysd/actionlint on Docker Hub to ghcr.io/jdx/jactionlint.
  • pre-commit: hook ids are now jactionlint, jactionlint-docker and jactionlint-system.
  • Go library: the module path is github.com/jdx/jactionlint and the package name is jactionlint. NewExprSemanticsChecker takes an extra configSecrets parameter.
  • Config files: existing .github/actionlint.yaml/.yml files and # actionlint ignore= comments keep working. jactionlint looks for .github/jactionlint.yaml/.yml first. -init-config now writes .github/jactionlint.yaml.
  • Docker build: the ACTIONLINT_VER build argument is now JACTIONLINT_VER.

Full Changelog: 0ba78a0...v1.8.0

💚 Sponsor jactionlint

jactionlint is a fork of rhysd/actionlint, maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.

If jactionlint has a place in your development workflow, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep jactionlint fast, free, and independent.