From f7dabafb65383e4e2d3ef91419641e9aa35fde89 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Thu, 17 Sep 2026 13:22:29 -0400 Subject: [PATCH] build: single-source the version in a VERSION file The version was duplicated across CMakeLists.txt (project(VERSION ...)), package.nix (the Nix flake added recently), and debian/changelog, with nothing keeping them in sync, so a release bump could easily ship a mislabeled artifact. Introduce a top-level VERSION file as the single source of truth: - CMakeLists.txt reads it via file(STRINGS) and passes it to project(), so MITHRIL_VERSION still flows from PROJECT_VERSION. - package.nix reads the same file via lib.fileContents. debian/changelog cannot derive its value (dpkg needs a literal and it carries its own -N Debian revision plus changelog history), so the release workflow gains a Version consistency step that fails the build if the git tag or debian/changelog upstream version disagrees with VERSION. CMake and Nix derive from VERSION and cannot drift. Cutting a release is now: edit VERSION, add a debian/changelog stanza, tag v. Verified the version flows end to end (binary reports VERSION) and the full suite stays green. --- .github/workflows/release.yml | 15 +++++++++++++++ CMakeLists.txt | 5 ++++- VERSION | 1 + package.nix | 3 ++- 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 VERSION diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c74a9ed..cbf127d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,6 +39,21 @@ jobs: steps: - uses: actions/checkout@v4 + # VERSION is the single source of truth (CMakeLists.txt and package.nix both + # read it). The git tag and debian/changelog carry the number independently, + # so fail the release if either drifts from VERSION rather than shipping a + # mislabeled artifact. + - name: Version consistency + run: | + ver="$(cat VERSION)" + if [ "v$ver" != "$GITHUB_REF_NAME" ]; then + echo "::error::git tag $GITHUB_REF_NAME does not match VERSION (v$ver)"; exit 1 + fi + deb="$(sed -n '1s/.*(\([^-)]*\).*/\1/p' debian/changelog)" + if [ "$deb" != "$ver" ]; then + echo "::error::debian/changelog version $deb does not match VERSION $ver"; exit 1 + fi + # mithril is stdlib-only C++20: just a compiler, CMake, and python3 for the # test gate. No compression or other libraries. - name: Install build dependencies (apt) diff --git a/CMakeLists.txt b/CMakeLists.txt index 24e6eaf..8e214d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 3.20) -project(mithril VERSION 0.2.1 LANGUAGES CXX) +# The version lives once, in the top-level VERSION file. package.nix reads the +# same file; debian/changelog and the git tag are checked against it in CI. +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION_STRING) +project(mithril VERSION ${VERSION_STRING} LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..0c62199 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.2.1 diff --git a/package.nix b/package.nix index b3a7bb0..0d0d405 100644 --- a/package.nix +++ b/package.nix @@ -6,7 +6,8 @@ }: stdenv.mkDerivation { pname = "mithril"; - version = "0.2.1"; + # Single source of truth: the top-level VERSION file (CMakeLists.txt reads it too). + version = lib.fileContents ./VERSION; src = ./.; nativeBuildInputs = [