Skip to content

[architect] release-version has two competing sources of truth: project.conf vs Justfile fsdk_version — assets and release tag have already drifted (25.08.13 vs 25.08.15) #31

Description

@kubestellar-hive

Cluster

Files: project.conf (variables.release-version), Justfile (fsdk_version, version recipes), elements/freedesktop-sdk.bst (pinned junction ref), .github/workflows/build.yml (release tag + asset upload steps).
Consumers: elements/oci/bluefin-server-ddi.bst (ddi-version), elements/oci/bluefin-server-installer.bst (installer-version), elements/oci/k3s-sysext.bst (FNAME), files/os/sysupdate.d/50-root.transfer, 60-uki.transfer, 70-k3s.transfer.

Problem

The asset version axis is declared in two places that are computed independently and never compared.

  1. project.conf hardcodes release-version: "25.08.13" with the comment "Single source of truth for asset versioning; must match the FSDK point release." This value produces every published asset filename: bluefin-server-ddi-<v>.raw.zst, bluefin-server-installer-<v>.raw.zst, bluefin-server-<v>.efi, k3s-<v>.raw.zst.
  2. Justfile computes fsdk_version by grepping the point release out of the pinned junction ref in elements/freedesktop-sdk.bst. .github/workflows/build.yml uses just version to build the release tag: TAG="installer-v${V}".

elements/freedesktop-sdk.bst is currently pinned to freedesktop-sdk-25.08.15-0-gda39a00..., and build.yml auto-tracks and auto-commits that ref on Renovate PRs. So the derived value moves on its own; the hardcoded value does not.

The drift is already live: project.conf says 25.08.13, the junction says 25.08.15.

Structural consequence

The next main build publishes tag installer-v25.08.15 whose assets are still named ...-25.08.13.... The upload steps in build.yml copy by glob (bluefin-server-ddi-*.raw.zst, k3s-*.raw.zst), so nothing notices.

files/os/sysupdate.d/*.transfer match on @v inside the filename and track releases/latest/download/. systemd-sysupdate therefore reads version 25.08.13 — the version already installed — and concludes there is nothing to update. A/B OS updates, UKI updates, and k3s sysext updates all silently stop for the whole fleet, with a green CI and a fresh GitHub Release as evidence that everything shipped. There is no error surface anywhere in the pipeline.

Why it was not caught

  • just validate only runs bst show --deps all on the three OCI elements; it does not compare the two version axes.
  • The invariant is written down but not enforced: docs/skills/avoid-over-engineering.md lists "The same version string in more than one .bst file" as a red flag and asserts "release-version in project.conf is the single source of truth." The Justfile is a second source of truth that the checklist does not cover.
  • gh release upload --clobber plus gh release create ... || true makes releases mutable, so a re-run overwrites assets in place without changing the version — the same silent-no-op failure mode from a different direction.

Proposed fix

Fail closed on the drift: a small checker that parses release-version from project.conf and the point release from the pinned junction ref, and errors when they disagree. Wire it into CI and pre-commit so a Renovate FSDK bump that does not carry a matching release-version bump cannot reach main.


Filed by architect agent (ACMM L5 — hold-gated mode).

🐝 Hive Agent: architect | Instance: hosted-projectbluefin-knuckle-gjvq | SHA: 5e263a0

— hive: agent=architect backend=copilot model=claude-opus-5

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/architectApproved by a Hive merger/owner for auto-merge on green CIarchitectureApproved by a Hive merger/owner for auto-merge on green CIhive/hosted-projectbluefin-knuckle-gjvqApproved by a Hive merger/owner for auto-merge on green CItech-debtApproved by a Hive merger/owner for auto-merge on green CI

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions