Skip to content

Resolve versions by SemVer precedence instead of trusting index order - #1

Open
igorlamos wants to merge 1 commit into
devfrom
fix/semver-ordered-version-resolution
Open

Resolve versions by SemVer precedence instead of trusting index order#1
igorlamos wants to merge 1 commit into
devfrom
fix/semver-ordered-version-resolution

Conversation

@igorlamos

Copy link
Copy Markdown
Contributor

display_remote_versions piped the index straight to grep, and get_latest_resolved_version keeps the first match β€” so which version be installs depended entirely on the order the index arrived in. Nothing promises that order.

The GitHub Releases API sorts by created_at, and every release in beplus/cli shares one: gh release create runs without --target, so all the tags point at that repo's unchanged default-branch HEAD. The whole list ties and comes back arbitrarily. In practice be 2 was resolving to a stage build published before the prod one, and be --latest would pick between v1 and v2 arbitrarily once a second full release existed.

What changed

Sort candidates by SemVer Β§11 before filtering:

  • major, minor, patch numerically;
  • then "has no pre-release" β€” a release outranks the pre-releases it was promoted from;
  • then the pre-release identifiers, with numeric ones compared numerically and ranked below alphanumeric ones, and a longer run of identifiers winning a shared prefix.

A name that is not a version sorts last rather than aborting the pipeline.

This is not sort -V: GNU version sort ranks 2.0.0-dev.40 above 2.0.0, which is backwards for a promotion pipeline. The comparison is done in jq, which the script already requires, so there is no new dependency.

Verification

test/tests/ordering.bats runs against a deliberately scrambled index served over file://. Five of the seven fail without the sort; the two that pass on both are the regression guards (an exact version still resolves to itself, a non-version name does not break the pipeline).

ORIGINAL  be 2 -> 2.0.0-dev.29    be --latest -> 1.0.5
PATCHED   be 2 -> 2.0.0           be --latest -> 2.0.0

The existing lsr.bats suite still passes against the live index. BE_RELEASE_INDEX_URL is now unset in unset_n_env so a fixture cannot leak between tests.

Sequencing

This is defence in depth. The index that be reads is being fixed at the producer in beplus/cli_v2#28 β€” sorted, and built from the bucket it is written to rather than from a global GitHub dump β€” and that lands on every be already installed with no rollout. Merge this after that one is live.

πŸ€– Generated with Claude Code

`display_remote_versions` piped the index straight to grep and callers kept the
first match, so resolution depended entirely on the order the index arrived in.
Nothing promises that order. The GitHub Releases API sorts by created_at, and
every beplus/cli release shares one β€” the tags all point at that repo's
unchanged default-branch HEAD β€” so the list ties and comes back arbitrarily.
`be 2` was resolving to a stage build published before the prod one, and
`be --latest` could pick an older major once two full releases existed.

Sort by SemVer Β§11 before filtering: major, minor, patch, then "has no
pre-release" (a release outranks the pre-releases it was promoted from), then
the pre-release identifiers β€” numeric ones compared numerically and ranked
below alphanumeric ones, a longer run winning a shared prefix. A name that is
not a version sorts last rather than aborting the pipeline.

Note this is not `sort -V`: GNU version sort ranks 2.0.0-dev.40 above 2.0.0,
which is backwards for a promotion pipeline.

The new tests run against a deliberately scrambled index; five of the seven
fail without the sort.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@igorlamos igorlamos self-assigned this Sep 12, 2026
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