Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[Unreleased]
[v0.22.0] - 2026-04-02
Added
- Add
uvr buildcommand for building changed workspace packages locally using layered dependency ordering without versioning, tagging, or publishing - Add typed pydantic argument models for all CLI commands, replacing untyped
getattr()access onargparse.Namespace
Changed
- Reorganize CLI command files into nested subpackages matching the command tree (
workflow/,skill/,jobs/) - Extract shared upgrade/merge-base helpers into
cli/_upgrade.py
Fixed
- Fix
uvr statusnot showing previous release version and diff-from tag for unchanged packages
[v0.18.0b0] - 2026-03-29
Changed
- BREAKING: Bump
ReleasePlanschema version to 9 — consolidate per-package data intoChangedPackagemodel replacingBumpPlan,MatrixEntry,PublishEntry,current_versions,release_tags, andbumpsfields - BREAKING: Rename release pipeline phase from "publish" to "release" — affects
--skipflag values, workflow job names, and plan field names (publish_commands→release_commands,publish_matrix→release_matrix,runners→build_matrix) - BREAKING: Rename all shared module functions to verb-first convention —
load_pyproject→read_pyproject,save_pyproject→write_pyproject,step→print_step,fatal→exit_fatal,discover_packages→find_packages,get_baseline_tags→find_baseline_tags,base_version→get_base_version,get_uvr_config→get_config,get_uvr_matrix→get_matrix - BREAKING: Restructure
shared/modules by topological dependency layer —planner/subpackage absorbsversions.py,deps.py,graph.py,changes.py;context/subpackage replacesdiscovery.pywithRepositoryContextmodel;execute.py→executor.py - Change
ReleasePlannerto accept a pre-builtRepositoryContextinstead of calling discovery functions internally - Change
uvr init --upgradeto use editor prompt with--waitfor GUI editors instead ofgit checkout -pfor conflict resolution - Prefix all core workflow jobs with
uvr-(uvr-validate,uvr-build,uvr-release,uvr-finalize) to distinguish from user-defined jobs - Replace GitHub API calls and tag scanning with O(1) local ref lookups via
find_previous_releaseinverse version bump
Added
- Add
RepositoryContextmodel that pre-fetches all repository state (repo handle, git tags, GitHub releases, packages, release tags, baselines) in a singlebuild_context()call - Add
ChangedPackagemodel extendingPackageInfowithcurrent_version,release_version,next_version,last_release_tag,release_notes,make_latest, andrunnersfields - Add
get_path()helper intoml.pyfor navigating nested TOML dicts without chained.get()calls - Add
--editorCLI flag and[tool.uvr.config].editorsetting for configuring conflict resolution editor inuvr init --upgrade - Add
@computed_fieldproperties onReleasePlanforbuild_matrixandrelease_matrix— derived fromchangedpackages, serialized into JSON for CI workflow consumption - Add cumulative pre-release notes — beta notes include all commits since the last final release, not just since the last alpha
- Add
--full-release-notesflag to show all commits (default truncates to 10 with overflow count) - Add
is_pre()helper for detecting alpha/beta/rc versions - Add
--allow-dirtyflag touvr releasefor running with uncommitted changes - Add progress bar with per-phase timing and bar chart summary to
uvr releaseplanning output - Add
find_previous_release()inverse version bump — derives predecessor via O(1) ref lookups with kind chain fallback (rc → b → a → final) - Add
uvr skill init --upgradewith three-way merge and editor conflict resolution matchinguvr init --upgrade - Add versioned skill templates replacing git commit SHA tracking
Removed
- Remove
BumpPlan,MatrixEntry,PublishEntry,PinChange,DepPinChangemodels — data consolidated intoChangedPackage - Remove
git(),gh(),run()subprocess wrappers fromshell.py— replaced by pygit2 and httpx in earlier versions - Remove unused functions:
dev_number,is_final,is_prerelease,is_postrelease,tag_for_package,topo_sort,rewrite_pyproject,update_dep_pins - Remove GitHub API dependency for release detection — all tag lookups are now local via pygit2
- Remove
git/remote.pymodule
Fixed
- Fix
git merge-fileexit code check inuvr init --upgrade— was treating conflict count > 1 as fatal error instead of only negative exit codes - Fix multiline
run:steps in generated workflow YAML rendering as quoted strings instead of block scalars (|) - Fix
strategyfield rendering afterstepsin workflow YAML job definitions - Fix
--pre bwith alpha version producing another alpha instead of beta - Fix
--devrejecting clean versions — now auto-appends.dev0consistent with other release types
[v0.17.0] - 2026-03-27
Added
- Add
pre_build_stage/post_build_stagehooks called before and after each build stage with the list of packages - Add
pre_build_package/post_build_packagehooks called around individual package builds (run in parallel threads) - Add optional
runnerparameter topre_build/post_buildhooks identifying the active runner labels
Changed
- BREAKING: Replace
BuildStage.commandsdict (with__setup__/__cleanup__sentinel keys) with explicitsetup,packages, andcleanupfields - BREAKING: Change
build_commandsdict keys from JSON-encoded strings toRunnerKey— a Pydantic-validatedtuple[str, ...]that parses JSON strings at model validation time - Change
ReleaseExecutor.build()to acceptstr | list[str] | Nonefor the runner parameter — JSON strings from CI are parsed via theRunnerKeyvalidator instead of a separateparse_runnerfunction
[v0.16.0] - 2026-03-27
Added
- Add
validate-planCI job that runs first in the release pipeline — validates the plan JSON as aReleasePlanand pretty-prints it to stdout - Add
uvr validate-planCLI subcommand for validating and displaying a release plan
Changed
- Change pipeline order to
validate-plan → build → publish → finalize— build now depends on validate-plan
[v0.15.0] - 2026-03-27
Added
- Add
ReleaseHookplugin system for extending the release pipeline with Python hooks — supports local hooks (pre_plan/post_plan) and CI hooks (pre_build/post_build/pre_release/post_release/pre_finalize/post_finalize) (ADR-0011) - Add
[tool.uvr.hooks]config key and convention-based discovery (uvr_hooks.pyat workspace root) - Export
ReleaseHookandReleasePlanfromuv_releasepackage root
Changed
- Replace
gitandghsubprocess calls with pygit2 and httpx for faster release planning (ADR-0012) - Change
uvr init --upgradeto use three-way merge for combining template updates with user customizations (ADR-0013) - Bump
ReleasePlanschema version to 8 — plans now preserve extra keys injected by hooks
[v0.14.3] - 2026-03-27
Changed
- Deduplicate subprocess calls in the planning phase — fetch git tags and GitHub releases once instead of 3x and 2x respectively
- Batch per-package baseline tag lookups into a single
git tag --listcall with Python set filtering (eliminates N subprocess calls) - Parallelize per-package
git diffchange detection withThreadPoolExecutor - Pre-compute release notes once instead of regenerating per caller
[v0.14.2] - 2026-03-27
Fixed
- Fix build commands failing on Windows runners — replace
mkdir -pandfind -deletewith cross-platformuv run python -cequivalents (#9)
[v0.14.1] - 2026-03-27
Fixed
- Fix
uvr init --upgradestep matching to use all of id/name/uses for cross-matching between old and new templates - Fix
uvr init --upgradeto block on uncommitted release.yml changes and handle quit gracefully - Remove special characters from CLI output
[v0.14.0] - 2026-03-27
Added
- Add
uvr init --upgradeto update frozen template fields in an existingrelease.ymlwhile preserving custom jobs, triggers, and env vars - Add
uvr skill initto copy bundled Claude Code skills into your project
[v0.13.4] - 2026-03-27
Fixed
- Fix
uvr build/uvr finalizefailing on Windows runners —--plannow falls back to theUVR_PLANenvironment variable and supports@fileinput (#8)
Changed
- Change workflow template to omit
--plan "$UVR_PLAN"from build/finalize run commands — re-runuvr initto update existing workflows
[v0.13.3] - 2026-03-27
Fixed
- Fix
uvr statusbuild display to show all packages built per runner, including transitive deps marked with(dep)
[v0.13.2] - 2026-03-27
Fixed
- Fix cross-runner builds failing when a workspace dependency is only assigned to a different runner — unchanged deps are now fetched into
deps/and changed transitive deps are built on every runner that needs them (#7)
[v0.13.1] - 2026-03-27
Fixed
- Fix topo-sort not considering
[build-system].requiresdependencies, causing concurrent builds to fail when a package's build-time dep hadn't finished building (#6)
[v0.13.0] - 2026-03-27
Changed
- Move version setting and dependency pinning from CI build commands to local pre-dispatch —
uvr releasenow commits release versions before dispatching to CI, so release tags point at commits with the correct version (ADR-0010)
[v0.12.0] - 2026-03-27
Changed
- Change
uvr release --jsonto output only the plan JSON to stdout — no human-readable output, no worktree check, no dispatch prompt
[v0.11.3] - 2026-03-27
Fixed
- Fix layered builds resolving workspace sources instead of pre-built wheels —
uv buildnow passes--no-sourcesfor layer 1+ packages (#5)
[v0.11.2] - 2026-03-27
Changed
- Change
uvr runnersto group output by runner instead of by package and show the default (ubuntu-latest) for unconfigured packages
[v0.11.1] - 2026-03-27
Fixed
- Fix
uvr releaseCI dispatch checking out the default branch instead of the dispatching branch
[v0.11.0] - 2026-03-27
Changed
- Move dependency pin writes from local two-pass flow to inline
uvr pin-depscommands in the build plan (ADR-0009) — pins are only applied if the build succeeds
Fixed
- Fix
set_versionandpin_dependenciescrashing on pyproject.toml files without a[project]table
[v0.10.0] - 2026-03-27
Added
- Add parallel builds within runners — packages at the same dependency depth build concurrently using topological layers
[v0.9.0] - 2026-03-27
Added
- Add self-hosted runner support — runners are now label sets (e.g.
uvr runners pkg --add "self-hosted,linux,x64") - Add tag and release conflict detection — planner validates no planned tags/releases already exist before dispatching
- Add
--where localplatform check — errors when changed packages have runners for a different OS - Add HEAD-vs-remote sync check before CI dispatch
Changed
- BREAKING: Remove hook jobs from workflow model —
uvr initgenerates onlybuild,release,finalize; users add their own jobs by editingrelease.yml - BREAKING: Remove
uvr set-versionsubcommand — planner emitsuv versioncommands instead - BREAKING: Change runner type from
strtolist[str]inMatrixEntry,ReleasePlan, and[tool.uvr.matrix] - BREAKING: Require
org/repo/pkgformat foruvr install(bare package names no longer accepted) - Change
uvr statusto an alias foruvr release --dry-run - Improve dry-run output: column headers, current → release version display, version rewrite visibility in build section
- Rewrite README with usage-focused sections
Removed
- Remove
uvr set-versionsubcommand (useuv versiondirectly) - Remove hook job classes (
HookJob,PreBuildJob,PostBuildJob,PreReleaseJob,PostReleaseJob) - Remove
_NOOP_STEPSconstant and auto-skip logic for no-op hooks
Fixed
- Fix publish workflow
files:pattern missingdist/prefix — wheels not attached to GitHub releases - Fix conflict error suggesting deletion as first option — now shows
--postand version bump first
[v0.8.0] - 2026-03-26
Added
- Add
--dev,--pre {a,b,rc}, and--postflags touvr releasefor PEP 440 dev, pre, and post releases (ADR-0008) - Add
uvr build,uvr finalize,uvr set-version, anduvr pin-depssubcommands (previously separateuvr-cientry point) - Add
--where {ci,local}flag touvr release— replaces the separateuvr runcommand - Add
--dry-runflag touvr releasefor previewing the release plan without changes - Add
PlanCommandmodel for pre-computed shell commands in the release plan - Add
ReleasePlannerclass as the single entry point for creating release plans
Changed
- BREAKING: Remove
uvr runcommand — useuvr release --where localinstead - BREAKING: Remove
uvr-ci/uvr-stepsentry point — all subcommands are now underuvr - BREAKING: Rename CI subcommand
build-alltobuild - BREAKING: Bump
ReleasePlanschema version to 6 — plans include pre-computed command sequences - Change
ReleaseExecutorto a pure command runner — all domain logic moved toReleasePlanner - Change
find_release_tagsto query GitHub releases instead of git tags - Change release tag lookup to only match versions below the current base version
- Change
BumpPlan.new_versionto store the exact pyproject.toml version (includes.dev0suffix) - Improve
uvr --helpwith grouped command listing (Commands, CI steps, Low-level) - Improve
uvr release --helpwith argument groups (mode, build, dispatch, local, output) - Column-align package, build, and finalize sections in dry-run output
Removed
- Remove
pipeline/re-export package — all imports useshared.*directly - Remove
ci/package — step functions inlined into CLI - Remove
run_release(),execute_plan(),bump_versions(),collect_published_state()functions - Remove legacy
-devbaseline tag handling
Fixed
- Fix
--dry-runnot showing auto-skipped no-op hook jobs - Fix
--devrelease silently publishing a clean version when pyproject.toml has no.devsuffix - Fix double
.dev0.dev0in post-release bump versions - Fix pre-release bump producing a patch bump instead of next pre-release
.dev0(e.g.a0→a1.dev0) - Fix post-release bump producing
.post0.dev0instead of.post1.dev0
[v0.6.1] - 2026-03-25
Added
- Add
--skip JOBand--skip-to JOBflags touvr releasefor skipping individual or ranges of jobs in the pipeline - Add
--reuse-run RUN_IDand--reuse-releaseflags for reusing build artifacts from a previous workflow run or existing GitHub releases - Add
skipandreuse_run_idworkflow dispatch inputs with per-jobif:conditions - Add
JOB_ORDERconstant defining the canonical pipeline job ordering
Fixed
- Fix
GH_TOKENnot being set in post-release download step - Fix duplicate
if:keys in generated workflow when hook jobs had template-generated skip conditions
[v0.6.0] - 2026-03-25
Added
- Add
uvr workflowcommand for reading, writing, and deleting any key inrelease.ymlwith--set,--add,--insert --at,--remove, and--clearflags - Add
uvr runners PKG --add/--remove/--clear RUNNERcommand for managing per-package build runners - Add
ReleaseWorkflowPydantic model validating the full workflow YAML schema before writes - Add
ruamel-yamldependency for lossless YAML round-tripping (preserves key order, comments, quote style)
Changed
- BREAKING: Remove
-m/--matrixflag fromuvr init— useuvr runnersinstead - BREAKING: Replace
uvr hooks PHASE {add|insert|remove|update|clear}positional subcommands with flag-based--add/--insert --at/--set/--remove/--clear - Split monolithic
cli.py(1461 lines) intocli/package with one module per command
Fixed
- Fix
on:key being serialized astrue:after YAML round-trip (PyYAML boolean coercion) - Fix PyYAML corrupting GitHub Actions
${{ }}expressions with double-quoted single quotes - Fix PyYAML reordering top-level YAML keys on write
[v0.5.0] - 2026-03-25
Added
- Add per-runner build matrix where each runner builds all assigned packages in dependency order via
uvr-steps build-all - Add
topo_layers()for computing dependency depth in the package graph - Add
runnersanddist_namefields toReleasePlan(schema version 4)
Changed
- BREAKING: Replace per-package parallel matrix with per-runner matrix — fixes build failures when packages have build-time dependencies on sibling workspace packages
- BREAKING: Rename
--force-allto--rebuild-all - Publish job filters wheels by
dist_namefor per-package GitHub releases
Fixed
- Fix CI dispatch pinning
uvr_versionto a.devversion that doesn't exist on PyPI - Fix shell quoting issues with plan JSON by passing it via environment variable
[v0.4.2] - 2026-03-23
Added
- Add tag-triggered PyPI publish workflow (
uv-release/v*tags, excluding-dev) - Add
make_latestfield toPublishEntry, driven by[tool.uvr.config] latestsetting
Fixed
- Fix glob wildcard for tag pattern in publish workflow trigger
[v0.4.1] - 2026-03-23
Fixed
- Fix PyPI publish rebuilding from HEAD (which picked up the
.dev0bump) — now downloads the wheel directly from the GitHub release artifact
[v0.4.0] - 2026-03-23
Added
- Add
[tool.uvr.config]withincludeandexcludelists for package filtering - Add
--yes/-yflag to skip the confirmation prompt
Changed
- BREAKING:
uvr releasenow prints the plan and prompts before dispatching — read-only by default (replaces--dry-run) - BREAKING: Remove
--dry-runflag fromuvr release - Replace shell scripts in release workflow with real GitHub Actions (
softprops/action-gh-release) - Move dependency pinning from CI to local planning —
build_plan()pre-computes all version bumps, CI applies them viaapply_bumps() - Add
BumpPlanmodel andbumpsfield toReleasePlan - Add precomputed release notes via
PublishEntryandgenerate_release_notes() - Bump
ReleasePlanschema version to 3
[v0.3.1] - 2026-03-20
Fixed
- Fix dogfood release by using
uv run uvr-stepsfrom workspace instead of global install
[v0.3.0] - 2026-03-20
Added
- Plan+execute architecture:
uvr releasebuilds aReleasePlanlocally and dispatches it to CI as a pure executor - Per-package GitHub releases tagged
{package}/v{version} uvr install PACKAGE[@VERSION]with transitive internal dependency resolutionuvr install ORG/REPO/PACKAGE[@VERSION]for remote installs--python VERSIONflag to pin CI Python version (default 3.12)uvr-stepsCLI entry point for workflow step dispatchuvr statuscommand showing workflow config and changed packages
Changed
- BREAKING: Replace
lazy-wheelspackage entirely withuv-release - Matrix config moved to
[tool.uvr.matrix]in workspace rootpyproject.toml
Removed
- Remove
lazy-wheelspackage and all associated code