Repository navigation
fix: Install plugins that publish only pre-releases - #361
Merged
Merged
Conversation
GitHub never marks a pre-release as the latest release, so for a repository with only pre-releases the releases/latest URL redirects to the release list. The installer took the last path segment of that URL as the tag and failed with an unexpected tag format error naming "releases". The installer now reads the tag only from a releases/tag/<tag> redirect. When there is no latest release it lists the repository's releases through the GitHub API and picks the highest semantic version tag, skipping drafts. Plugin upgrade uses the same lookup, so a pre-release install upgrades to newer pre-releases. Tags must now be valid semantic versions, and errors name the rejected tag, the accepted format, and how to pin a release with owner/repo@<tag>. Fixes #356 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0xmc
enabled auto-merge
November 6, 2026 19:17
ecv
approved these changes
Nov 6, 2026
ecv
left a comment
Contributor
There was a problem hiding this comment.
Approve.
"Latest" still resolves to the release GitHub marks latest, and the pre-release listing is used only when that redirect says no stable release exists, so a stable release is never displaced by a pre-release. Checksum and signature verification take the resolved tag and are untouched.
- Fallback ordering is right:
fetchLatestTagreturns the stable tag whenever one exists and only then calls the API. Drafts are skipped, andsemver.Compareranks-rc.1above-beta.2correctly and ignores build metadata (two tags differing only in+buildtie, first listed wins). - Pagination: only the first 100 releases are read and
Linkis not followed. For a repo with more than 100 pre-releases the true highest could sit on a later page, though the API lists newest first so it is rarely wrong in practice. semver.IsValidis now enforced on the stable path too. A stable repo whose latest tag is not semver (for examplevNextorv1.2.3.4) used to install and now errors out. That is stricter and safer for the path-derived tag, but it is a behaviour change.
Follow-ups:
- Print a notice when the fallback picks a pre-release, so a user who typed an unpinned install knows they got
v1.0.0-preview.28rather than a stable build. - Follow
Link: rel=nextpages, or stop at the first page and say so in the error. - Unauthenticated API calls are limited to 60 per hour per IP; the error already carries the
owner/repo@<tag>pin hint, which is the right fallback.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Installing a plugin by repository failed when the repository had only pre-releases, with an error naming "releases" as the tag.
GitHub never marks a pre-release as latest, so the installer misread the release list page as a tag.
The installer now falls back to the newest pre-release, and upgrades follow newer pre-releases the same way. When nothing installable exists, the error names the tags it found and shows how to pin a version.
Test plan
Fixes #356
🤖 Generated with Claude Code