Skip to content

Releasing a New Version

A release script at scripts/build_publish.sh automates the full release pipeline.

One-Command Release

bash
./scripts/build_publish.sh release 1.0.0

This runs through every step with a confirmation prompt upfront:

StepActionAborts if...
Pre-flightChecks clean working tree, tag doesn't existUncommitted changes or tag collision
1. BumpUpdates version in pyproject.toml and src/formal/__init__.pyInvalid format or already at that version
2. Commitgit commit -m "release: v1.0.0"
3. BuildClean build of sdist + wheel, validates with twineBuild or validation failure
4. TestInstalls wheel via pipx, checks --version and --helpVersion mismatch or broken CLI
5. Taggit tag -a v1.0.0 -m "Release v1.0.0"
6. Publishtwine upload dist/* to PyPIUpload failure
7. PushPushes commit and tag to origin

Individual Steps

Each step is also available standalone for more control:

bash
# Bump version without committing (useful for pre-release tweaks)
./scripts/build_publish.sh bump 0.2.0

# Build and validate only
./scripts/build_publish.sh build

# Smoke-test the built wheel
./scripts/build_publish.sh test

# Publish to TestPyPI first (dry run)
./scripts/build_publish.sh testpublish

# Publish to PyPI (assumes dist/ already built)
./scripts/build_publish.sh publish

# Build + publish in one go (no version bump)
./scripts/build_publish.sh all

Where the Version Lives

The version is stored in two files that the bump / release commands update together:

FileLineUsed by
pyproject.tomlversion = "X.Y.Z"PyPI, build tools
src/formal/__init__.py__version__ = "X.Y.Z"formal --version, runtime

Requirements for Publishing