Development

Setup

uv sync --all-groups --all-extras
pre-commit install
uv run pytest
uv run mypy src/lib/ src/tools/

Local Testing

Build a .devN wheel (N = commits since version tag) and install it:

release local                          # build + install as e.g. 0.3.2.dev3
release --dry-run local                # preview version without building

This bypasses mise but installs to the same ~/.local/bin. After testing, restore the mise-managed version:

mise install --force "pipx:buvis-gems"

Release

release patch|minor|major              # bump, tag, push → CI publishes to PyPI
release --pre rc1                      # pre-release current version to TestPyPI
release --pre rc1 minor                # bump + pre-release to TestPyPI
release                                # after rc: strip suffix, release stable to PyPI
release --dry-run [--pre rc1] [patch]  # preview without changes

mise adds dev/bin to PATH. Tags with rc publish to TestPyPI; stable tags go to PyPI.

Re-running a Failed Release

If CI fails after a release tag was pushed (e.g. a lint error), fix the issue on master, then move the tag to the latest commit and force-push it:

git tag -f gems-vX.Y.Z
git push origin gems-vX.Y.Z --force

This re-triggers the publish workflow on the new commit.

Installing Pre-releases

To install a release candidate from TestPyPI:

uv tool install "buvis-gems[all]==X.Y.Zrc1" \
    --extra-index-url https://test.pypi.org/simple/ \
    --index-strategy unsafe-best-match

Replace X.Y.Zrc1 with the actual version (e.g. 0.4.0rc1).

If you use mise to manage buvis-gems, install into the mise venv instead:

mise_root=$(mise where pipx:buvis-gems)
uv pip install --force-reinstall "buvis-gems[all]==X.Y.Zrc1" \
    --extra-index-url https://test.pypi.org/simple/ \
    --index-strategy unsafe-best-match \
    --python "$mise_root/buvis-gems/bin/python"

To go back to the stable release:

# uv tool users
uv tool install --force buvis-gems[all]

# mise users
mise install --force "pipx:buvis-gems"