Skip to content

Resolve SHA pins to release tags in script/release-train#194

Merged
WillAbides merged 2 commits into
mainfrom
willabides/fix-sha-pinned-action
May 30, 2026
Merged

Resolve SHA pins to release tags in script/release-train#194
WillAbides merged 2 commits into
mainfrom
willabides/fix-sha-pinned-action

Conversation

@WillAbides

Copy link
Copy Markdown
Owner

Fixes #193

Problem

When the action is pinned by commit SHA (e.g. uses: WillAbides/release-train@<sha>), basename "$GITHUB_ACTION_PATH" in script/release-train returns the SHA instead of a release tag. That produces a download URL like

https://github.com/WillAbides/release-train/releases/download/<sha>/bindown.yaml

which 404s. curl -L -o happily writes the 404 HTML page to tmp/bindown.yaml, bindown then fails parsing it, and the failure is masked by action_dl || local_build. Most consumers don't have go on the runner, so what they actually see is a confusing go: command not found / go.mod not found error far removed from the real cause.

Fix

script/release-train now decides what to do based on the basename of $GITHUB_ACTION_PATH:

  • vX.Y.Z-shaped → download bindown.yaml for that release. Any download/install failure is fatal — silently falling back to a source build would defeat the point of pinning to a released version.
  • Full 40-hex SHA pinned against canonical WillAbides/release-train → resolve the SHA to a release tag via git ls-remote --tags https://github.com/WillAbides/release-train.git, then treat as a release. Forks at the same SHA are intentionally not trusted — a fork could carry a vX.Y.Z tag pointing at unrelated source.
  • Anything else (branch name like main, fork SHA, short SHA, local checkout, unresolved SHA) → fall through to go build with a clear log message instead of attempting a download that's guaranteed to 404.

Additional hardening:

  • curl --fail --silent --show-error --location so a 404 surfaces as an error instead of a 200-with-HTML body.
  • Explicit error checks around curl and bindown install with diagnostic messages.
  • Remove any stale bin/release-train before install so a failed install can't exec a previous build.
  • git ls-remote output is captured before being piped through awk so a network failure isn't lost to POSIX-sh's lack of pipefail.

Notes / follow-ups

  • The script remains POSIX #!/bin/sh and passes bin/shellcheck (per script/lint).
  • git is assumed available on the runner. It's effectively guaranteed on GitHub-hosted runners and on any runner using actions/checkout. If git ls-remote fails, the script logs and falls back to local build.
  • An alternative implementation discussed in Action fails when pinned by commit SHA (basename $GITHUB_ACTION_PATH not a release tag) #193 was to bake a VERSION file into the release artifacts. That would avoid the runtime network call but requires non-trivial release-workflow changes (the release runs from detached HEAD so the new file would need a separate commit path). Happy to do that as a follow-up if preferred.

Validation

  • bin/shellcheck script/* passes.
  • New helper functions (looks_like_release_tag, is_full_sha, resolve_sha_to_tag, determine_release_tag) were spot-tested locally against the scenarios above, including resolving the actual cd01ea9e19bb396bf659f61e1c840c5174b92de8 SHA from the issue → v3.8.5.
  • go test ./... passes.
  • script/release-train --generate-action produces an unchanged action.yml.

WillAbides and others added 2 commits May 29, 2026 19:44
When the action is pinned by commit SHA (e.g. `uses: WillAbides/release-train@<sha>`),
`basename "$GITHUB_ACTION_PATH"` returns the SHA instead of a release tag,
so the bindown.yaml download from
`https://github.com/WillAbides/release-train/releases/download/<sha>/bindown.yaml`
returns a 404 HTML page that curl silently writes to disk, bindown then fails
parsing it, and the failure is masked by `action_dl || local_build` so the user
sees a confusing 'go: command not found' or 'go.mod not found' error instead of
the real problem.

Fix:

- Only treat `vX.Y.Z`-shaped basenames as release tags.
- For full 40-hex SHAs pinned against the canonical
  `WillAbides/release-train` repo, resolve the SHA to a release tag via
  `git ls-remote --tags` against the canonical URL. Don't trust forks at the
  same SHA, because they could have an unrelated `vX.Y.Z` tag.
- Anything else (branch name, local action dir basename, fork SHA, short SHA)
  falls through to a clean source build with a clear log message instead of
  attempting a download that will 404.
- `curl --fail --silent --show-error --location` so a 404 surfaces as an
  error instead of a 200-with-HTML.
- Explicit error checks around curl and bindown install, and remove any stale
  `bin/release-train` before install so we can't exec a previous build if the
  current install fails.
- When a release tag is selected (explicitly or via SHA resolution), a download
  or install failure is fatal: silently falling back to a source build would
  defeat the point of pinning to a released version.

Fixes #193

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@WillAbides
WillAbides merged commit a234a74 into main May 30, 2026
4 checks passed
@WillAbides
WillAbides deleted the willabides/fix-sha-pinned-action branch May 30, 2026 00:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Action fails when pinned by commit SHA (basename $GITHUB_ACTION_PATH not a release tag)

1 participant