From 525dbd6e88815e51192df24d57dfd8921e6afcb4 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Sun, 26 Jul 2026 13:55:42 +0200 Subject: [PATCH] chore(release): cut 0.37.0 and version the chart with the operator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0.36.0 is abandoned. Its tag was pushed at f56f7ed without a version bump, so the release gate failed (workspace 0.35.0 != tag 0.36.0) and nothing was published: the crates.io job failed on the gate, CI skipped release-cli and never ran the image push, and every package publisher was cancelled. The v0.36.0 GitHub release was also created by hand, which — with immutable releases on this repo — can lock the release and its tag, so the number is skipped rather than re-cut. Chart versioning changes with this release: the chart ships from the same `v*` tag as the operator, so `version:` == `appVersion:` == the workspace version. One-time jump for the chart, 0.21.19 -> 0.37.0 (monotonic, so helm accepts it; nothing pins the chart by version — int-pro installs it by path from its GitRepository). - `just bump X.Y.Z` now rewrites the chart's `version:` as well as `appVersion:` - the version gate asserts it, alongside appVersion and nix/package.nix A chart-only fix is therefore a patch release of the whole thing. It is deliberately NOT an `X.Y.Z-1` suffix: semver reads `-1` as a PRERELEASE of X.Y.Z, so it would sort BELOW the release it means to fix and helm hides it from search and dependency resolution unless --devel is passed. Build metadata (`X.Y.Z+1`) is no better — ignored for precedence, so `helm upgrade` would not see it as newer, and OCI tags cannot carry `+`. --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- charts/kobe/Chart.yaml | 4 ++-- justfile | 13 +++++++++---- scripts/check-version-consistency.sh | 24 ++++++++++++++++++------ 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa6df0c..eea34ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2656,7 +2656,7 @@ dependencies = [ [[package]] name = "kobe-operator" -version = "0.35.0" +version = "0.37.0" dependencies = [ "anyhow", "async-trait", @@ -2717,7 +2717,7 @@ dependencies = [ [[package]] name = "kobectl" -version = "0.35.0" +version = "0.37.0" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 1416ffc..5f575de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ resolver = "3" # CLI so they always publish in lockstep. `just bump X.Y.Z` rewrites this; the # version-consistency gate enforces tag == this == Chart.yaml at release time. [workspace.package] -version = "0.35.0" +version = "0.37.0" edition = "2024" rust-version = "1.94.1" license = "Apache-2.0" diff --git a/charts/kobe/Chart.yaml b/charts/kobe/Chart.yaml index b9930d6..2331af5 100644 --- a/charts/kobe/Chart.yaml +++ b/charts/kobe/Chart.yaml @@ -4,8 +4,8 @@ description: >- Kubernetes operator for instant cluster provisioning via warm pools. Supports multiple backends: k3s, k0s, CAPI, and kobe-sync. type: application -version: 0.21.19 -appVersion: "0.35.0" +version: 0.37.0 +appVersion: "0.37.0" keywords: - kubernetes - operator diff --git a/justfile b/justfile index d84f630..f5417e0 100644 --- a/justfile +++ b/justfile @@ -146,8 +146,12 @@ coverage-open: clean: cargo clean -# Bump the release version across the workspace + Chart.yaml appVersion in -# lockstep, then verify consistency. Usage: just bump 0.32.0 (or 0.32.0-rc.1) +# Bump the release version across the workspace + Chart.yaml version and +# appVersion in lockstep, then verify consistency. The chart ships with the +# operator on the same `v*` tag, so all three move together — a chart-only fix +# is a patch release of the whole thing, NOT a `-1` suffix (semver reads that as +# a prerelease, so it would sort BELOW the release it fixes and be hidden from +# `helm search` / dependency resolution). Usage: just bump 0.32.0 (or 0.32.0-rc.1) [group('release')] bump VERSION: #!/usr/bin/env bash @@ -165,9 +169,10 @@ bump VERSION: fi # Sets [workspace.package].version; both kobe-operator and kobectl inherit. cargo set-version --workspace "{{ VERSION }}" - # Mirror into the chart's appVersion (the chart's own `version:` is decoupled - # and bumped separately when the chart itself changes). + # Mirror into the chart's appVersion AND its own `version:` — the chart is + # published from the same release tag, so both track the operator version. perl -i -pe 's/^appVersion:.*$/appVersion: "{{ VERSION }}"/' charts/kobe/Chart.yaml + perl -i -pe 's/^version:.*$/version: {{ VERSION }}/' charts/kobe/Chart.yaml cargo update -p kobe-operator -p kobectl --precise "{{ VERSION }}" 2>/dev/null || true ./scripts/check-version-consistency.sh echo "Bumped to {{ VERSION }}. Review the diff, commit, then \`just release\`." diff --git a/scripts/check-version-consistency.sh b/scripts/check-version-consistency.sh index f763c06..c5271f2 100755 --- a/scripts/check-version-consistency.sh +++ b/scripts/check-version-consistency.sh @@ -8,11 +8,16 @@ # (`[workspace.package].version`), inherited by both `kobe-operator` and the # published `kobectl` crate. The places that must mirror it: # - charts/kobe/Chart.yaml `appVersion` (the app/operator release version) +# - charts/kobe/Chart.yaml `version` (the chart ships on the same tag) # - nix/package.nix `version` (only if the file exists) # -# NOTE: the chart's own `version:` is INTENTIONALLY decoupled — kobe versions the -# Helm chart on its own track (e.g. chart 0.21.x while appVersion is 0.31.x), so -# it is deliberately NOT gated here. +# NOTE: the chart's own `version:` used to be on its own track (chart 0.21.x while +# appVersion was 0.31.x). As of 0.36.0 the chart is published from the same `v*` +# release tag as the image, so it is gated here too and `just bump` moves both. +# A chart-only fix is therefore a patch release of the whole thing — NOT a +# `X.Y.Z-1` suffix, which semver reads as a PRERELEASE of X.Y.Z (it sorts below +# the release it means to fix, and helm hides it from search / dependency +# resolution without --devel). # The binary's --version comes from BUILD_VERSION= at build time; the tag is # a checked mirror of the manifest. # @@ -76,13 +81,20 @@ def chart_field(name): mm = re.search(rf'(?m)^{name}:\s*"?([^"\s]+)"?\s*$', chart) return mm.group(1) if mm else None -# Only appVersion is gated; the chart's own `version:` is decoupled on purpose. chart_appversion = chart_field("appVersion") if chart_appversion is None: errors.append("charts/kobe/Chart.yaml has no `appVersion:`") elif chart_appversion != ws_version: errors.append(f"Chart.yaml appVersion {chart_appversion!r} != workspace version {ws_version!r}") +# The chart is published from the same release tag, so its own `version:` tracks +# the operator version too. +chart_version = chart_field("version") +if chart_version is None: + errors.append("charts/kobe/Chart.yaml has no `version:`") +elif chart_version != ws_version: + errors.append(f"Chart.yaml version {chart_version!r} != workspace version {ws_version!r}") + # --- nix/package.nix version (optional) --- nix_pkg = root / "nix" / "package.nix" if nix_pkg.exists(): @@ -104,7 +116,7 @@ if errors: sys.exit(1) if tag_version: - print(f"version consistency OK: tag {tag_version} == workspace == Chart.yaml appVersion") + print(f"version consistency OK: tag {tag_version} == workspace == Chart.yaml version + appVersion") else: - print(f"version consistency OK: workspace == Chart.yaml appVersion == {ws_version}") + print(f"version consistency OK: workspace == Chart.yaml version + appVersion == {ws_version}") PY