From 31f9fec74c325a48404e7cb9e1ef158d658a528d Mon Sep 17 00:00:00 2001 From: Jack Sullivan Date: Thu, 30 Jul 2026 13:19:49 -0700 Subject: [PATCH] fix: keep checksum verification when commitlint is public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The install step set GOPRIVATE unconditionally. That is necessary for a private module — the proxy and checksum database cannot see one — but it also disables checksum-database validation, which Go's own documentation calls out. Once commitlint is public that protection would be forfeited silently, with nothing in the workflow output indicating it. Attempt the ordinary public install first and fall back to the credentialed path only when it fails, scoping GOPRIVATE to that fallback. A public commitlint therefore keeps proxy and checksum verification, and a private one still works. When the public fetch fails and no token was supplied, emit an ::error:: naming the likely cause instead of surfacing git's "terminal prompts disabled", which does not say what to do about it. Verified all three paths: a public module installs via the public path, a private module without a token produces the actionable error, and the credentialed fallback installs commitlint v1.1.2. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01VSrrciEDBTuFNMtKocScML --- README.md | 16 +++++++++++----- action.yml | 34 +++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8891e7e..c4464fa 100644 --- a/README.md +++ b/README.md @@ -68,11 +68,17 @@ merge with rebase or merge commits instead, set `commits-mode: block`. to fetch the commits. The action makes no API calls and never writes anything. With `commits-mode: off` it reads only the event payload. -While the `commitlint` repository is private, `go install` needs credentials -to fetch the module. The action rewrites only `github.com/DivergentCodes/` -URLs to carry `github-token`, so the token is never offered to another host or -org, and sets `GOPRIVATE` so the public proxy and checksum database are -bypassed. Pass a token that can read that repo: +The action installs the linter with a public `go install` first. If the +`commitlint` repository is public, that path is used and the module proxy's +**checksum-database verification applies** — nothing else is needed. + +If that fetch fails, the repository is private and credentials are required. +The action then rewrites only `github.com/DivergentCodes/` URLs to carry +`github-token`, so the token is never offered to another host or org, and sets +`GOPRIVATE` for the retry. `GOPRIVATE` bypasses the proxy and checksum +database — unavoidable for a private module, which is why it is scoped to the +fallback rather than applied unconditionally. Pass a token that can read the +repo: ```yaml - uses: DivergentCodes/commitlint-action@ diff --git a/action.yml b/action.yml index cefa2aa..d5140b1 100644 --- a/action.yml +++ b/action.yml @@ -45,34 +45,42 @@ runs: go-version: stable cache: false - # `go install` fetches over HTTPS with no credentials, so while the - # commitlint repo is private git prompts for a username and dies with - # "terminal prompts disabled". Rewrite only DivergentCodes URLs to carry - # the token, so it is never offered to another host or org, and set - # GOPRIVATE so the public proxy and checksum database — which cannot see a - # private module — are bypassed rather than consulted and failed. - # - # This is a no-op once commitlint is public: the rewrite still matches, but - # a public fetch would have succeeded anyway. + # Public first, credentials only as a fallback. The private path has to set + # GOPRIVATE, which bypasses the module proxy *and the checksum database* — + # unavoidable for a private module, but a real loss of supply-chain + # verification. Attempting the public fetch first means a public commitlint + # keeps that verification instead of silently forfeiting it. - name: Install commitlint shell: bash env: VERSION: ${{ inputs.version }} GH_TOKEN: ${{ inputs.github-token }} - GOPRIVATE: github.com/DivergentCodes/* run: | set -euo pipefail + + if go install "github.com/DivergentCodes/commitlint@${VERSION}"; then + exit 0 + fi + + if [ -z "${GH_TOKEN:-}" ]; then + echo "::error::could not fetch github.com/DivergentCodes/commitlint@${VERSION}; if that repository is private, pass a token that can read it via the github-token input" + exit 1 + fi + + echo "public fetch failed; retrying with credentials" cleanup() { git config --global --unset-all \ url."https://x-access-token:${GH_TOKEN}@github.com/DivergentCodes/".insteadOf || true } trap cleanup EXIT - # The token stays in the environment rather than argv, and Actions - # masks it in logs; the trap keeps it out of later steps' git config. + # Rewrite only DivergentCodes URLs, so the token is never offered to + # another host or org. It stays in the environment rather than argv, + # Actions masks it in logs, and the trap keeps it out of later steps. git config --global \ url."https://x-access-token:${GH_TOKEN}@github.com/DivergentCodes/".insteadOf \ "https://github.com/DivergentCodes/" - go install "github.com/DivergentCodes/commitlint@${VERSION}" + GOPRIVATE='github.com/DivergentCodes/*' \ + go install "github.com/DivergentCodes/commitlint@${VERSION}" - name: Lint PR title if: ${{ inputs.pr-title-mode != 'off' && github.event_name == 'pull_request' }}