From 3ec287413828cea4e9a8604a0066566539b74b70 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Thu, 18 Jun 2026 11:06:59 -0700 Subject: [PATCH] Resolve alias target for releases on older distros. --- scripts/lib/builds.py | 17 ++++++++++++----- scripts/publish_aliases.py | 6 ++++-- tests/unit/test_builds.py | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/scripts/lib/builds.py b/scripts/lib/builds.py index 3d169a6..a0167bd 100644 --- a/scripts/lib/builds.py +++ b/scripts/lib/builds.py @@ -89,16 +89,23 @@ def derive_default_rust(data: dict[str, Any], cli: str) -> str: entry = find_cli(data, cli) if entry is None: raise ValueError(f"unknown stellar-cli version: {cli}") + pins = entry.get("rust_versions", []) + if not pins: + raise ValueError(f"stellar-cli {cli} declares no rust_versions[] pins") matches = [ (semver.parse(rust_keys.version_of(label_of(pin))), idx, pin) - for idx, pin in enumerate(entry.get("rust_versions", [])) + for idx, pin in enumerate(pins) if label_of(pin).endswith(f"-{suffix}") ] if not matches: - raise ValueError( - f"no rust_versions[] pin matches default_distro {distro!r} " - f"(suffix {suffix!r}) for stellar-cli {cli}" - ) + # A release predating the current default_distro (e.g. a bookworm-only + # back-port published after the repo switched to trixie) has no pin + # matching the default suffix. Fall back to the release's own pins so + # its `:` alias still resolves, instead of failing the publish. + matches = [ + (semver.parse(rust_keys.version_of(label_of(pin))), idx, pin) + for idx, pin in enumerate(pins) + ] # Highest rust version wins; among equal versions (a relabelled base), the # last-appended pin — the freshest digest — wins. matches.sort(key=lambda t: (t[0], t[1])) diff --git a/scripts/publish_aliases.py b/scripts/publish_aliases.py index 2bc357e..3d7c968 100755 --- a/scripts/publish_aliases.py +++ b/scripts/publish_aliases.py @@ -2,8 +2,10 @@ """Re-point the `:` (and `:latest` if newest) tags at the default rust pair. The default rust pair is the highest-version rust_versions[] key whose -suffix matches `slim-`. `:latest` is re-pointed only if -this cli is the newest declared one in builds.json. +suffix matches `slim-`; a release predating the current +default_distro (no matching suffix) falls back to its own highest pin. +`:latest` is re-pointed only if this cli is the newest declared one in +builds.json. """ import argparse diff --git a/tests/unit/test_builds.py b/tests/unit/test_builds.py index eff3654..faa0766 100644 --- a/tests/unit/test_builds.py +++ b/tests/unit/test_builds.py @@ -126,10 +126,37 @@ def test_derive_default_rust_newest_digest_for_repeated_label() -> None: assert builds.derive_default_rust(data, "26.0.0") == newest -def test_derive_default_rust_skips_non_matching_suffix(multi_cli_builds: dict) -> None: - # 25.1.0 has only bookworm; default_distro is trixie → no match. +def test_derive_default_rust_falls_back_when_no_suffix_match(multi_cli_builds: dict) -> None: + # 25.1.0 has only bookworm; default_distro is trixie → no suffix match, + # so it falls back to the release's own highest pin instead of failing. + pin = builds.derive_default_rust(multi_cli_builds, "25.1.0") + assert builds.label_of(pin).endswith("-slim-bookworm") + + +def test_derive_default_rust_fallback_picks_highest_version() -> None: + # Fallback still honours highest-version-wins across mixed non-default pins. + older = "1.89.0-slim-bookworm@sha256:" + "a" * 64 + newer = "1.90.0-slim-bookworm@sha256:" + "b" * 64 + data = { + "default_distro": "trixie", + "stellar_cli_versions": [ + { + "ref": "a" * 40, + "version": "25.1.0", + "rust_versions": [older, newer], + } + ], + } + assert builds.derive_default_rust(data, "25.1.0") == newer + + +def test_derive_default_rust_no_pins(multi_cli_builds: dict) -> None: + data = { + "default_distro": "trixie", + "stellar_cli_versions": [{"ref": "a" * 40, "version": "25.1.0", "rust_versions": []}], + } with pytest.raises(ValueError, match="no rust_versions"): - builds.derive_default_rust(multi_cli_builds, "25.1.0") + builds.derive_default_rust(data, "25.1.0") def test_derive_default_rust_missing_default_distro(multi_cli_builds: dict) -> None: