Skip to content

ci: use a maintained commitlint action fork - #20

Merged
robinbowes merged 1 commit into
mainfrom
fix/commitlint-ci-version-skew
Aug 11, 2026
Merged

ci: use a maintained commitlint action fork#20
robinbowes merged 1 commit into
mainfrom
fix/commitlint-ci-version-skew

Conversation

@robinbowes

@robinbowes robinbowes commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What

Points the commitlint job at yo61/commitlint-github-action — a maintained fork running commitlint v21 on Node 24.

Why

Dependabot PRs fail the commitlint job on body-max-line-length, while the pre-commit lint job passes the same commit. Same commit, same commitlint.config.mjs, different verdict.

@commitlint/ensure v20 added an exemption for long lines containing a URL:

const URL_REGEX = /\bhttps?:\/\/\S+/;
value.split(/\r?\n/).every((line) => URL_REGEX.test(line) || ensure(line, max));

wagoid/commitlint-github-action@v6.2.1 is the latest release and pins @commitlint/ensure: ^19.0.3, so CI enforced a stricter rule than the config intends. Dependabot bodies are markdown link lists — one real example is 314 characters on a single line.

Upstream is unmaintained: no commit to master since 2025-01-14, and the v20 bump (PR #837) has been open and mergeable since July with no response.

The fork

yo61/commitlint-github-action@v6.3.0 — all @commitlint/* at ^21, Node 24.19.0 LTS (v21 needs node >= 22.12), commitlint-plugin-function-rules at ^5 (v4's peer range caps at <20 and breaks npm ci), published to ghcr.io from a pushed tag. Actions SHA-pinned, least-privilege permissions, actionlint and zizmor clean.

Verified against the action's own load+lint path with a real commitlint.config.mjs:

Case Result
Dependabot commit, 314-char body line valid
Sentence-case subject with subject-case: [0] valid — the .mjs override is honored
Malformed commit rejected

Commit subjects stay validated for Dependabot as well as humans, rather than exempting bot commits.

yo61-lastlight[bot]
yo61-lastlight Bot previously approved these changes Aug 11, 2026

@yo61-lastlight yo61-lastlight Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Replaces wagoid/commitlint-github-action (pinned to @commitlint/ensure ^19) with a direct npx run pinned to @commitlint/cli@21.2.1 / @commitlint/config-conventional@21.2.0, matching the pre-commit hook's version floor. Verified locally against this repo's actual commit history: the pinned command runs cleanly against the existing commit range (including the dependabot bump commits and this PR's own commit), and the permissions change (pull-requests: read -> contents: read) is correct since the commit range now comes from local git rather than the API. BASE_SHA/HEAD_SHA are passed through env vars rather than interpolated into the script, avoiding injection. No stale references to the old action remain elsewhere in the repo. Clean, well-scoped CI fix.

yo61-lastlight[bot]
yo61-lastlight Bot previously approved these changes Aug 11, 2026

@yo61-lastlight yo61-lastlight Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Re-review after the prior bot APPROVE was dismissed by a new commit. That commit replaces the npx-based commitlint invocation with a package.json/package-lock.json tracked in .github/commitlint, installed via npm ci and cached by actions/setup-node, plus a matching Dependabot npm entry for that directory. This directly addresses the issue title ("pin commitlint in a tracked manifest") and is a strict improvement over the previous npx approach: the exact versions are now visible to Dependabot and reviewable in diffs rather than embedded in a workflow run command. Verified: the install step's working-directory and the binary path used in the lint step are consistent (.github/commitlint/node_modules/.bin/commitlint from repo root), the lockfile's pinned versions match package.json exactly, cache-dependency-path points at the right lockfile, the new dependabot.yml entry's directory matches, permissions (contents: read) are sufficient for checkout+local git range, and BASE_SHA/HEAD_SHA are passed via env vars rather than interpolated into the shell command. No stale references to the old npx/action-based approach remain elsewhere in the repo. No Critical or Important findings.

@robinbowes
robinbowes force-pushed the fix/commitlint-ci-version-skew branch 2 times, most recently from 7150108 to d470186 Compare August 11, 2026 13:39
@robinbowes robinbowes changed the title ci: run commitlint directly instead of stale action ci: use a maintained commitlint action fork Aug 11, 2026

@yo61-lastlight yo61-lastlight Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Prior bot reviews were both dismissed by later commits that replaced the fix entirely (npx-pinned commitlint, then a tracked package.json/lockfile), so neither's findings carry over to this diff — this is a third, unrelated approach (repointing the workflow at a personally-maintained fork of the upstream action) and none of my earlier findings apply here. The diff itself (7 lines in ci.yml) does what it says: swaps wagoid/commitlint-github-action@v6.2.1 for yo61/commitlint-github-action@v6.3.0, SHA-pinned. I confirmed the pinned commit (31e5e045...) is real, on the fork's master, and its package.json is at version 6.3.0 with @commitlint/* bumped to ^21 as claimed. One real gap: the fork's action.yml runs docker://ghcr.io/yo61/commitlint-github-action:6.3.0 — a mutable registry tag, not a digest — so the git-SHA pin on the uses: line doesn't actually pin what gets executed.

Comment thread .github/workflows/ci.yml Outdated
# containing a URL added in v20. Dependabot bodies are markdown link lists
# well over 100 chars, so ^19 fails them on body-max-line-length while the
# pre-commit hook (v21) passes them.
- uses: yo61/commitlint-github-action@31e5e0454fc0709625e6dcfb502ea18978f45f15 # v6.3.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Important] SHA pin doesn't cover the actual executed artifact — the Docker image is referenced by mutable tag

This pins the git ref of yo61/commitlint-github-action to a commit SHA, but the fork's action.yml declares runs.using: docker with image: docker://ghcr.io/yo61/commitlint-github-action:6.3.0 — a registry tag, not a digest. GitHub Actions pulls that pre-built image straight from ghcr.io at run time rather than building it from the pinned commit; the SHA pin only fixes which action.yml gets read, not which container gets executed. If tag 6.3.0 is ever repushed on ghcr.io (deliberately or via a compromised token), every CI run using this SHA-pinned reference silently starts running different code, with no diff or commit to review. The PR body's "Actions SHA-pinned" claim doesn't hold for the actual runtime artifact. Pinning by digest (ghcr.io/yo61/commitlint-github-action@sha256:...) in the fork's action.yml would close this; as-is, worth calling out since the whole point of this PR is tightening trust in the commitlint pipeline.

@robinbowes
robinbowes force-pushed the fix/commitlint-ci-version-skew branch 2 times, most recently from 73243fb to 2b7d043 Compare August 11, 2026 14:27

@yo61-lastlight yo61-lastlight Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Re-review after the last bot review (COMMENTED, sha d470186). Prior-findings ledger: [Important] Docker image pinned by mutable tag rather than digest — still open. The only change since that review is a reword of the code comment above the uses: line (message text swapped for a different phrasing of the same rationale); the uses: yo61/commitlint-github-action@31e5e0454... pin and the fork's action.yml are unchanged. I re-fetched the fork's action.yml at the pinned commit and confirmed runs.using: docker still points at docker://ghcr.io/yo61/commitlint-github-action:6.3.0, a mutable registry tag rather than a digest, so the finding stands unchanged.

Comment thread .github/workflows/ci.yml
# two majors behind. This fork runs commitlint v21 on node 24, matching
# the version the pre-commit hook resolves.
- uses: yo61/commitlint-github-action@31e5e0454fc0709625e6dcfb502ea18978f45f15 # v6.3.0
with:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Important] SHA pin still doesn't cover the executed artifact — fork's action.yml runs a mutable Docker tag

Unchanged from the last review: the git-SHA pin on yo61/commitlint-github-action@31e5e045... only fixes which action.yml gets read. That file declares runs.using: docker with image: docker://ghcr.io/yo61/commitlint-github-action:6.3.0 (confirmed by fetching action.yml at this exact SHA) — a registry tag, not a digest. GitHub Actions pulls that pre-built image from ghcr.io at run time, so if tag 6.3.0 is ever repushed, every CI run using this SHA-pinned reference silently executes different code with no diff to review. Since this PR's stated purpose is tightening the commitlint pipeline's supply-chain hygiene, pinning the fork's action.yml to ghcr.io/yo61/commitlint-github-action@sha256:... would close the gap.

@robinbowes
robinbowes enabled auto-merge (squash) August 11, 2026 14:42
@robinbowes
robinbowes disabled auto-merge August 11, 2026 14:42
@robinbowes
robinbowes force-pushed the fix/commitlint-ci-version-skew branch from 2b7d043 to 962afb1 Compare August 11, 2026 14:50

@yo61-lastlight yo61-lastlight Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Re-review after the previous COMMENTED review. Prior-findings ledger: [Important] Docker image pinned by mutable registry tag rather than digest — still open. The only change since that review is a reword of the code comment above the uses: line; the uses: yo61/commitlint-github-action@31e5e0454... pin and the fork's action.yml are otherwise unchanged. I re-fetched the fork's action.yml at the pinned commit and confirmed runs.using: docker still resolves to docker://ghcr.io/yo61/commitlint-github-action:6.3.0, a mutable tag, so the finding stands and this stays a COMMENT rather than an APPROVE.

Comment thread .github/workflows/ci.yml Outdated
# Fork of wagoid/commitlint-github-action. Upstream is unmaintained: no
# commit to master since 2025-01-14, and it pins @commitlint/ensure ^19,
# two majors behind. This fork runs commitlint v21 on node 24.
- uses: yo61/commitlint-github-action@31e5e0454fc0709625e6dcfb502ea18978f45f15 # v6.3.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Important] SHA pin doesn't cover the executed artifact — fork's action.yml runs a mutable Docker tag

The uses: line pins the git ref of yo61/commitlint-github-action to commit 31e5e0454..., but that commit's action.yml declares runs.using: docker with image: docker://ghcr.io/yo61/commitlint-github-action:6.3.0 — a registry tag, not a digest (verified by fetching action.yml at this exact SHA). GitHub Actions pulls that pre-built image from ghcr.io at run time; the SHA pin only fixes which action.yml is read, not which container executes. If tag 6.3.0 is ever repushed on ghcr.io, every CI run using this SHA-pinned reference silently executes different code with no diff to review — undermining the PR's own stated goal of tightening the commitlint pipeline's supply-chain hygiene. Pinning the fork's action.yml to ghcr.io/yo61/commitlint-github-action@sha256:... would close this gap.

wagoid/commitlint-github-action pins @commitlint/ensure ^19. The
exemption for long lines containing a URL landed in v20, so CI enforced
a stricter rule than the config intended and failed Dependabot commits
on body-max-line-length, while the pre-commit hook resolving v21 passed
the same commit.

Upstream is unmaintained: master has had no commit since 2025-01-14 and
the v20 bump has sat open since July. Point at yo61/commitlint-github-action
instead, which runs commitlint v21 on node 24 and is published to ghcr.io.
@robinbowes
robinbowes force-pushed the fix/commitlint-ci-version-skew branch from 962afb1 to 55fa660 Compare August 11, 2026 15:29

@yo61-lastlight yo61-lastlight Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Prior-findings ledger: [Important] Docker image pinned by mutable registry tag rather than digest — fixed. The only change since the last review is the uses: SHA (31e5e045... -> 501ff7bb...) and the code comment. I fetched the fork's action.yml at the new pinned commit and confirmed runs.using: docker now targets docker://ghcr.io/yo61/commitlint-github-action@sha256:78d4769928... — a digest, not a tag — closing the supply-chain gap raised in every prior review. package.json at that commit is version 6.3.0 with @commitlint/* at ^21.2.0, matching the PR body's claims. The workflow diff itself is otherwise unchanged (still 6 lines in ci.yml, same permissions, same configFile input). No remaining Critical or Important findings.

@robinbowes
robinbowes merged commit 2c2fc4b into main Aug 11, 2026
3 checks passed
@robinbowes
robinbowes deleted the fix/commitlint-ci-version-skew branch August 11, 2026 15:35
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