From 7e84176f63421b75324fc1e3437241e6b9680621 Mon Sep 17 00:00:00 2001 From: Christian-Manuel Butzke Date: Wed, 1 Jul 2026 21:06:43 +0900 Subject: [PATCH] maint: single source of truth for the version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the version to src/harel/__about__.py and have hatchling read it via [tool.hatch.version] (pyproject 'dynamic'); __init__ imports __version__ from there. One place to bump — and unlike importlib.metadata it reflects the current source immediately (no stale editable-install metadata). Document the lockstep release checklist in CONTRIBUTING. Closes #36. --- CONTRIBUTING.md | 17 ++++++++++++++--- pyproject.toml | 5 ++++- src/harel/__about__.py | 8 ++++++++ src/harel/__init__.py | 3 +-- 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 src/harel/__about__.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a836b70..1cd8caf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,15 +70,26 @@ reuses it. To force a refresh, delete `.cache/`. ## Versioning -The version source of truth is **`pyproject.toml`** (`version = "0.0.1"`); the package -exports it as `harel.__version__`. The package version **is** the implemented harel spec -version. +The version source of truth is **`pyproject.toml`** (`version = …`); the package derives +`harel.__version__` from the installed distribution metadata (no second copy to keep in +sync). The package version **is** the implemented harel spec version. > harel, harel-conformance, and harel-python share one synchronized SemVer version > (currently pre-1.0 `0.0.x`). A release tags all three `vX.Y.Z` in lockstep; an > implementation declares "implements harel spec vX.Y.Z" and pins the conformance suite > at that tag. +### Releasing `vX.Y.Z` (lockstep) +1. Land all spec / conformance / implementation changes on the three `main` branches. +2. Bump the version in **`pyproject.toml`** (here) and the `VERSION` files in `harel` and + `harel-conformance`. +3. Tag `vX.Y.Z` on **harel** and **harel-conformance** (`gh api -X POST + repos/fruwehq//git/refs -f ref=refs/tags/vX.Y.Z -f sha=$(gh api + repos/fruwehq//commits/main --jq .sha)`), so this package pins the matching + conformance tag instead of falling back to `main`. +4. Tag **harel-python** `vX.Y.Z` only to publish to PyPI — it triggers `release.yml` + (Trusted Publishing). + ## License Contributions are made under the project's [MIT license](LICENSE). diff --git a/pyproject.toml b/pyproject.toml index de5f173..916cba9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "harel-python" -version = "0.0.2" +dynamic = ["version"] description = "Python reference implementation of the harel statechart engine" readme = "README.md" requires-python = ">=3.11" @@ -46,6 +46,9 @@ dev = [ [project.scripts] harel = "harel.cli:main" +[tool.hatch.version] +path = "src/harel/__about__.py" + [tool.hatch.build.targets.wheel] packages = ["src/harel"] diff --git a/src/harel/__about__.py b/src/harel/__about__.py new file mode 100644 index 0000000..058c3ab --- /dev/null +++ b/src/harel/__about__.py @@ -0,0 +1,8 @@ +"""Single source of truth for the package version. + +Both the runtime (``harel.__version__``) and the build backend (hatchling, via +``[tool.hatch.version]`` in ``pyproject.toml``) read the version from here, so there +is exactly one place to bump. +""" + +__version__ = "0.0.2" diff --git a/src/harel/__init__.py b/src/harel/__init__.py index 5d06197..f6c5c67 100644 --- a/src/harel/__init__.py +++ b/src/harel/__init__.py @@ -10,6 +10,7 @@ import logging from . import yaml12 +from .__about__ import __version__ from .cel import CelError from .definition import Definition, load_definition, load_definitions from .engine import Host @@ -43,8 +44,6 @@ "__version__", ] -__version__ = "0.0.2" - # Diagnostic logging under the ``harel`` logger; silent unless the host app # configures logging (e.g. ``logging.basicConfig(level=logging.DEBUG)``). logging.getLogger("harel").addHandler(logging.NullHandler())