CompareVersions sorts a prerelease ABOVE its own stable release (1.3.1-rc.1 > 1.3.1), so rc users are never nudged back
CompareVersions (cmd/bd/doctor/version.go:276-307) has no prerelease awareness. It parses with Sscanf on .-separated integers, so a prerelease string is mis-tokenised:
"1.3.1-rc.1" -> [1, 3, 1, 1] // Sscanf reads "1-rc" as 1; the trailing ".1" becomes a 4th part
"1.3.1" -> [1, 3, 1]The four-part form therefore sorts above the three-part one:
CompareVersions("1.3.1", "1.3.1-rc.1") == -1 // i.e. the rc is treated as NEWER than its own stable releaseConsequence 1 — rc users are never told to come back
Someone who installs v1.3.1-rc.1 to help test keeps seeing bd doctor report 1.3.1-rc.1 (latest) forever, including after stable 1.3.1 ships. The rc release notes tell users to "return to the stable release through your normal channel" — but the tool that would remind them never will. An rc is by definition something you want people off once it has served its purpose, and this makes it sticky.
Consequence 2 — the stable-user guarantee rests on one gate
The property "no rc ever reaches a stable user" currently depends entirely on goreleaser marking a -rc. tag prerelease: true and GitHub's releases/latest contract excluding prereleases. Both bd doctor (cmd/bd/doctor/version.go) and scripts/install.sh resolve through releases/latest, so the server side is doing all the work.
That gate is correct today and was verified for v1.3.0-rc.2 (isPrerelease=true, releases/latest still v1.3.0). But the client has no second line of defence: if a prerelease were ever published without that flag, or if a future channel resolved tags directly rather than via releases/latest, CompareVersions would happily recommend an rc to a stable user, because it sorts the rc higher.
Suggested fix
Give CompareVersions semver-2.0 prerelease semantics:
- Split the build/prerelease suffix on
-before parsing the numeric core. - A version with a prerelease suffix sorts below the identical version without one (
1.3.1-rc.1 < 1.3.1). - Compare prerelease identifiers pairwise, numeric identifiers numerically and alphanumeric ones lexically (
rc.1 < rc.2).
Then decide the policy question separately: should bd doctor on an rc offer the newer stable release as an upgrade? Semver ordering alone gives the right answer (1.3.1 > 1.3.1-rc.1), so fixing the comparison fixes consequence 1 as a side effect.
Worth a table-driven test over at least: 1.3.1 vs 1.3.1-rc.1, 1.3.1-rc.1 vs 1.3.1-rc.2, 1.3.1-rc.2 vs 1.3.1-rc.10 (the numeric-identifier trap), 1.3.1-rc.1 vs 1.3.0, and equal-to-itself for each form.
Not a release blocker
Pre-existing, unchanged by 1.3.1, and the server-side gate holds. Filed because cutting v1.3.1-rc.1 makes consequence 1 reachable by real users for the first time in this release line.
Found while verifying the blast radius of the v1.3.1-rc.1 tag.
Source: gastownhall/beads