Skip to content

Derive the version from the git tag - #12

Merged
mconflitti-pbc merged 1 commit into
mainfrom
release-versions
Aug 5, 2026
Merged

Derive the version from the git tag#12
mconflitti-pbc merged 1 commit into
mainfrom
release-versions

Conversation

@mconflitti-pbc

@mconflitti-pbc mconflitti-pbc commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replaces the hard-coded version in pyproject.toml with dynamic = ["version"] plus the hatch-vcs build plugin, so the git tag is the only source of the version. No bump commit, and no tag-vs-manifest mismatch to get wrong.
  • Writes the resolved version to src/posit_cli/_version.py (gitignored) through the hatch-vcs build hook, so a wheel built from an sdist — which carries no git metadata — still gets a version.
  • Keeps the tag check in release.yaml, but compares the tag against the built version. It now catches a build that missed the tag: a shallow clone, a dirty tree, or two tags on one commit.
  • Adds a github-release job that runs after publish, so a failed PyPI upload leaves no release. It attaches the wheel and sdist, and generates notes from the commits.
  • Fetches tags in CI's build job (fetch-depth: 0), so its artifact carries a real version instead of a 0.1.dev1+g… fallback.
  • Points just version at hatch version. uv version cannot read a dynamic version.
  • Leads the install docs with uv tool install posit-cli in the README and the Claude Code skill, now that posit-cli 0.1.0 is on PyPI. Both keep the GitHub form for unreleased changes.
  • Rewrites RELEASE.md for the tag-only flow, and tells agents in CLAUDE.md not to re-add a version field.

uv.lock no longer records a version for the project; uv lock writes (dynamic) instead.

Releasing after this change:

git checkout main && git pull
git tag v0.2.0
git push origin v0.2.0

Test plan

  • just lint passes
  • just test passes (64 tests)
  • just test 3.8 passes — the oldest supported interpreter still installs the project under the new build backend
  • uv lock --locked passes, so the lockfile is stable with a dynamic version
  • uv build builds the wheel from the sdist, which proves the sdist path resolves a version with no git present
  • Built in a tagless, single-commit repo: produces 0.1.dev1+g<sha> rather than failing, so CI's shallow checkouts stay green
  • posit --version from the built wheel reports the hatch-vcs version
  • First tag push (vX.Y.Z on main) to confirm the publish and the GitHub release run end-to-end

The release environment reviewers and the PyPI trusted publisher are unchanged. RELEASE.md still lists both as one-time setup.

`pyproject.toml` held a hard-coded `version`, so every release needed a bump
commit that had to match the tag. `hatch-vcs` now reads the version from the
git tag at build time, and the tag/pyproject mismatch class of error goes away.

- Declare `dynamic = ["version"]` and add the `hatch-vcs` build backend plugin.
- Write the resolved version to `src/posit_cli/_version.py` (gitignored) so a
  wheel built from an sdist, which has no git metadata, still gets a version.
- Keep a tag check in the release workflow, but compare the tag against the
  built version. This catches a build that missed the tag: a shallow clone, a
  dirty tree, or two tags on one commit.
- Fetch tags in CI's build job so its artifact carries a real version.
- Point `just version` at `hatch version`; `uv version` cannot read a dynamic
  version.

Also create a GitHub release after a successful publish, and update the install
docs now that posit-cli is on PyPI.
@mconflitti-pbc
mconflitti-pbc merged commit ce29b80 into main Aug 5, 2026
9 checks passed
@mconflitti-pbc
mconflitti-pbc deleted the release-versions branch August 5, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant