Repository navigation
fix: derive the reported version from the release tag - #13
Open
jeroenrinzema wants to merge 1 commit into
Open
jeroenrinzema wants to merge 1 commit into
jeroenrinzema wants to merge 1 commit into
Conversation
brainpod --version printed 0.1.0 for every published release because Cargo.toml hardcoded that version and releases are tagged only in git, so the tag never reached the crate. The release workflow now derives the version from the tag, writes it to VERSION, and flake.nix passes it to the build as BRAINPOD_VERSION, which build.rs re-exports for clap. VERSION sits outside the crane source filter, so stamping a release does not invalidate cargoArtifacts and only the crate itself rebuilds. A malformed or empty tag fails the release, and both workflows run the binary they just built and fail if its reported version disagrees.
jeroenrinzema
force-pushed
the
fix/report-release-version
branch
from
September 21, 2026 20:44
f78bd8c to
f31a032
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
brainpod --versionprintedbrainpod 0.1.0for every release ever published, carrying no information about which build a user was running.Cargo.tomlhardcodedversion = "0.1.0"and releases are versioned only by git tag, so the tag never reached the crate.How the version now travels
The release tag is the single source of truth, and it reaches the compiler through a
VERSIONfile rather thanCargo.toml:release.ymlstrips the leadingvfromgithub.event.release.tag_name, validates it as semver, and writes it toVERSION.flake.nixreadsVERSIONand passes it into the derivation asBRAINPOD_VERSION.build.rsre-exports it so#[command(version = env!("BRAINPOD_VERSION"))]picks it up.Cargo.tomldrops to0.0.0because it is no longer the release version, withCargo.lockkept consistent so--lockedbuilds still resolve. Unstamped builds report0.0.0-dev, plus the commit they were built from when git metadata is reachable, so a local binary can never be mistaken for a published one.Why
VERSIONand notCargo.tomlRewriting
Cargo.tomlper release is the obvious approach, but the manifest is inside the crane source filter and is also read directly viacargoTomlContents, so every release would changecargoArtifactsand rebuild the whole dependency set on all four runners.VERSIONsits outside that filter. Verified by evaluating the derivations before and after a version rewrite, on both a native and a cross target:VERSION=0.0.0-devVERSION=0.0.6…-brainpod-cli-deps-0.0.0.drv…-brainpod-cli-deps-x86_64-unknown-linux-musl-0.0.0.drv…-brainpod-cli-0.0.0-dev.drv…-brainpod-cli-0.0.6.drvOnly the crate itself rebuilds. This also keeps the
hashFiles('flake.nix', 'flake.lock', 'Cargo.lock')Nix store cache key stable across releases, and avoids needingcargo-editon the runners.One note on
build.rsbuild.rspreviously emitted nocargo:rerun-if-*directives, so Cargo's default applied: rerun the script whenever any file in the package changes. Addingrerun-if-env-changedforBRAINPOD_VERSIONwould have silently narrowed that to only the env var and stopped the protobufs from regenerating when a.protochanged, socargo:rerun-if-changed=protois emitted alongside it.The regression gate
This bug shipped five times because nothing verified it. Both workflows now run the binary they just built and compare
--versionagainst what it should be — the tag inrelease.yml, theVERSIONplaceholder inbuild.yml. In the release workflow this runs afternix buildand before the artifact is packaged or uploaded, so a mismatching binary never reaches a release.A malformed or empty tag fails the job at its first step rather than shipping another wrong version. Rejected:
v1.2,v1.2.3.4,release-1, empty. Accepted:v1.2.3,1.2.3,v1.2.3-rc.1.The check runs on all four matrix entries, including
x86_64-darwin, which is built on an arm64macos-14runner: the same Rosetta path that lets Nix build that target also runs the resulting binary. If it were ever unavailable, the step fails loudly with a distinct "could not run" error rather than silently skipping.Verified locally
nix flake check --all-systems --no-buildpasses.nix buildon a checkout with no tag →brainpod 0.0.0-dev. Git is unreachable inside the builder and.gitis not in the source filter, so the placeholder is deterministic, which is whatbuild.ymlasserts.0.0.6toVERSIONunstaged, exactly as the workflow does →brainpod 0.0.6, with onlybrainpod-cli-0.0.6.drvbuilt and dependencies reused. Nix reads a tracked file's working-tree content, so the workflow needs nogit add.aarch64-darwinbuild succeeds, so itspostFixupassertion still holds;otool -Lon the result shows no/nix/store/dependency.cargo build→brainpod 0.0.0-dev+d4ac6679d0b4, matchingHEAD, refreshing on the next commit.BRAINPOD_VERSION=0.0.6 cargo build→brainpod 0.0.6.brainpod describe --jsonreports the same version incliVersion.rustfmt --checkandnixfmt-rfc-style --checkare clean on the changed files.Retroactively correcting the already-published
v0.0.1–v0.0.5artifacts is out of scope.