Skip to content

fix: resolve "latest" without api.github.com - #1

Merged
mrjbq7 merged 1 commit into
mainfrom
fix/resolve-latest-without-the-api
Sep 7, 2026
Merged

mrjbq7 merged 1 commit into
mainfrom
fix/resolve-latest-without-the-api

Conversation

@mario4tier

@mario4tier mario4tier commented Sep 6, 2026

Copy link
Copy Markdown
Member

api.github.com allows 60 requests/hour per IP, and GitHub-hosted runners
share IPs. On a busy hour the version lookup gets a 403 and the action dies —
this reddened an unrelated PR on ta-lib-python today. Worse, curl and
python3 ran in a pipeline, so the visible error was a JSONDecodeError, not a
rate limit.

Before

VERSION=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \
          | python3 -c "import sys,json; print(json.load(sys.stdin)['tag_name'].lstrip('v'))")

After — github.com's /releases/latest redirect, which GitHub documents and
which carries no rate-limit quota:

LOCATION=$(curl -fsS --retry 3 -o /dev/null -w '%{redirect_url}' \
             "https://github.com/${REPO}/releases/latest")
TAG="${LOCATION##*/tag/}"
VERSION="${TAG#v}"

No API, no quota, no JSON parser.

It is the common pattern

Shell installers avoid the API rather than authenticate it. golangci-lint,
trivy and syft all resolve "latest" from github.comgrep -c api.github.com is 0 in all three install.sh files. (They use the
Accept: application/json variant of the same URL; the redirect used here is
the form GitHub actually documents, under "Linking to releases".)

Tested

Resolution, against live repos:

repo resolved
TA-Lib/ta-lib 0.7.1
golangci/golangci-lint 2.13.2
aquasecurity/trivy 0.74.0
cli/cli 2.100.0

Failure modes stay loud, which matters most — a wrong version installs silently:

  • nonexistent repo → curl: (22) ... 404, exit 22
  • repo with no releases (actions/toolkit) → redirect has no /tag/, so the
    guard fires with a clear message rather than returning a bad version

Also here

  • --retry 3 on the three asset downloads, for transient 5xx and timeouts. No
    --retry-delay, so curl keeps its own exponential backoff.
  • .github/workflows/test.yml — the action had no CI, so it has never actually
    been exercised. Installs on ubuntu/macos/windows × latest/0.7.1, and checks
    the reported version against the installed header.

@mario4tier
mario4tier force-pushed the fix/resolve-latest-without-the-api branch 3 times, most recently from 048535a to 8ec2d19 Compare September 6, 2026 23:50
The version lookup used api.github.com, which allows 60 requests/hour per IP.
GitHub-hosted runners share IPs, so on a busy hour it answers 403 and the action
dies -- and because curl and python ran in a pipeline, what the user saw was a
JSONDecodeError, not a rate limit.

Resolve from github.com's documented /releases/latest redirect instead. No API,
no quota, no parser. This is what the shell installers for golangci-lint, trivy
and syft all do.

Also --retry 3 on the asset downloads, for transient 5xx, and a smoke test: the
action had no CI.
@mario4tier
mario4tier force-pushed the fix/resolve-latest-without-the-api branch from 8ec2d19 to cfe56f1 Compare September 6, 2026 23:50
@mario4tier
mario4tier requested a review from mrjbq7 September 6, 2026 23:50
@mrjbq7
mrjbq7 merged commit b650284 into main Sep 7, 2026
12 checks passed
@mrjbq7

mrjbq7 commented Sep 7, 2026

Copy link
Copy Markdown
Member

Rad!

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.

2 participants