diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5996a76..12618a7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -109,6 +109,7 @@ jobs: RUST_VERSION=${{ matrix.rust_version }} RUST_BASE_SUFFIX=${{ matrix.rust_base_suffix }} RUST_IMAGE_DIGEST=${{ matrix.rust_image_digest }} + CLI_RUST_IMAGE_DIGEST=${{ matrix.cli_rust_image_digest }} STELLAR_CLI_REV=${{ matrix.stellar_cli_ref }} STELLAR_CLI_VERSION=${{ matrix.stellar_cli_version }} BUILD_DATE=${{ steps.meta.outputs.build_date }} diff --git a/Dockerfile b/Dockerfile index 5aa1320..2b45554 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,12 +15,17 @@ ARG RUST_VERSION ARG RUST_BASE_SUFFIX ARG RUST_IMAGE_DIGEST +# Falls back to RUST_IMAGE_DIGEST so direct `docker build` usage keeps working +# without supplying CLI_RUST_IMAGE_DIGEST. The build scripts and CI always set +# it explicitly (from cli_rust_version) so the builder stage can diverge from +# the final stage's base image. +ARG CLI_RUST_IMAGE_DIGEST=${RUST_IMAGE_DIGEST} ARG STELLAR_CLI_REV ARG STELLAR_CLI_VERSION ARG BUILD_DATE ARG SOURCE_REPO -FROM rust@${RUST_IMAGE_DIGEST} AS builder +FROM rust@${CLI_RUST_IMAGE_DIGEST} AS builder ARG STELLAR_CLI_REV ARG STELLAR_CLI_VERSION SHELL ["/bin/bash", "-eo", "pipefail", "-c"] diff --git a/builds.json b/builds.json index b3ff10e..dc01156 100644 --- a/builds.json +++ b/builds.json @@ -4,6 +4,7 @@ "default_distro": "trixie", "stellar_cli_versions": [ { + "cli_rust_version": "1.90.0-slim-bookworm@sha256:64232e656c058f4468e8d024e990acff04f0fd5a5c0a88a574dc37773d7325c9", "ref": "a048a57a75762458b487052e0021ea704a926bee", "rust_versions": [ "1.90.0-slim-bookworm@sha256:64232e656c058f4468e8d024e990acff04f0fd5a5c0a88a574dc37773d7325c9" @@ -11,6 +12,7 @@ "version": "25.1.0" }, { + "cli_rust_version": "1.95.0-slim-trixie@sha256:e14e87345b4d5964ddcc3491d27ee046a0f23820f340c3c1e24da6880141f7c0", "ref": "60f7458e7ecffddf2f2d91dc6d0d2db4fab03ecc", "rust_versions": [ "1.93.0-slim-trixie@sha256:760ad1d638d70ebbd0c61e06210e1289cbe45ff6425e3ea6e01241de3e14d08e", @@ -19,6 +21,7 @@ "version": "26.0.0" }, { + "cli_rust_version": "1.95.0-slim-trixie@sha256:e14e87345b4d5964ddcc3491d27ee046a0f23820f340c3c1e24da6880141f7c0", "ref": "1228cff8022b804659750b94b315932b0e0f3f6a", "rust_versions": [ "1.95.0-slim-trixie@sha256:e14e87345b4d5964ddcc3491d27ee046a0f23820f340c3c1e24da6880141f7c0" diff --git a/builds.schema.json b/builds.schema.json index 05b116c..2b7585d 100644 --- a/builds.schema.json +++ b/builds.schema.json @@ -40,12 +40,16 @@ "items": { "additionalProperties": false, "properties": { + "cli_rust_version": { + "$ref": "#/definitions/rust_pin", + "description": "Fully-qualified rust base pin (@) to build this stellar-cli release - not the same as the rustc used to compile contracts" + }, "ref": { "$ref": "#/definitions/git_sha", "description": "Upstream stellar/stellar-cli git commit SHA for this release. Source of truth; version is metadata." }, "rust_versions": { - "description": "Append-only list of fully-qualified rust base pins (@) this stellar-cli release was ever built against. Refreshes append the picker's freshly-resolved pins; previously-published pins are retained so the file stays consistent with the immutable tags in the registry. The same label may appear more than once with distinct digests (e.g. a rebuilt base) — each pin is its own immutable image.", + "description": "Append-only list of fully-qualified rust base pins (@) this stellar-cli release was ever built against. Refreshes append the picker's freshly-resolved pins; previously-published pins are retained so the file stays consistent with the immutable tags in the registry. The same label may appear more than once with distinct digests (e.g. a rebuilt base) \u2014 each pin is its own immutable image.", "items": { "$ref": "#/definitions/rust_pin" }, diff --git a/scripts/build_image.py b/scripts/build_image.py index 5057a46..27d3636 100755 --- a/scripts/build_image.py +++ b/scripts/build_image.py @@ -36,6 +36,9 @@ def main(argv: list[str] | None = None) -> int: ) stellar_ref = builds.stellar_cli_ref(data, args.stellar_cli_version) parsed = rust_keys.parse(args.rust_version) + entry = builds.find_cli(data, args.stellar_cli_version) + cli_rust_pin = entry.get("cli_rust_version") if entry else None + cli_rust_digest = builds.digest_of(cli_rust_pin) if cli_rust_pin else rust_digest except ValueError as exc: common.die(str(exc)) @@ -48,6 +51,7 @@ def main(argv: list[str] | None = None) -> int: common.log(f"building {tag}") common.log(f" stellar-cli {args.stellar_cli_version} ({stellar_ref})") common.log(f" rust {args.rust_version} ({rust_digest})") + common.log(f" cli-build rust ({cli_rust_digest})") common.log(f" base rust:{parsed.version}-{parsed.suffix}") common.log(f" platform {args.platform or ''}") @@ -63,6 +67,8 @@ def main(argv: list[str] | None = None) -> int: "--build-arg", f"RUST_IMAGE_DIGEST={rust_digest}", "--build-arg", + f"CLI_RUST_IMAGE_DIGEST={cli_rust_digest}", + "--build-arg", f"STELLAR_CLI_REV={stellar_ref}", "--build-arg", f"STELLAR_CLI_VERSION={args.stellar_cli_version}", diff --git a/scripts/resolve_matrix.py b/scripts/resolve_matrix.py index a980d48..df373ff 100755 --- a/scripts/resolve_matrix.py +++ b/scripts/resolve_matrix.py @@ -26,6 +26,8 @@ def build_matrix(data: dict, only_cli: str = "") -> dict: if only_cli and cli != only_cli: continue ref = entry["ref"] + cli_rust_pin = entry.get("cli_rust_version") + cli_rust_image_digest = builds.digest_of(cli_rust_pin) if cli_rust_pin else None # The published tag is label-only, so only the newest pin per label is # built — the last occurrence in rust_versions wins. builds.json keeps # the superseded pins as history; they are not rebuilt or republished. @@ -38,6 +40,7 @@ def build_matrix(data: dict, only_cli: str = "") -> dict: rows.append( { "arch": arch, + "cli_rust_image_digest": cli_rust_image_digest or digest, "platform": f"linux/{arch}", "rust_base_id": rust_base_id, "rust_base_key": label, diff --git a/tests/unit/test_resolve_matrix.py b/tests/unit/test_resolve_matrix.py index f79055f..51e656e 100644 --- a/tests/unit/test_resolve_matrix.py +++ b/tests/unit/test_resolve_matrix.py @@ -28,6 +28,7 @@ def test_build_matrix_row_carries_expected_keys(minimal_builds: dict) -> None: row = matrix["include"][0] assert set(row.keys()) == { "arch", + "cli_rust_image_digest", "platform", "rust_base_id", "rust_base_key",