Fix two version-comparison bugs in cryptohopper upgrade#7
Merged
pimfeltkamp merged 1 commit intomainfrom Apr 28, 2026
Merged
Conversation
Bug 1: alpha.10 < alpha.2
compareVersions used String#localeCompare on the full prerelease
string, so "alpha.10" sorts before "alpha.2" alphabetically. SemVer
2.0.0 specifies dot-separated identifiers, with numeric ones compared
numerically. Adds a comparePrerelease helper that splits on "." and
applies the SemVer rules:
- all-digit identifiers compared numerically
- mixed/letter identifiers compared lexically
- numeric identifiers always have lower precedence than non-numeric
- longer-prefix-matching set wins
Bug 2: fetchLatestRelease relied on GitHub's created_at order
GitHub returns /releases sorted by created_at desc, which usually
matches version order — but a hot-fix tag pushed after a newer
release inverts that. Now sorts the filtered cli-v* list by version
(highest first) using the now-correct compareVersions, so the latest
is always the highest version regardless of publication order.
Verified with a 9-case matrix covering: alpha.10 vs alpha.2 both
directions, equality, release vs prerelease both directions, minor
bumps, alpha vs beta vs rc, and longer-prefix prereleases. typecheck
and build are clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
pimfeltkamp
added a commit
that referenced
this pull request
Apr 28, 2026
The 0.6.0-alpha.2 entry only mentioned the auth-fix dep bump from #9. PRs #7 (cryptohopper upgrade version-comparison) and #8 (OAuth browser-flow state validation + token-exchange timeout) also landed on main without their own CHANGELOG lines. Folding all four bug fixes under the same release since none has shipped yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Why
Iter-35 audit of
src/upgrade/github-release.tsfound two bugs that haven't bitten yet because the CLI is at0.6.0-alpha.1and tags are pushed in order — but they will the moment we crossalpha.10, ship a hotfix, or both.Bug 1:
alpha.10 < alpha.2compareVersionsfalls through toString#localeCompareon the entire prerelease tail. That's alphabetic — so"alpha.10"sorts before"alpha.2"because the second character (1vs2) is smaller.Reproduction (against the unpatched code):
User-visible effect once we ship
cli-v0.6.0-alpha.10: anyone oncli-v0.6.0-alpha.2runscryptohopper upgrade, the SDK fetches the new release, the comparison says it's older, and the tool prints "✓ cryptohopper is up to date" — silently refusing the upgrade.Fix
Adds
comparePrereleasethat follows SemVer 2.0.0 §11:Bug 2:
fetchLatestReleasetrusts GitHub'screated_atorderGitHub's
/releasesAPI returns releases sorted by creation date, descending. For sequential tag pushes that matches version order. But:cli-v0.7.0-alpha.1, then a security hotfix on the older line ascli-v0.6.1-alpha.1.cliReleases[0]is now0.6.1-alpha.1because it was created last.compareVersions(cli-v0.7.0-alpha.1, cli-v0.6.1-alpha.1) > 0says the user is ahead, soupgradedoes nothing — even though there is a newer-numbered release sitting at index 1.0.6.0could be told they're on the latest becausecliReleases[0]happens to be0.6.1-prerelease and the user is technically newer. They'd never see0.7.0.Fix
Sort the filtered
cli-v*list by version (highest first) with the now-correctcompareVersions, then return the first element. Robust against anycreated_atorder.Test plan
9-case matrix run with
tsx:npm run typecheckandnpm run buildboth clean. The CLI doesn't currently have a vitest setup; would happily wire one up in a follow-up if you want these to live as unit tests.Compatibility
No public API change.
compareVersionsandversionFromTagkeep their signatures. The newcomparePrereleaseis module-private. The only behavior change is for the corner cases that were broken — every previously-correct case still returns the same sign.