From f999e9115d44b474fdf3fd56db0da2091db0450f Mon Sep 17 00:00:00 2001 From: dkcumming Date: Tue, 14 Jul 2026 19:35:40 +0200 Subject: [PATCH 1/6] Updates to master-push.yml and version.sh - `master` branch now has all versions as sentinel 0.0.0; - master-push.yml on `release` branch will read previous version from that branch, conflicts will default to `release` so 0.0.0 is never merged from `master` to `release`; - Commit trailer "Bump: {major, minor, patch}" now instruct how to bump the version - version.sh updated to take argument stripped from commit trailer - TODO: write out docs/dev/releasing.md at the end --- .github/workflows/master-push.yml | 26 +++++++++++++++++--------- package/version.sh | 25 ++++++++++++------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/.github/workflows/master-push.yml b/.github/workflows/master-push.yml index a836b6312..5ba504eb2 100644 --- a/.github/workflows/master-push.yml +++ b/.github/workflows/master-push.yml @@ -34,17 +34,25 @@ jobs: - name: 'Update release branch with current master' run: | git checkout -B release origin/release + # The release branch owns the version counter. master carries sentinel + # 0.0.0 and should not be changed by any scripts. Release branch reads + # the prior version (from release) and bumps it. `--strategy-option=ours` + # keeps the release branch's version files when they conflict with master. + # See docs/dev/releasing.md prior_version=$(cat package/version) - old_master="$(git merge-base origin/master origin/release)" - new_master="$(git rev-parse origin/master)" - # otherwise bump the prior_version - if git diff --exit-code ${old_master} ${new_master} -- package/version; then - git merge --no-edit origin/master - package/version.sh bump ${prior_version} - else - # if the version has changed on master, use it unmodified - git merge --no-edit --strategy-option=theirs origin/master + + # Choose the bump level from `Bump:` trailers on the new master commits + # (defaults to patch; major wins over minor wins over patch). + new_commits="origin/release..origin/master" + if git log --format='%B' "${new_commits}" | grep -qiE '^[[:space:]]*Bump:[[:space:]]*major[[:space:]]*$'; then + bump_level=major + elif git log --format='%B' "${new_commits}" | grep -qiE '^[[:space:]]*Bump:[[:space:]]*minor[[:space:]]*$'; then + bump_level=minor fi + echo "Release bump level: ${bump_level}" + + git merge --no-edit --strategy-option=ours origin/master + package/version.sh bump ${prior_version} ${bump_level} # substitute the version in all relevant files package/version.sh sub uv --directory kmir lock --no-upgrade diff --git a/package/version.sh b/package/version.sh index f82aa94ac..091de6ae1 100755 --- a/package/version.sh +++ b/package/version.sh @@ -7,24 +7,23 @@ fatal() { echo "[FATAL] $@" ; exit 1 ; } version_file="package/version" +# Bump the given version by the requested level and write it to the version file. +# Usage: version_bump [major|minor|patch] (defaults to patch) +# The version counter lives on the `release` branch, so is always the +# prior released version -- see docs/dev/releasing.md version_bump() { - local version release_commit version_major version_minor version_patch new_version current_version current_version_major current_version_minor current_version_patch + local version level version_major version_minor version_patch new_version version="$1" ; shift + level="${1:-patch}" version_major="$(echo ${version} | cut --delimiter '.' --field 1)" version_minor="$(echo ${version} | cut --delimiter '.' --field 2)" version_patch="$(echo ${version} | cut --delimiter '.' --field 3)" - current_version="$(cat ${version_file})" - current_version_major="$(echo ${current_version} | cut --delimiter '.' --field 1)" - current_version_minor="$(echo ${current_version} | cut --delimiter '.' --field 2)" - current_version_patch="$(echo ${current_version} | cut --delimiter '.' --field 3)" - new_version="${version}" - if [[ "${version_major}" == "${current_version_major}" ]] && [[ "${version_minor}" == "${current_version_minor}" ]]; then - new_version="${version_major}.${version_minor}.$((version_patch + 1))" - fi - # If the file being commited increases the major or minor, then take that version as it is - if [[ "${version_major}" < "${current_version_major}" ]] || [[ "${version_minor}" < "${current_version_minor}" ]]; then - new_version="${current_version}" - fi + case "${level}" in + major) new_version="$((version_major + 1)).0.0" ;; + minor) new_version="${version_major}.$((version_minor + 1)).0" ;; + patch) new_version="${version_major}.${version_minor}.$((version_patch + 1))" ;; + *) fatal "Unknown bump level: ${level} (expected major, minor or patch)" ;; + esac echo "${new_version}" > "${version_file}" notif "Version: ${new_version}" } From 3789a152ff07a08339cadf20bd4a255a1b80d736 Mon Sep 17 00:00:00 2001 From: dkcumming Date: Tue, 14 Jul 2026 19:56:58 +0200 Subject: [PATCH 2/6] Updated `master` to have version pinned to sentinel `0.0.0` --- kmir/pyproject.toml | 2 +- kmir/uv.lock | 2 +- package/version | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kmir/pyproject.toml b/kmir/pyproject.toml index e7a6f525a..e6654e9e3 100644 --- a/kmir/pyproject.toml +++ b/kmir/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "kmir" -version = "0.3.181" +version = "0.0.0" description = "" requires-python = ">=3.10" dependencies = [ diff --git a/kmir/uv.lock b/kmir/uv.lock index 803dd4735..e803cf65a 100644 --- a/kmir/uv.lock +++ b/kmir/uv.lock @@ -621,7 +621,7 @@ wheels = [ [[package]] name = "kmir" -version = "0.3.181" +version = "0.0.0" source = { editable = "." } dependencies = [ { name = "kframework" }, diff --git a/package/version b/package/version index 1d0ba9ea1..77d6f4ca2 100644 --- a/package/version +++ b/package/version @@ -1 +1 @@ -0.4.0 +0.0.0 From 66ad313a35862ed60c4336d96b8077508d130021 Mon Sep 17 00:00:00 2001 From: dkcumming Date: Tue, 14 Jul 2026 20:01:57 +0200 Subject: [PATCH 3/6] Pin `uv` version for local builds to `deps/uv2nix` This means that local builds will fail unless they have the same version that CI uses. If we want to test with a differnt version, we can remove the section from the pyproject.toml file. --- .github/workflows/update-dependencies.yml | 4 +++- kmir/pyproject.toml | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index 72216f551..c5b479126 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -28,7 +28,9 @@ jobs: UV_VERSION=$(curl -s https://raw.githubusercontent.com/pyproject-nix/uv2nix/$(cat deps/uv2nix)/pkgs/uv-bin/srcs.json | jq -r .version) [[ "$UV_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] echo $UV_VERSION > deps/uv_release - git add deps/uv_release && git commit -m "Sync uv version: uv ${UV_VERSION}" || true + # keep the [tool.uv] required-version guard in kmir/pyproject.toml in lockstep + sed --in-place 's/^required-version = ".*"$/required-version = "'"${UV_VERSION}"'"/' kmir/pyproject.toml + git add deps/uv_release kmir/pyproject.toml && git commit -m "Sync uv version: uv ${UV_VERSION}" || true echo uv_version=$UV_VERSION >> "${GITHUB_OUTPUT}" - name: 'Install uv' uses: astral-sh/setup-uv@v6 diff --git a/kmir/pyproject.toml b/kmir/pyproject.toml index e6654e9e3..c1fa22263 100644 --- a/kmir/pyproject.toml +++ b/kmir/pyproject.toml @@ -47,6 +47,10 @@ dev = [ "pyupgrade", ] +[tool.uv] +# Pinned uv version for local builds, kept in sync with deps/uv_release +required-version = "0.9.22" + [tool.hatch.metadata] allow-direct-references = true From b48a090a6a9e88dfbc38123ab1cbcbd0abbc1050 Mon Sep 17 00:00:00 2001 From: dkcumming Date: Tue, 14 Jul 2026 20:13:31 +0200 Subject: [PATCH 4/6] Added `kmir --version` command to print the version --- kmir/src/kmir/__main__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kmir/src/kmir/__main__.py b/kmir/src/kmir/__main__.py index 290b50ed8..fc4f43358 100644 --- a/kmir/src/kmir/__main__.py +++ b/kmir/src/kmir/__main__.py @@ -15,6 +15,7 @@ from pyk.proof.show import APRProofShow from pyk.proof.tui import APRProofViewer +from . import __version__ from .cargo import CargoProject from .kmir import KMIR, KMIRAPRNodePrinter from .linker import link @@ -325,6 +326,7 @@ def kmir(args: Sequence[str]) -> None: def _arg_parser() -> ArgumentParser: parser = ArgumentParser(prog='kmir') + parser.add_argument('-V', '--version', action='version', version=f'kmir {__version__}') command_parser = parser.add_subparsers(dest='command', required=True) kcli_args = KCLIArgs() From fcb091fa3e59767fdad18d30e3b8fdbe39cc9b21 Mon Sep 17 00:00:00 2001 From: dkcumming Date: Tue, 14 Jul 2026 20:31:29 +0200 Subject: [PATCH 5/6] Minor fixes from claude: - Added `kmir --version` to test-package.sh - Default `bump_level` to patch in master-push.yml for safety - Explicitly mention assumption that github strategy "ours" should only differ on version files - Mention in README.md that specific uv version is needed now --- .github/workflows/master-push.yml | 5 +++-- README.md | 2 +- package/test-package.sh | 4 +--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/master-push.yml b/.github/workflows/master-push.yml index 5ba504eb2..052abdcc4 100644 --- a/.github/workflows/master-push.yml +++ b/.github/workflows/master-push.yml @@ -41,8 +41,7 @@ jobs: # See docs/dev/releasing.md prior_version=$(cat package/version) - # Choose the bump level from `Bump:` trailers on the new master commits - # (defaults to patch; major wins over minor wins over patch). + bump_level=patch # default bump level, may be overwritten new_commits="origin/release..origin/master" if git log --format='%B' "${new_commits}" | grep -qiE '^[[:space:]]*Bump:[[:space:]]*major[[:space:]]*$'; then bump_level=major @@ -51,6 +50,8 @@ jobs: fi echo "Release bump level: ${bump_level}" + # `ours` resolves conflicts in favour of release; only the version + # files should ever conflict (release = master + version commits). git merge --no-edit --strategy-option=ours origin/master package/version.sh bump ${prior_version} ${bump_level} # substitute the version in all relevant files diff --git a/README.md b/README.md index e235851bf..4aa029973 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ For semantics details and specialized workflows, see [Further Reading](#further- ### Prerequisites - [Python](https://www.python.org/) `>= 3.10` -- [`uv`](https://docs.astral.sh/uv/) +- [`uv`](https://docs.astral.sh/uv/), pinned in [`deps/uv_release`](deps/uv_release); if yours differs, run `uv self update ` - [`pip`](https://pip.pypa.io/) `>= 20.0.2` - [`gcc`](https://gcc.gnu.org/) `>= 11.4.0` - [Rust](https://rustup.rs/) via `rustup` diff --git a/package/test-package.sh b/package/test-package.sh index 9e48d4e01..c58b40ff7 100755 --- a/package/test-package.sh +++ b/package/test-package.sh @@ -4,9 +4,7 @@ set -xueo pipefail which kmir kmir --help - -# there is no `kmir version` implemented yet -# kmir version +kmir --version # ( \ # cd kmir/src/tests/integration/data/crate-tests/single-bin/main-crate \ From 6003b26711cee81accdf56bffe0076714672d93e Mon Sep 17 00:00:00 2001 From: dkcumming Date: Tue, 14 Jul 2026 21:09:56 +0200 Subject: [PATCH 6/6] releasing.md with info on version updates between master and release branches --- README.md | 1 + docs/dev/releasing.md | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 docs/dev/releasing.md diff --git a/README.md b/README.md index 4aa029973..917f9f1d4 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ RUSTC=deps/.stable-mir-json/debug.sh cargo build - [docs/semantics-of-mir.md](docs/semantics-of-mir.md) - [docs/example-mir-execution-flow.md](docs/example-mir-execution-flow.md) - [docs/dev/adding-intrinsics.md](docs/dev/adding-intrinsics.md) +- [docs/dev/releasing.md](docs/dev/releasing.md) - [docs/feature-checklist.md](docs/feature-checklist.md) - [Stable-MIR-JSON repository](https://github.com/runtimeverification/stable-mir-json/) diff --git a/docs/dev/releasing.md b/docs/dev/releasing.md new file mode 100644 index 000000000..ef129626f --- /dev/null +++ b/docs/dev/releasing.md @@ -0,0 +1,11 @@ +# Releasing + +- **`release` branch owns the version.** Every push to `master` auto-bumps the patch, tags it, and ships docker (`master-push.yml` -> `release.yml`). +- **`master` version files are `0.0.0` placeholders.** Never hand-edit `package/version`, `kmir/pyproject.toml`, or `kmir/uv.lock`. They only ever hold `0.0.0`. So `kmir --version` is `0.0.0` on a local master build, and the real version in nix/docker builds. +- **Want minor/major instead of patch?** Put a trailer on its own line in a commit (or the squash/PR description) that lands on master e.g.: + + ``` + Bump: minor + ``` + + `major` > `minor` > `patch`; anything else defaults to patch.