Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,29 @@ jobs:
}
- name: Test action image
run: ./scripts/test-action.bash actionlint-action:test
action-cli:
name: CLI action on a daemon-less runner
runs-on: ubuntu-slim
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with: { persist-credentials: false }
# The published actionlint the action installs is older than this branch,
# so linting the repository itself would report syntax this release does
# not know yet. A fixture keeps the job about the action.
- name: Write a fixture workflow
run: |
mkdir -p "${RUNNER_TEMP}/fixture"
cat > "${RUNNER_TEMP}/fixture/smoke.yaml" <<'FIXTURE'
on: push
jobs:
smoke:
runs-on: ubuntu-latest
steps:
- run: echo hello
FIXTURE
- uses: $/action/cli
with: { pyflakes: "false", flags: "${{ runner.temp }}/fixture/smoke.yaml" }

pre-commit-shellcheck:
name: pre-commit ShellCheck integration
runs-on: ubuntu-latest
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/matcher.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ jobs:
run: make ./scripts/generate-actionlint-matcher/testdata/* SKIP_GO_GENERATE=true
- name: Test actionlint-matcher.json
run: npm run test:matcher
- name: Ensure .github/actionlint-matcher.json is up-to-date
- name: Ensure the generated matcher files are up-to-date
run: |
make .github/actionlint-matcher.json
make matcher
if git diff --quiet; then
echo 'OK'
else
echo 'ERROR! .github/actionlint-matcher.json is outdated. Update it by "make .github/actionlint-matcher.json"' >&2
echo 'ERROR! A generated actionlint-matcher.json is outdated. Update both by "make matcher"' >&2
set -x
git diff
exit 1
Expand Down
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,10 @@ man: man/actionlint.1 man/actionlint.1.html
bench:
go test -bench Lint -benchmem

.github/actionlint-matcher.json: scripts/generate-actionlint-matcher/object.mjs
node ./scripts/generate-actionlint-matcher/main.mjs .github/actionlint-matcher.json
.github/actionlint-matcher.json action/cli/actionlint-matcher.json: scripts/generate-actionlint-matcher/object.mjs
node ./scripts/generate-actionlint-matcher/main.mjs $@

matcher: .github/actionlint-matcher.json action/cli/actionlint-matcher.json

scripts/generate-actionlint-matcher/testdata/escape.txt: $(TARGET)
./actionlint -color ./testdata/err/one_error.yaml > ./scripts/generate-actionlint-matcher/testdata/escape.txt || true
Expand All @@ -126,4 +128,4 @@ CHANGELOG.md:
c clean:
rm -f ./$(TARGET) ./man/actionlint.1 ./man/actionlint.1.html ./actionlint-workflow-ast

.PHONY: all test clean build lint fuzz man bench cov b t c l CHANGELOG.md FORCE
.PHONY: all test clean build lint fuzz man matcher bench cov b t c l CHANGELOG.md FORCE
20 changes: 5 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,25 +135,15 @@ jobs:
- uses: kjanat/actionlint@v1
```

On a daemon-less runner such as `ubuntu-slim`, download and run the binary instead:
On a daemon-less runner such as `ubuntu-slim`, use the CLI action instead. It installs actionlint with [mise](https://mise.jdx.dev) and registers the problem matcher, so errors still show up as annotations:

```yaml
- uses: actions/checkout@v7
with: { persist-credentials: false }
- name: Download and run actionlint
env: { GH_TOKEN: "${{ github.token }}", GH_REPO: "kjanat/actionlint" }
run: |
case "${RUNNER_ARCH}" in
X64) asset_arch=amd64 ;;
ARM64) asset_arch=arm64 ;;
ARM) asset_arch=armv6 ;;
X86) asset_arch=386 ;;
*) echo "Unsupported runner architecture: ${RUNNER_ARCH}" >&2; exit 1 ;;
esac
gh release download --pattern "actionlint_*_${RUNNER_OS,,}_${asset_arch}.tar.gz" --output - | tar -xzf - actionlint
./actionlint -color
- { uses: actions/checkout@v7, with: { persist-credentials: false } }
- uses: kjanat/actionlint/action/cli@v1
```

ShellCheck and pyflakes are installed alongside actionlint unless you set `shellcheck: "false"` and `pyflakes: "false"`.

The moving `v1` tag follows compatible v1 releases. `v1.13.0` is a versioned release tag, but only a full-length commit SHA provides an immutable action reference.

<details><summary><h3>Inputs</h3></summary>
Expand Down
60 changes: 60 additions & 0 deletions action/cli/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# yaml-language-server: $schema=https://www.schemastore.org/github-action.json
---
name: actionlint CLI by @kjanat
description: >-
Run actionlint on GitHub Actions workflow files and report problems as
annotations. Installs actionlint with mise, so no Docker daemon is needed.
inputs:
version:
description: >-
actionlint release to install, for example 1.13.0. "latest" takes the
newest release.
required: false
default: latest
shellcheck:
description: >-
Install ShellCheck so actionlint checks shell scripts in "run" steps.
required: false
default: "true"
pyflakes:
description: >-
Install pyflakes so actionlint checks Python scripts in "run" steps.
required: false
default: "true"
working-directory:
description: Directory to run actionlint in, relative to the workspace.
required: false
default: .
flags:
description: >-
Extra actionlint flags, for example "-ignore SC2086". Split on whitespace,
so it is for workflow authors rather than untrusted input.
required: false
default: ""
runs:
using: composite
steps:
- uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0
with:
mise_toml: |
[tools]
"github:kjanat/actionlint" = "${{ inputs.version }}"
${{ inputs.shellcheck == 'true' && 'shellcheck = "latest"' || '' }}
${{ inputs.pyflakes == 'true' && '"pipx:pyflakes" = "latest"' || '' }}

[settings]
minimum_release_age = "0s"

- shell: bash
env:
WORKING_DIRECTORY: ${{ inputs.working-directory }}
FLAGS: ${{ inputs.flags }}
run: |
set -euo pipefail
echo "::add-matcher::${GITHUB_ACTION_PATH}/actionlint-matcher.json"
read -ra flags <<< "${FLAGS}"
cd "${WORKING_DIRECTORY}"
actionlint -color "${flags[@]}"
branding:
icon: check-circle
color: blue
17 changes: 17 additions & 0 deletions action/cli/actionlint-matcher.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"problemMatcher": [
{
"owner": "actionlint",
"pattern": [
{
"regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
}
]
}
38 changes: 21 additions & 17 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,29 +303,32 @@ socket. Standard Ubuntu runners, including `ubuntu-24.04-arm` and
`ubuntu-26.04-arm`, are supported by the published `linux/amd64` and
`linux/arm64` image.

On a daemon-less runner such as `ubuntu-slim`, download and run the binary
instead. `uses: docker://ghcr.io/kjanat/actionlint:latest` is not an alternative
there because it has the same Docker daemon requirement.
On a daemon-less runner such as `ubuntu-slim`, use the CLI action at
`action/cli` instead. `uses: docker://ghcr.io/kjanat/actionlint:latest` is not an
alternative there because it has the same Docker daemon requirement.

```yaml
- uses: actions/checkout@v7
with: { persist-credentials: false }
- name: Download and run actionlint
env: { GH_TOKEN: "${{ github.token }}", GH_REPO: "kjanat/actionlint" }
run: |
case "${RUNNER_ARCH}" in
X64) asset_arch=amd64 ;;
ARM64) asset_arch=arm64 ;;
ARM) asset_arch=armv6 ;;
X86) asset_arch=386 ;;
*) echo "Unsupported runner architecture: ${RUNNER_ARCH}" >&2; exit 1 ;;
esac
gh release download --pattern "actionlint_*_${RUNNER_OS,,}_${asset_arch}.tar.gz" --output - | tar -xzf - actionlint
./actionlint -color
- uses: kjanat/actionlint/action/cli@v1
```

It installs actionlint with [mise][mise], which picks the release asset for the
runner's platform, and registers the [problem matcher](#problem-matchers) so
errors appear as annotations. No Docker daemon and no copied matcher file are
needed.

ShellCheck and pyflakes are installed alongside actionlint unless you turn them
off:

```yaml
- uses: kjanat/actionlint/action/cli@v1
with: { shellcheck: "false", pyflakes: "false" }
```

The binary-only path does not bundle ShellCheck or pyflakes; install them on the
runner when those integrations are required. `v1` moves to each new release.
The other inputs are `version` for the actionlint release, `working-directory`,
and `flags` for extra command line options such as `-ignore`. `v1` moves to each
new release.
`v1.13.0` is a versioned release tag, but only a full-length commit SHA provides
an immutable action reference.

Expand Down Expand Up @@ -785,6 +788,7 @@ You can also see actionlint issues inline in VS Code via the [Trunk VS Code exte
[go-shellcheck]: https://github.com/wasilibs/go-shellcheck
[go-template]: https://pkg.go.dev/text/template
[jsonl]: https://jsonlines.org/
[mise]: https://mise.jdx.dev
[nova-extension]: https://extensions.panic.com/extensions/org.netwrk/org.netwrk.actionlint/
[nova]: https://nova.app
[nvim-lint]: https://github.com/mfussenegger/nvim-lint
Expand Down
Loading