Skip to content

fix(release): derive version from git tag via hatch-vcs (#1503)#1507

Merged
dimitri-yatsenko merged 1 commit into
masterfrom
fix/1503-version-from-tag
Jul 20, 2026
Merged

fix(release): derive version from git tag via hatch-vcs (#1503)#1507
dimitri-yatsenko merged 1 commit into
masterfrom
fix/1503-version-from-tag

Conversation

@dimitri-yatsenko

@dimitri-yatsenko dimitri-yatsenko commented Jul 17, 2026

Copy link
Copy Markdown
Member

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.py at each tag still reports the previous release (at the v2.3.1 tag it reads 2.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 reporting 2.3.0
  • pip show datajoint on that install reports 2.3.0
  • version-gated code (if datajoint.__version__ >= "2.3.1") silently takes the wrong branch

Fix — make the git tag the single source of truth (hatch-vcs)

  • pyproject.toml: [tool.hatch.version] source = "vcs" (+ hatch-vcs build dep) and a [tool.hatch.build.hooks.vcs] hook that writes the resolved version to the generated, git-ignored src/datajoint/_version.py.
  • src/datajoint/version.py: re-exports the generated version, falling back to installed package metadata (importlib.metadata) for source-tree runs — so datajoint.__version__ keeps working everywhere.
  • .github/workflows/post_draft_release_published.yaml: drops the version.py sed/commit step and the follow-up bump PR entirely; checks out with fetch-depth: 0 so the build resolves the tag. Publishing the vX.Y.Z tag 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.9 tag:

  • hatchling version at the clean tag → 9.9.9; python -m builddatajoint-9.9.9-py3-none-any.whl and datajoint-9.9.9.tar.gz (the sdist→wheel path pip install git+…@vX uses).
  • Installed wheel → datajoint.__version__ == 9.9.9 and importlib.metadata.version("datajoint") == 9.9.9.
  • A dirty/untagged tree correctly yields a .devN+g<sha> version; _version.py is git-ignored and never tracked.

Notes

  • No version.py value to bump by hand anymore; the tag sets the version for pip install, pip show, and datajoint.__version__ alike.
  • Opened as a draft — this touches the release path, so worth a careful look before it's live. The workflow change can only be fully exercised on the next real release.
  • Behavior change — bare source checkout without install. Running from an uninstalled tree (PYTHONPATH=./src python -c "import datajoint; print(datajoint.__version__)") now reports 0.0.0+unknown, because both the build-generated _version.py and installed package metadata are absent. This differs from the previous hardcoded __version__. Anyone developing seriously will pip install -e . (which runs the hatch-vcs hook and generates _version.py), so this is minor — but flagged here so that seeing 0.0.0+unknown after upgrading isn't mistaken for a regression; the fix is pip install -e ..

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).
@dimitri-yatsenko dimitri-yatsenko added the bug Indicates an unexpected problem or unintended behavior label Jul 17, 2026
@dimitri-yatsenko dimitri-yatsenko added this to the v2.3.2 milestone Jul 17, 2026
@dimitri-yatsenko
dimitri-yatsenko marked this pull request as ready for review July 18, 2026 19:06

@MilagrosMarin MilagrosMarin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-vcs in build requires.
  • version.py fallback chain is sound: build-generated _versionimportlib.metadata.version("datajoint")"0.0.0+unknown" sentinel. Covers wheel, sdist, editable install, and bare-checkout cases.
  • .gitignore correctly excludes generated src/datajoint/_version.py.
  • Workflow drops the sed + bump-PR steps cleanly, removes pull-requests: write permission (no longer needed), and adds fetch-depth: 0 — the critical bit, since shallow clones would leave hatch-vcs without the tag.
  • RELEASE_MEMO.md update 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.

@dimitri-yatsenko
dimitri-yatsenko merged commit 1d880ce into master Jul 20, 2026
13 checks passed
@dimitri-yatsenko
dimitri-yatsenko deleted the fix/1503-version-from-tag branch July 20, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Indicates an unexpected problem or unintended behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants