diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 602e7b244..193275a19 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -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 diff --git a/.github/workflows/matcher.yaml b/.github/workflows/matcher.yaml index ba40c91d6..542af873d 100644 --- a/.github/workflows/matcher.yaml +++ b/.github/workflows/matcher.yaml @@ -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 diff --git a/Makefile b/Makefile index 5413d18d6..4c1134308 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -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 diff --git a/README.md b/README.md index 5503832fa..76b7f354c 100644 --- a/README.md +++ b/README.md @@ -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.

Inputs

diff --git a/action/cli/action.yml b/action/cli/action.yml new file mode 100644 index 000000000..c004b58f8 --- /dev/null +++ b/action/cli/action.yml @@ -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 diff --git a/action/cli/actionlint-matcher.json b/action/cli/actionlint-matcher.json new file mode 100644 index 000000000..4613e1617 --- /dev/null +++ b/action/cli/actionlint-matcher.json @@ -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 + } + ] + } + ] +} diff --git a/docs/usage.md b/docs/usage.md index 6087211c4..45d9691d4 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -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. @@ -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