fix(api): skip stable tags whose GitHub Release is not yet published#277
fix(api): skip stable tags whose GitHub Release is not yet published#277hydai wants to merge 1 commit into
Conversation
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
5e11420 to
881be04
Compare
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 881be04f73
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
881be04 to
a11b1c3
Compare
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a11b1c348d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
a11b1c3 to
b888478
Compare
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
There was a problem hiding this comment.
Pull request overview
This PR fixes how latest_release() determines the “latest” stable WasmEdge version by skipping stable git tags that don’t yet have published release assets on the GitHub CDN (e.g., during the tag-push / draft-release window), preventing downstream install/checksum operations from failing on missing SHA256SUM.
Changes:
- Update
latest_release()to iterate stable tags newest-first and pick the first tag whoseSHA256SUMis reachable via CDN (HEAD with GET fallback). - Add a private helper
is_release_published(tag)encapsulating the publication check and its 404-vs-error semantics. - Update
test_install_latest_versionto exercise the real"latest"resolution path end-to-end.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/api/mod.rs |
Implements CDN-based “published assets” detection and updates latest_release() selection logic. |
tests/install_test.rs |
Adjusts integration test to install "latest" via the standard resolution path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b888478 to
4dec523
Compare
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
4dec523 to
07a93db
Compare
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07a93db568
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
`latest_release()` was returning whichever stable-formatted git tag had
the highest semver, regardless of whether the corresponding GitHub
Release had its install assets uploaded.
That worked when WasmEdge's tag-push and release-publish steps
happened atomically, but the actual release flow has two phases:
1. Maintainers push a tag (e.g. 0.16.3) to mark the revision and
trigger CI to start building cross-platform archives.
2. CI builds the archives plus the SHA256SUM digest file and
uploads them; then the GitHub Release goes live with assets
attached. The Release may be a *draft* during the upload window.
Between phases 1 and 2 the tag exists in `git ls-remote` but the
SHA256SUM file 404s. During that window `latest_release()` would
report the in-progress tag as latest, and any caller that tried to
download an asset (`get_release_checksum`,
`wasmedgeup install latest`) would fail with `ChecksumNotFound`.
This is independent of the recent gix migration — the previous
`git2::Remote::list` path had the same logical conflation between
"latest tag" and "latest installable release" and would fail the
same way.
Why HEAD the CDN file instead of the GitHub REST API
----------------------------------------------------
A first attempt at this fix used `GET
/repos/WasmEdge/WasmEdge/releases/tags/<tag>` to determine
publication. That endpoint is gated by GitHub's 60-req/hour
unauthenticated rate limit, which CI runners on shared IPs hit
easily — manifesting as a 403 that gets reported as an unrelated
error instead of as "not published yet."
The release-download URL on github.com is served by GitHub's CDN
with no API rate limit, so the check is both cheaper and more
reliable. It also incidentally handles the draft case: a draft
Release exposes no asset URLs to the public CDN, so the HEAD
naturally 404s.
Changes
-------
- `WasmEdgeApiClient::latest_release` now walks the sorted stable
candidates newest-first and returns the first one whose SHA256SUM
file is reachable via HEAD on
`<WASMEDGE_RELEASE_BASE_URL>/<tag>/SHA256SUM`. A 404 means the
tag's install assets have not been uploaded — fall through to the
next candidate. Other non-2xx statuses propagate so transient
outages surface as errors rather than as misleading
`NoReleasesFound`.
- New private helper `is_release_published(tag)` keeps the
404-vs-error distinction in one place.
- `tests/install_test.rs::test_install_latest_version` previously
re-implemented the buggy "first stable tag" logic with
`releases::get_all(...)[0]`. Switched it to pass the literal
`"latest"` so the install command's standard `resolve_version`
path drives the test — exercising the corrected
`latest_release()` end-to-end.
Verification
------------
- `cargo test --tests` — 87 pass. Before this change,
`test_get_release_checksum` and `test_install_latest_version`
both failed because `latest_release()` was returning the
in-progress `0.16.3` tag (Release exists as draft, SHA256SUM not
yet uploaded).
- Confirmed against the live remote at the time of this commit:
`HEAD https://github.com/WasmEdge/WasmEdge/releases/download/0.16.3/SHA256SUM`
returns 404; the same HEAD on `0.16.2/SHA256SUM` returns 302→200.
After the fix, `latest_release()` returns `0.16.2`.
Signed-off-by: hydai <z54981220@gmail.com>
07a93db to
5f5af3d
Compare
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
| // candidate would pay full TCP+TLS handshake cost. | ||
| let client = self.http_client()?; | ||
| for candidate in candidates { | ||
| if Self::is_release_published(&client, &candidate.to_string()).await? { |
Summary
Fixes
latest_release()to return the latest stable version whose install assets are actually uploaded to the release CDN, not just the latest stable git tag. The two diverge during release-prep windows when a tag is pushed but its archives are still being built / a draft Release exists without published assets.Root cause
WasmEdge releases happen in two phases:
0.16.3to mark a revision and trigger CI.git ls-remoteimmediately.SHA256SUMdigest, then a GitHub Release goes live with assets attached. The Release may be a draft during the upload window.releases/tags/<tag>REST endpoint and asset CDN URLs.latest_release()was reading from phase 1 (releases::get_all→git ls-remote). Whenever phase 2 hadn't completed for the highest tag, callers that subsequently tried to download anything (get_release_checksum,wasmedgeup install latest, the<- latestmarker inwasmedgeup list --remote) would fail withChecksumNotFound.This bug is independent of the recent gix migration — the previous
git2::Remote::listpath had the same conflation between "latest tag" and "latest installable release."Fix: HEAD the CDN, not the API
latest_release()now walks sorted stable candidates newest-first and accepts the first one whoseSHA256SUMfile is reachable viaHEAD <WASMEDGE_RELEASE_BASE_URL>/<tag>/SHA256SUM. A 404 → fall through to the next candidate; other non-2xx → propagate.Why HEAD-on-CDN rather than
GET /repos/.../releases/tags/<tag>: the REST endpoint is gated by GitHub's 60-req/hour unauthenticated rate limit. CI runners share IPs and our other tests already hit that API, so the publication check would land 403 — surfacing as a misleading "release publication check" error rather than as "not published yet." The release-download URL is served by GitHub's CDN with no API rate limit, so the check is both cheaper and more reliable. It also handles the draft case naturally: a draft Release exposes no asset URLs to the public CDN, so the HEAD 404s the same way it does for a tag with no Release at all.A first iteration of this PR went through the API; CI on macOS-beta hit the rate-limit path and failed with 403. Switched to the HEAD-on-CDN approach in
881be04.Other changes
is_release_published(tag)keeps the 404-vs-error distinction in one place.tests/install_test.rs::test_install_latest_versionpreviously re-implemented the same buggy "first stable tag" logic locally withreleases::get_all(...)[0]. Switched it to pass the literal"latest"so the install command's standardresolve_versionpath drives the test — exercising the correctedlatest_release()end-to-end.Test plan
cargo fmt --all --checkclean.cargo clippy --all --all-features --tests -- -D warningsclean.cargo test --tests— 87 pass. Before the fix,test_get_release_checksumandtest_install_latest_versionboth failed becauselatest_release()returned the in-progress0.16.3tag (whose Release was a draft with no uploaded assets).HEAD https://github.com/WasmEdge/WasmEdge/releases/download/0.16.3/SHA256SUM→ 404;HEAD .../releases/download/0.16.2/SHA256SUM→ 302 → 200. With the fix,latest_release()returns0.16.2.Testjob that previously hit the 60/hr API rate limit.