Skip to content

chore(ci): add actionlint + prettier check on PRs#12

Merged
topcoder1 merged 2 commits into
mainfrom
chore/lint-on-pr
May 1, 2026
Merged

chore(ci): add actionlint + prettier check on PRs#12
topcoder1 merged 2 commits into
mainfrom
chore/lint-on-pr

Conversation

@topcoder1

Copy link
Copy Markdown
Owner

Summary

ci-workflows hosts reusable workflows that other projects pull in via uses:. A typo here (bad expression syntax, deprecated runner version, undefined steps.X.outputs.Y reference) silently breaks every downstream consumer. This adds a CI gate to catch those before they merge.

Companion to whois-api-llc/wxa-jake-ai#178 and qwibitai/nanoclaw#2171, which wired husky+lint-staged on JS repos. ci-workflows gets a different shape because it has no package.json — pulling in a JS toolchain to format three files isn't worth the dependency footprint. CI-only enforcement is the right call for a YAML+Markdown repo.

What's in this PR

1. .github/workflows/lint.yml — new

  • actionlint job: downloads the official binary and runs it on pull_request + push to main. Catches GHA-specific bugs prettier can't see (and includes embedded shellcheck for run: blocks).
  • prettier job: runs prettier --check **/*.md. Just the README today; future-proof for any docs added later.

2. pr-classify.yml — shellcheck inline disable for SC2001
The intentional echo "$changed" | sed 's/^/ /' indents multiline output. shellcheck suggested ${var//.../...} but for "prepend N spaces to each line" sed is clearer than bash parameter expansion gymnastics. Documented inline.

3. README.md — prettier --write
Cleaning up pre-existing drift so the new check starts green.

Pre-flight done locally

  • actionlint -color → clean (was flagging SC2001 before the inline disable)
  • npx prettier@3 --check "**/*.md" → clean (was flagging README before --write)

What this does NOT add

  • Bash linting via shellcheck on standalone .sh scripts (no scripts in repo today; revisit if any get added)
  • yamllint (actionlint's embedded YAML parser is sufficient for workflow files)

🤖 Generated with Claude Code

ci-workflows hosts reusable workflows that other projects pull in via
`uses:`. A typo here (bad expression syntax, deprecated runner,
undefined `steps.X` output ref) silently breaks every downstream
consumer. CI gate prevents that.

Why not husky/lint-staged: this repo has no package.json. Pulling in
a JS toolchain to format three files isn't worth the dependency
footprint. CI-only enforcement is the right shape for a YAML+Markdown
repo — actionlint covers the GHA-specific bugs prettier can't see,
and prettier covers the README.

Bundled in the same PR (small fixes that would otherwise immediately
fail the new lint job):

- `pr-classify.yml`: shellcheck inline disable for SC2001 on the
  intentional `sed 's/^/  /'` multiline indent. sed is clearer than
  the bash parameter-expansion alternative for this case.
- `README.md`: prettier --write to clean up pre-existing drift.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

- name: Download actionlint
id: get_actionlint
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supply-chain risk: unpinned main-branch curl | bash

This fetches and executes a script from rhysd/actionlint's main branch with no integrity check. Any commit to that branch — including a compromise — lands immediately in this repo's CI with no review gate.

This is especially risky here because ci-workflows is a shared-reusable-workflow host: a poisoned actionlint binary could exfiltrate secrets injected by downstream callers.

Safer alternatives (in order of preference):

  1. Pin to a specific version tag using the official action:
Suggested change
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
uses: rhysd/actionlint@v1.7.7

(replace with the current release; pinning to a SHA gives the strongest guarantee)

  1. Or, if you must use the download script, pin to a commit SHA:
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/<COMMIT_SHA>/scripts/download-actionlint.bash)

@claude

claude Bot commented May 1, 2026

Copy link
Copy Markdown

Flagged 1 issue inline — unpinned main-branch curl | bash in the actionlint download step is a supply-chain risk, especially given this repo is a shared reusable-workflow host.

Adds workflow_call trigger so other repos can call this via
  uses: topcoder1/ci-workflows/.github/workflows/lint.yml@main

Existing pull_request + push: main triggers stay so the workflow
self-tests on this repo. Inputs (all optional, sensible defaults):
  - markdown_glob (default '**/*.md')
  - run_actionlint (default true)
  - run_prettier (default true)

Per-job `if:` guards skip jobs when called with the corresponding
input set to false; for non-workflow_call invocations both jobs
always run.

Companion change: ~/.claude/templates/ci-workflows/{callers,scripts}/
gains lint.yml caller template + install-lint.sh installer (mirrors
install-pr-review.sh shape).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

- name: Download actionlint
id: get_actionlint
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supply chain risk: fetching from unpinned main branch

This curl | bash pulls from rhysd/actionlint@main with no version pin and no checksum verification. If that branch is ever compromised, the malicious script runs immediately in every subsequent CI run — and because this is a reusable workflow, all downstream consumers are exposed too.

Pin to a specific release tag so the content is immutable:

Suggested change
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/v1.7.7/scripts/download-actionlint.bash)

Or use the official action pinned to a SHA for stronger guarantees:

- uses: rhysd/actionlint@11f75d9775d0829b8fdc43df25c96a6e4ba40de1 # v1.7.7

(No id: / outputs.executable step needed with the action form.)

@claude

claude Bot commented May 1, 2026

Copy link
Copy Markdown

Flagged 1 issue inline — unpinned curl-pipe-bash for actionlint download is a supply chain risk given this repo serves reusable workflows to downstream consumers.

@topcoder1
topcoder1 merged commit 470d663 into main May 1, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant