fix(release): derive version from git tag via hatch-vcs (#1503)#1507
Conversation
The version bump PR lands after the release tag, so version.py at each tag reports the previous release: pip install git+...@vX.Y.Z and pip show on a git install report the prior version, silently breaking version-gated code. PyPI wheels were unaffected (built from the sed'd tree). Make the git tag the single source of truth via hatch-vcs: - pyproject.toml: hatch-vcs version source + vcs build hook writing the generated src/datajoint/_version.py (git-ignored). - version.py: re-export the generated version, falling back to installed package metadata for source-tree runs. - post_draft_release_published.yaml: drop the version.py sed/commit and the follow-up bump PR; fetch full history+tags so the build resolves the tag. - RELEASE_MEMO.md: document the tag-driven flow (no manual bump, no PR).
MilagrosMarin
left a comment
There was a problem hiding this comment.
Thanks — closes finding 1 of #1503 exactly as I'd hoped (option c). All 12 CI checks green.
Verified:
- hatch-vcs config is standard:
source = "vcs"+version-file = "src/datajoint/_version.py"build hook +hatch-vcsin build requires. version.pyfallback chain is sound: build-generated_version→importlib.metadata.version("datajoint")→"0.0.0+unknown"sentinel. Covers wheel, sdist, editable install, and bare-checkout cases..gitignorecorrectly excludes generatedsrc/datajoint/_version.py.- Workflow drops the sed + bump-PR steps cleanly, removes
pull-requests: writepermission (no longer needed), and addsfetch-depth: 0— the critical bit, since shallow clones would leave hatch-vcs without the tag. RELEASE_MEMO.mdupdate accurately reflects the new tag-as-source-of-truth flow.- Author verification against
v9.9.9(wheel + sdist + installed metadata all agree; dirty tree →.devN+g<sha>) matches standard hatch-vcs behavior.
Two non-blocking observations:
1. First-real-release risk
The workflow only fires on release publish, so it can't be fully end-to-end-tested until the next real release. You note this in the PR body. Reasonable to accept given the local reproduction, but worth being ready to hotfix quickly if the workflow surfaces something unexpected on first fire.
2. Bare-checkout dev-mode change worth a release-notes line
Before this PR, PYTHONPATH=./src python -c "import datajoint; print(datajoint.__version__)" on a bare git clone (no pip install) returned the hardcoded __version__. After this PR, that path lands on "0.0.0+unknown" because both _version.py and installed package metadata are absent. Very minor — anyone doing serious development would pip install -e . (which runs the hatch-vcs hook and generates _version.py). But worth a release-note line so anyone hitting 0.0.0+unknown after upgrade doesn't mistake it for a regression; the fix is pip install -e ..
3. Rebase before merge
Same as #1508 — branch predates #1506, auto-mergeable but worth rebasing so the diff view stays clean.
Approving on the substance — clean tag-driven migration.
Resolves finding 1 of #1503. (Findings 2–4 already landed in #1504.)
Problem
The version bump PR lands after the release tag, so
src/datajoint/version.pyat each tag still reports the previous release (at thev2.3.1tag it reads2.3.0, and so on). PyPI wheels are unaffected — they're built from the sed'd tree in the same workflow run — but:pip install git+https://github.com/datajoint/datajoint-python.git@v2.3.1→ wheel reporting2.3.0pip show datajointon that install reports2.3.0if datajoint.__version__ >= "2.3.1") silently takes the wrong branchFix — make the git tag the single source of truth (hatch-vcs)
pyproject.toml:[tool.hatch.version] source = "vcs"(+hatch-vcsbuild dep) and a[tool.hatch.build.hooks.vcs]hook that writes the resolved version to the generated, git-ignoredsrc/datajoint/_version.py.src/datajoint/version.py: re-exports the generated version, falling back to installed package metadata (importlib.metadata) for source-tree runs — sodatajoint.__version__keeps working everywhere..github/workflows/post_draft_release_published.yaml: drops theversion.pysed/commit step and the follow-up bump PR entirely; checks out withfetch-depth: 0so the build resolves the tag. Publishing thevX.Y.Ztag is now the only version action..gitignore: ignore the build-generated_version.py.RELEASE_MEMO.md: document the tag-driven flow (no manual bump, no bump PR).Verification
Built and installed locally against a throwaway
v9.9.9tag:hatchling versionat the clean tag →9.9.9;python -m build→datajoint-9.9.9-py3-none-any.whlanddatajoint-9.9.9.tar.gz(the sdist→wheel pathpip install git+…@vXuses).datajoint.__version__ == 9.9.9andimportlib.metadata.version("datajoint") == 9.9.9..devN+g<sha>version;_version.pyis git-ignored and never tracked.Notes
version.pyvalue to bump by hand anymore; the tag sets the version forpip install,pip show, anddatajoint.__version__alike.PYTHONPATH=./src python -c "import datajoint; print(datajoint.__version__)") now reports0.0.0+unknown, because both the build-generated_version.pyand installed package metadata are absent. This differs from the previous hardcoded__version__. Anyone developing seriously willpip install -e .(which runs the hatch-vcs hook and generates_version.py), so this is minor — but flagged here so that seeing0.0.0+unknownafter upgrading isn't mistaken for a regression; the fix ispip install -e ..