Skip to content

Automate releases: tag-derived version and a release per merge to main - #159

Merged
almilder merged 3 commits into
mainfrom
ci/auto-release
Oct 8, 2026
Merged

almilder merged 3 commits into
mainfrom
ci/auto-release

Conversation

@almilder

@almilder almilder commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Cuts a release automatically on every merge to main, with PR labels as the human decision about what kind of release it is.

Label on the merged PR Result
none patch release, published with auto-generated notes
release:minor / release:major that part is bumped instead
release:draft the tag is pushed, but the release is left as a draft to be written by hand
release:skip no tag and no release; the PR shows up in the next release's notes

release:draft combines with the bump labels. The workflow can also be run by hand from the Actions tab (choose the bump and whether to draft), which covers a forgotten label.

Changes

  • Version from git tags. pyproject.toml no longer carries a version number; hatch-vcs reads it from the latest tag. A tagged commit installs as 0.4.1; later commits install as e.g. 0.4.2.dev3+g<sha>. No more version-bump commits in PRs.
  • .github/workflows/release.yaml (new): on push to main, looks up the merged PR's labels, computes the next tag from the latest vX.Y.Z tag, pushes it, and creates the GitHub release.
  • .github/release.yml (new): groups the generated notes by the existing enhancement, bug, and documentation labels.
  • Docker: the build context has no git history, so deploy.yaml computes the version and passes it to the Dockerfile as a build argument. actions/checkout is bumped from v2 to v4 there to fetch full history.
  • Read the Docs: fetches full history so the version resolves.
  • PR template: a short "Release" section listing the labels.

Things to know

  • This PR carries release:skip, so merging it does not cut a release. The next merged PR becomes v0.4.1.
  • The Docker image version can lag by one: deploy and release start on the same push, so the image may be built before the new tag exists and report a dev version (0.4.1.dev1+g<sha>).
  • An editable install reports the version from the time of the last pip install -e ., not the current checkout.
  • If several PRs merge in quick succession, GitHub keeps only the newest queued run of this workflow. A dropped run's PR still appears in the next release's notes, but its bump label would be ignored.
  • A commit pushed straight to main with no PR gets a patch release.

Testing

  • Local wheel build picks up the tag-derived version, and the override used by the Docker build is honoured.
  • hatch version (the command deploy.yaml uses) prints only the version on stdout.
  • Bump arithmetic and label matching dry-run in bash; the PR lookup was checked against the MCMC uncertainty postprocessor, covariance noise model, and supporting changes #158 merge commit.
  • Not tested: the release workflow itself (it only runs on main), the Docker build, and the Read the Docs build.

🤖 Generated with Claude Code

Avi and others added 2 commits October 8, 2026 14:45
The version now comes from the latest git tag (hatch-vcs) instead of a number in
pyproject.toml. A new workflow tags and releases every merge to main: patch by
default, with PR labels release:minor, release:major, release:draft, release:skip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@almilder almilder added the release:skip Merge cuts no release label Oct 8, 2026

@ergodic-reviewer ergodic-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking findings. Added non-blocking comments on recovery after a tag push succeeds but release creation fails, and on loss of version provenance when installing GitHub source archives.

Reviewed the complete diff and relevant packaging, workflow, version-consumer, and contribution guidance. Static review only: I did not execute tests, builds, or workflows; the latest inspected checks show CPU CI in progress and GPU CI skipped. Postprocessing is not applicable to these release/packaging infrastructure changes.

Comment thread .github/workflows/release.yaml Outdated
Comment on lines +65 to +68

if [ -n "$(git tag --points-at "$GITHUB_SHA" --list 'v[0-9]*')" ]; then
echo "This commit is already tagged."
skip=true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: let a retry finish a partially created release. If git push origin "$TAG" succeeds but the subsequent gh release create fails, the retry fetches the tag, enters this branch, and reports success without ever creating the missing release. A manual dispatch at the same commit is also skipped. Consider checking for the release as well as the tag, reusing the existing tag to create a missing release, and making only a fully completed release a no-op. This keeps a transient API failure from requiring out-of-band repair.

Comment thread pyproject.toml
source = "vcs"

[tool.hatch.version.raw-options]
fallback_version = "0+unknown"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: preserve or document version provenance for release-archive installs. GitHub's generated source ZIP/tarball has no .git, and this repository supplies neither archive version metadata (.gitattributes only configures the notes merge driver) nor built wheel/sdist assets in the release workflow. Installing one of those source archives therefore falls back to 0+unknown, rather than retaining the release version as the previous static metadata did. This value also propagates through misc.get_version() into canonical_tags() and build_manifest(), so runs from different release archives lose that version identifier. Consider adding archive metadata, providing versioned build artifacts, or explicitly documenting that accurate version provenance requires a Git checkout or an override. The README's clone-based installation is not affected by this case.

…ion source archives

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@ergodic-reviewer ergodic-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No material findings in the complete diff. The revision adds recovery for a pushed tag whose release is missing and Git archive metadata for version discovery, addressing the earlier non-blocking concerns at the code level. Checked the packaging, deployment/docs integration, version consumers, relevant tests, and repository guidance.

Static review only: I did not execute tests, builds, or workflows. The latest inspected checks show CPU CI in progress and GPU CI skipped; end-to-end release, Docker, Read the Docs, and archive-install behavior remain unverified here. Postprocessing is not applicable to these release/packaging infrastructure changes.

@almilder
almilder merged commit 9555612 into main Oct 8, 2026
2 checks passed
@almilder
almilder deleted the ci/auto-release branch October 8, 2026 19:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:skip Merge cuts no release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant