lazy-wheels
CI release workflow for your multi-package uv monorepo that only rebuilds changed packages.
Why lazy-wheels?
Managing versions across multiple packages in a monorepo is painful. lazy-wheels makes it simple: you own major.minor, CI owns patch. When you're ready for a breaking change or new feature in any package, bump the major or minor version yourself (e.g. uv version --project packages/your-project --bump minor). For everything else, CI automatically increments patch versions after each release.
lazy-wheels always keeps your main branch one patch version ahead of the latest release (i.e. main represents unreleased changes). This means HEAD is always releasable, version numbers are always increasing, and you never have to think about patch versions again. Change detection uses per-package git tags, so only packages with actual changes (or dependencies on changed packages) get rebuilt.
Installation
pip install lazy-wheels
Or with uv:
uv add --group dev lazy-wheels
Or scaffold just once with uvx:
uvx lazy-wheels init
Usage
Initialize
Scaffold the GitHub Actions workflow into your repo:
lazy-wheels init
This creates .github/workflows/release.yml configured for your uv workspace.
Requirements:
- A git repository
- A
pyproject.tomlwith[tool.uv.workspace]members defined
Triggering a Release
Option 1: GitHub CLI
gh workflow run release.yml
gh workflow run release.yml -f release=r1
gh workflow run release.yml -f force_rebuild_all=true
Option 2: lazy-wheels CLI
Just wraps the gh commands into a more compact CLI.
lazy-wheels release
lazy-wheels release -r r1
lazy-wheels release --force-all
Option 3: GitHub.com
You can also manually launch the release workflow in the github.com UI.
Workflow Inputs
| Input | Description |
|---|---|
release |
Release tag (e.g., r1, r2). Auto-generates if not provided. |
force_rebuild_all |
Rebuild all packages regardless of changes. |
How It Works
- Discover — Scans
[tool.uv.workspace]members to find all packages and their dependencies - Detect changes — Compares each package against its last release tag (
{pkg}/v{version}) - Propagate dirtiness — Marks dependents of changed packages as dirty (transitive rebuild)
- Fetch unchanged — Downloads wheels for unchanged packages from previous GitHub releases
- Build changed — Runs
uv buildonly on packages that need rebuilding - Tag — Creates per-package version tags (e.g.,
my-pkg/v1.2.3) - Bump versions — Increments patch version in each built package's
pyproject.toml - Publish — Creates a GitHub Release with all wheels (changed + unchanged)
- Push — Commits version bumps and pushes tags
Metadata
Release files for lazy-wheels 0.1.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lazy_wheels-0.1.9.tar.gz | 19.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lazy_wheels-0.1.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.0 kB
Release files / lazy_wheels-0.1.9.tar.gz
| Download URL | lazy_wheels-0.1.9.tar.gz |
|---|---|
| Size | 19.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6b3b0a6343855e67e3861b1ff5fab046e6559ac859768ef61696e4ff095a1ba5
|
|
BLAKE2b-256 checksum How to use checksums |
19ae80cc512083857882df7276e41b1081d5d2f69b019280f2ed29800cc17c42
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 13, 2026.
Transparency logRelease files / lazy_wheels-0.1.9-py3-none-any.whl
| Download URL | lazy_wheels-0.1.9-py3-none-any.whl |
|---|---|
| Size | 17.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
98c77177014cc2727c62c94382c9ad7fbb437f25b9f51830e52a23dda19d2170
|
|
BLAKE2b-256 checksum How to use checksums |
b48e7a7e4b63daacdc5c3d1a890c117af72dba5e293669f3fe20c19a278538d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 13, 2026.
Transparency log