bough is a tool to determine which uv workspace packages need building or testing based on git changes.
When using uv workspaces, it's often unclear which packages are affected by a given change. This leads to either rebuilding everything (wasteful) or missing necessary rebuilds (broken deployments).
Analyze dependencies and git diffs to identify affected packages, then build only what's needed.
bough
# Custom base commit
bough --base main analyze
# Display dependency graph
bough graph
# Output GitHub Actions matrix format
bough --format github-matrix analyzemy-app/
├── pyproject.toml
├── packages/
│ ├── auth/ # library (no deps)
│ ├── database/ # library (no deps)
│ └── shared/ # library (depends on: database)
└── apps/
├── api/ # buildable (depends on: auth, database, shared)
└── web/ # buildable (depends on: shared)
The bough graph command shows the dependency relationships between packages:
🚀 Buildable Packages:
==================================================
📦 api (apps/api)
└─ depends on: auth, database, shared
📦 web (apps/web)
└─ depends on: shared
📚 Library Packages:
==================================================
📖 auth (packages/auth)
├─ depends on: (none)
└─ depended on by: api
📖 database (packages/database)
├─ depends on: (none)
└─ depended on by: api, shared, web
📖 shared (packages/shared)
├─ depends on: database
└─ depended on by: api, web
The bough analyze command shows what packages should be built based on what files have changed.
GitHub Matrix (for parallel CI jobs):
{
"include": [
{"package": "api", "directory": "apps/api"},
{"package": "web", "directory": "apps/web"}
]
}Text (default):
Packages to rebuild:
api (apps/api)
web (apps/web)
Changed files:
packages/database/models.py
.bough.yml:
# Packages that produce build artifacts (default: ["apps/*"])
buildable:
- "apps/*"
# Files that never trigger rebuilds
ignore:
- "*.md"
- "docs/**"See GitHub Actions Integration Guide for examples of using Bough in CI/CD pipelines.
- Find all workspace members from
pyproject.toml - Build dependency graph from
tool.uv.sources - Detect changed files with git diff
- Apply change detection rules:
- File changed inside package → package directly affected
- File changed at workspace root → all packages affected
- Calculate transitive impacts (if A depends on B and B changes, A is affected)
- Filter to only buildable packages
- Output build list
If packages/database/models.py changes:
databaseis directly affectedsharedis affected (depends on database)apiis affected (depends on database and shared)webis affected (depends on shared)- Output shows only
apiandweb(they're buildable)
This tool is intentionally simple:
- Not a build system (like Bazel or Buck)
- Not a task runner
- Not multi-language aware
- Not trying to optimize build order or parallelization
- Not caching build artifacts
- una - Unify Python packaging commands
- postmodern-mono - Python monorepo example
- Nx affected - Similar concept for JS/TS monorepos
- Turborepo --affected - Git-based filtering for builds
- setup a release workflow to pypi
- provide an option that outputs all affected packages, not just buildable ones (useful for selectively running tests)
- handle working tree changes
- add a contributing guide
- check in a sample configuration file and document the defaults better
- improve or remove the github actions examples