Repository navigation
feat: release tooling (version bump, changelog, tag, GitHub release) - #17
Merged
Merged
Conversation
scripts/release.py, standard library only: `prepare patch|minor|major|X.Y.Z` runs the suite, writes the version into pyproject.toml (the only place it lives), moves the changelog's Unreleased section under the version (or renders one from Conventional Commit subjects since the last tag), commits, creates an annotated tag with the notes, and pushes branch and tag atomically after confirmation. `check-version`, `notes` and `version` serve the release workflow. It reads the project name from pyproject.toml, so a renamed clone changes nothing in it, and refuses to run while [tool.release] starter = true, which keeps the starter itself unreleased. After the release commit it reinstalls the project so the installed metadata (what APP_VERSION reads) carries the new version. The annotated tag is created with --cleanup=verbatim: git otherwise drops the "### Heading" lines of the notes as comments. tests/test_release_script.py covers bumps, pyproject and changelog handling, and full prepare runs in a throwaway repository, including the starter guard and the preflight refusals. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
.github/workflows/release.yml: on a pushed v* tag, `verify` checks the tag against pyproject.toml and that CHANGELOG.md has the section (standard library script, nothing installed), `ci` runs the existing CI workflow through workflow_call (lint, mypy, pip-audit, the suite with PostgreSQL), `build` makes the wheel and sdist with the Poetry named in poetry.lock, and `publish` creates the GitHub release with gh, the changelog section as its notes and the archives attached, marked pre-release when the version has a suffix. A manual run stops after build. ci.yml gains the workflow_call trigger and checks scripts/ too; mypy covers scripts/. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…E, AGENTS docs/releasing.md: how a release is put together, choosing the version for an HTTP API, the step by step, the starter marker and a clone's first release, writing the notes (headings, style, the generated fallback), changing notes later, troubleshooting, hotfixes. Setup's adapting list gains the marker flip; the pure-test command lists the new test files; lint commands include scripts/. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
[tool.release] starter = true keeps the starter at 0.1.0: scripts/release.py refuses to tag while it is set. The changelog header now says Unreleased becomes the release notes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release tooling for projects built from this starter, while the starter itself stays at
0.1.0. Four commits, one concern each.scripts/release.py(standard library only)prepare patch|minor|major|X.Y.Z: refuses off a clean, up-to-datemainor when the tag exists; runspytest; writes the version intopyproject.toml(the only place it lives,APP_VERSIONreads the installed metadata); moves the changelog's Unreleased section under the version, or renders one from Conventional Commit subjects since the last tag (securitymaps to a Security heading); commitschore(release): vX.Y.Z; creates an annotated tag with the notes; pushes branch and tag atomically after confirmation.--dry-run,--skip-tests,--no-push,--yes,--allow-branch.pyproject.toml: a renamed clone changes nothing in it.[tool.release] starter = true, which this PR sets in the starter. A clone flips it once (added to the "Adapting this starter" list).poetry install --only-rootso a running dev server reports the new version (editable installs write the metadata at install time).--cleanup=verbatim: git otherwise strips the### Headinglines of the notes as comments. The reference script this is ported from has that latent bug; the end-to-end test caught it here.check-version,notes,versionserve the workflow..github/workflows/release.ymlonv*tags and manual runs:verify(tag vspyproject.toml, notes exist; nothing installed),ci(reusesci.ymlthrough a newworkflow_calltrigger: lint, mypy, pip-audit, the suite with PostgreSQL),build(poetry build, wheel and sdist as an artifact),publish(gh release createwith the changelog section as notes and the archives attached,--prereleasefor a suffixed version). A manual run stops afterbuild. No third-party release action.Docs:
docs/releasing.md(how a release is put together, choosing the version for an HTTP API, step by step, the starter and its clones, writing the notes, troubleshooting, hotfixes); setup, index, README, AGENTS and the changelog header updated.black,flake8andmypynow coverscripts/too.Verification
tests/test_release_script.py(pure, 26 tests): bumps and pre-release ordering,pyproject.tomlreading and writing (other tables untouched, marker present/absent/false), generated notes incl. breaking and skipped housekeeping, changelog splitting and insertion, and fullprepareruns in a throwaway repository with a bare remote: commit, verbatim tag message, empty Unreleased,check-versionpass and fail,notes,version, dry run changes nothing, the starter guard, refusals offmain, with a dirty tree and when behind.prepare minor --dry-runstops with the starter message and the tree stays clean;versionprints0.1.0;check-version v0.1.0passes.scripts/) clean; 88 pure tests pass. CI runs the full suite.mainexercises verify, ci and build without publishing.🤖 Generated with Claude Code