Release Guide
This page walks you through the full release cycle for lauren:
preparing a release branch, tagging, building, and publishing to PyPI.
Prerequisites
- You have push access to the
mainbranch (or can open a PR to it). - The
LAUREN_PYPI_TOKENsecret is configured in the repository settings (used by the GitHub Actionsreleaseworkflow). - Your local environment has Python 3.11+ and the dev dependencies
installed (
pip install -e ".[dev]").
1. Prepare the Release
1.1 Branch from main
git checkout main
git pull origin main
git checkout -b release/v1.2.3Use the version you are about to publish as the branch name — it makes pull-request titles self-documenting.
1.2 Update CHANGELOG.md
lauren follows the Keep a Changelog
format. Move items from [Unreleased] to a new [1.2.3] - YYYY-MM-DD
section. Example:
## [1.2.3] - 2026-05-01
### Added
- Unified `ExtractionMarker.extract` signature with `ExecutionContext`.
- `@public` decorator and `IS_PUBLIC_KEY` for cooperative guard bypass.
### Fixed
- `LaurenFactory.create()` no longer requires `await`.
### Changed
- `_ExtractionMarker` renamed to `ExtractionMarker` (public alias kept).1.3 Run the Full CI Matrix Locally
nox # lint + tests + typecheck (default sessions)
nox -s docs # strict MkDocs build
nox -s llms_check # every public symbol is in llms-full.txtAll sessions must be green before you open a PR.
1.4 Open and Merge the Release PR
Push the branch and open a pull request against main. The PR title
should be release: vX.Y.Z. After review, merge with a standard merge
commit (no squash — the tag must point to a commit that is already on
main).
2. Tag the Release
After the release PR lands on main, tag it:
git checkout main
git pull origin main
# Annotated tag — the message becomes the release description on GitHub.
git tag -a v1.2.3 -m "Release v1.2.3"Push the Tag
git push origin v1.2.3Pushing a v* tag triggers .github/workflows/release.yml, which:
- Runs
nox -s buildto producedist/. - Publishes to PyPI via OIDC Trusted Publishing (no token required in the environment).
Warning: Do not push a tag to a non-
maincommitThe release workflow publishes whatever commit the tag points to. Always tag the merged
maincommit, not the release branch tip.
3. Verify the Release
Once the GitHub Actions release job completes:
# In a clean environment:
pip install lauren==1.2.3
python -c "import lauren; print(lauren.__version__)"
# Expected: 1.2.3Then create a GitHub Release:
- Go to Releases → Draft a new release.
- Select the
v1.2.3tag. - Paste the changelog section as the release body.
- Publish.
4. Manual / Local Release (Fallback)
Prefer the GitHub Actions workflow. Use the manual path only if CI is unavailable:
nox -s build # produces dist/lauren-X.Y.Z*.whl + .tar.gz
nox -s build_check # validates with twine check
# TestPyPI first:
nox -s release_test
# Real PyPI (destructive — cannot be undone):
nox -s release -- --yesDanger: Manual releases bypass OIDC
The
releasesession usestwine upload, which requiresTWINE_USERNAME=__token__andTWINE_PASSWORD=<pypi-token>in your shell environment.
5. Post-Release Housekeeping
- Add a new
[Unreleased]section to the top ofCHANGELOG.md. - Close the milestone on GitHub (if one was used).
- Announce in the project discussion board or release notes.
Version Format
lauren uses setuptools-scm to derive the package version
from git tags automatically:
| Scenario | Example version |
|---|---|
| Exactly on a tag | 1.2.3 |
| Commits after a tag | 1.2.3.post4+g1a2b3c4 |
| Untagged / dirty working tree | 0.0.0+unknown |
You never edit a version number manually. The tag is the version. See Versioning for the full details.