fix: repair invalid action.yml and harden the action - #2
Conversation
action.yml was not valid YAML on any ref, including the published v1.0.0
and v1 tags: the `Lint PR commits` step embedded a Python script at column
0 inside an 8-space block scalar, so the dedent ended the scalar and YAML
read `if msg.startswith("Merge "): continue` as a mapping. GitHub could not
load the action at all — it was broken for every consumer.
Rather than re-indent the heredoc, drop it. commitlint already has
`--range`, which reads the PR's commits from git and skips merge commits
itself, so the API call, the token, the base64 round-trip, and the
pagination all disappear. That removes the construct that broke the parse
and three defects with it:
- per_page=250 was silently capped at 100 by the API, so PRs with more
than 100 commits were partially linted with no warning
- `|| status=1` was unreachable in warn mode, since --mode warn exits 0
- the ALLOW_REVERT_PREFIX comment described merge commits, but that flag
only accepts `Revert "..."` subjects
Shallow checkouts do not contain the PR base, and HEAD on a pull_request
event is GitHub's synthetic merge commit, so fetch both endpoints and lint
to the branch tip. Guard for a missing checkout with an actionable error
rather than a bare git failure.
Pin actions/setup-go to a commit SHA. The README recommended SHA pinning
while the action itself used a mutable tag.
Add MIT LICENSE (the repo had none, leaving it legally unusable) and CI:
action.yml is parsed, actionlint runs, unpinned `uses:` fail the build, and
a self-test job runs the action against its own PR. The parse check and
actionlint were both confirmed to catch the original defect at line 81.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VSrrciEDBTuFNMtKocScML
CI caught two problems with its own new checks. The pin guard flagged `uses: ./`. A local path refers to the commit already checked out, so there is no external ref to pin; exclude `./`-prefixed uses rather than weaken the SHA pattern. The self-test could not run the action: it installs the linter with `go install`, and DivergentCodes/commitlint is still private, so the module proxy returns 404 on a hosted runner. Confirmed by fetching both the repo and proxy.golang.org unauthenticated. Gate the job on a COMMITLINT_PUBLIC repo variable so it is skipped for a known reason instead of failing for one unrelated to this code; drop the condition once commitlint is public. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VSrrciEDBTuFNMtKocScML
|
CI is green. It also caught two problems in its own new checks, both now fixed:
Ordering constraint for going publicThe action installs the linter with Confirmed by fetching both unauthenticated — So this action cannot work for anyone, including this repo's own CI, until commitlint is public. Making Correct order: make The self-test is gated on that variable so it skips for a known, documented reason rather than failing for one unrelated to the code under review. Once commitlint is public, delete the Still outstanding after merge
|
The action is broken on every ref, including
v1.0.0andv1action.ymlis not valid YAML. TheLint PR commitsstep embedded a Python script at column 0 inside an 8-spacerun: |block scalar:The dedent terminates the scalar, so YAML parses the Python as a mapping key and fails at line 81. GitHub cannot load this action at all — it fails for every consumer, on the published tags.
Fix: delete the script rather than re-indent it
commitlintalready has--range, which reads the PR's commits from git and skips merge commits itself. Using it removes the API call, the token, the base64 round-trip, and the pagination — and with them, three more defects:per_page=250silently capped at 100 by the API — PRs over 100 commits were partially linted with no warning|| status=1unreachable in warn mode (verified:--mode warnexits 0)ALLOW_REVERT_PREFIXcomment described merge commits, but that flag only acceptsRevert "..."subjects (verified both ways)The remaining git handling carries over the two lessons from the sibling repo's CI: shallow checkouts don't contain the PR base, and
HEADon apull_requestevent is GitHub's synthetic merge commit. Both endpoints are fetched and the range ends at the real branch tip. Verified end-to-end against an actual--depth 1clone.A missing checkout now produces an actionable
::error::instead of a bare git failure.SHA pinning
actions/setup-go@v5→@40f1582…(v5.6.0). The README recommended SHA pinning while the action itself used a mutable tag.I also caught myself here: I first pinned actionlint to a Docker digest I had invented. It matched no real tag — checked against the registry. Replaced with a source install at a pinned version, which also fits this repo's "no third-party actions" stance better than a container.
LICENSE
MIT,
Copyright (c) 2026 DivergentCodes. The repo had none, which left it legally unusable by anyone — a problem for something meant to be consumed.CI
The check that would have prevented this entire PR:
action.ymlparses — confirmed to catch the original defect at line 81uses:commits-modeon andoff, inwarnso contributor commit style never gates this repo's CIStatic checks alone wouldn't have caught a composite action that parses but doesn't run, hence the self-test.
README
Corrected claims that are no longer true: removed the
github-tokeninput, changedpermissions: pull-requests: read→contents: read, dropped thepython3/base64runner requirements, and added the now-requiredactions/checkoutstep to the example. Verified the input table matchesaction.ymlexactly — no documented-but-nonexistent inputs, none undocumented.After merge
v1.0.0andv1both point at broken code. They should be re-cut: tagv1.0.1frommainand movev1to it, so anyone following the README's@v1guidance gets something that loads.🤖 Generated with Claude Code
https://claude.ai/code/session_01VSrrciEDBTuFNMtKocScML