This project uses Semantic Versioning. Releases are published to PyPI automatically by GitHub Actions when a GitHub Release is published.
- MAJOR (
1.0.0→2.0.0): breaking API changes - MINOR (
0.2.0→0.3.0): new features, backwards-compatible - PATCH (
0.2.0→0.2.1): bug fixes only
Pre-1.0 minor bumps may contain breaking changes (noted in the changelog).
Keep all three in sync:
pyproject.toml→version = "X.Y.Z"src/lettr/__init__.py→__version__ = "X.Y.Z"src/lettr/_client.py→User-Agentheader (two occurrences:request()andget_no_auth())
-
Update the changelog. Move items from
[Unreleased]into a new[X.Y.Z]section inCHANGELOG.md. Add a new empty[Unreleased]section at the top. Update the compare links at the bottom. -
Bump the version in the three files above.
-
Run the checks locally:
source .venv/bin/activate python -m pytest tests/ -v ruff check src/ tests/ -
Commit and push on
main:git add CHANGELOG.md pyproject.toml src/lettr/ git commit -m "Release vX.Y.Z" git push origin main -
Tag the release:
git tag vX.Y.Z git push origin vX.Y.Z
-
Create a GitHub Release from the tag. The body should mirror the changelog entry for this version.
gh release create vX.Y.Z --title "vX.Y.Z" --notes-from-tag(or use the GitHub web UI)
-
Watch the workflow. The
.github/workflows/publish.ymlworkflow fires on release publish:- Builds the sdist and wheel
- Publishes to TestPyPI
- Publishes to PyPI
Both PyPI targets use trusted publishing via OIDC, so no API tokens are needed — but the
testpypiandpypienvironments must be configured in the GitHub repo settings with matching trusted publisher entries on PyPI. -
Verify the new version appears at https://pypi.org/project/lettr/ and installs cleanly:
pip install --upgrade lettr python -c "import lettr; print(lettr.__version__)"
- TestPyPI step fails: TestPyPI rejects re-uploads of an existing version. Delete the release, bump to the next patch, and retry.
- PyPI step fails: same constraint — a published version cannot be overwritten. You must bump to the next version.
- Never yank/delete a PyPI release unless it has a critical issue; prefer publishing a fix release instead.
When the API surface is considered stable:
- Ensure the changelog's
[Unreleased]section is clean. - Add a
## [1.0.0]section documenting the stability commitment. - Follow the release checklist above with
X.Y.Z = 1.0.0.