Skip to main content

uv-upsync

Python PyPI CI Ruff StandWithUkraine

Overview

uv-upsync is a uv-native tool for automated dependency updates and version bumping in pyproject.toml.

uv lock --upgrade refreshes your lockfile but leaves the lower bounds in pyproject.toml untouched, so httpx>=0.24.0 stays >=0.24.0 forever. uv-upsync raises those human-authored bounds to the latest published version, re-locks with uv, and rolls back if the resolution fails. Your formatting, comments, operators, extras and environment markers are preserved.

Features

  • Familiar uv flags (--project, --upgrade-package, --all-groups, --offline, --no-cache, --color), uv-style output and a uv lock round-trip with automatic rollback on failure
  • Versions are resolved from the PEP 691 index configured for your project via [[tool.uv.index]], so private indexes work out of the box
  • Specifiers are parsed with packaging, the canonical PEP 440/508 implementation, not regular expressions
  • Only lower bounds (>=, >, ~=) are raised; pinned (==) requirements are never touched
  • Compound specifiers like >=1.2,<2.0 have their floor raised to the latest version that still satisfies the cap (<2.0) and any exclusions (!=)
  • --max-bump patch|minor|major holds back larger jumps (auto-apply minors, review majors), and --prerelease opts into pre-release versions
  • Only the version token is rewritten; everything else, including comments and markers, is kept verbatim
  • Version lookups are fetched concurrently and cached
  • Target specific groups or packages, or exclude packages
  • Defaults live in a [tool.uv-upsync] table and can be overridden per run
  • By default an upgrade that does not resolve is held back individually instead of failing the whole run (--strict to opt out)
  • --dry-run previews the changes, --check gates CI
  • --format json for tooling, --format markdown for pull request bodies
  • Ships a pre-commit hook and a GitHub Action

Installation

Run it without installing:

uvx uv-upsync

Or add it to your development dependencies:

uv add --dev uv-upsync

Usage

The examples below assume uv-upsync is installed. If it isn't, prefix any command with uvx to run it without installing (e.g. uvx uv-upsync --dry-run).

By default, uv-upsync upgrades every dependency in the pyproject.toml found in the current directory:

$ uv-upsync
Updated click v8.1.8 -> v8.2.1
Updated httpx v0.27.0 -> v0.28.1
Resolved 12 packages in 184ms
Updated 2 dependencies in pyproject.toml
Locked dependencies

Nothing to do is reported the way uv reports it:

$ uv-upsync
Resolved 12 packages in 121ms
Audited 12 dependencies, all up to date

Options

Option Description
--project <DIR> Path to the project directory containing the pyproject.toml
--directory <DIR> Change to DIR before running
-P, --upgrade-package <PKG> Allow upgrades for only the given package(s)
--exclude <PKG> Package(s) to exclude from upgrading
--group <NAME> Upgrade dependencies in the given group(s) only
--all-groups Upgrade dependencies in all groups
--max-bump <level> Limit upgrades to at most patch, minor, or major
--prerelease Allow upgrading to pre-release versions
--index-url <URL> Base URL of the PEP 691 package index (defaults to the project's uv index or PyPI)
--offline Disable network access, using only cached data
-n, --no-cache Avoid reading from or writing to the cache
--dry-run Preview the upgrades without writing to pyproject.toml
--check Exit with a non-zero status if any upgrades are available
--strict Roll back every upgrade and fail if the result does not lock
--no-lock Write the upgrades without running uv lock
--resolve When an upgrade does not lock, bump to the latest version that does
-q, --quiet Use quiet output
-v, --verbose Use verbose output (shows skipped dependencies)
--format <text|json|markdown> Output format for the upgrade summary
--color <auto|always|never> Control the use of color in output
-V, --version Show the version and exit

uv-upsync understands all three dependency tables: project.dependencies, project.optional-dependencies, and dependency-groups (PEP 735).

Resolution

After bumping the specifiers, uv-upsync re-locks with uv. If the combined upgrade does not resolve, the default best-effort mode keeps the largest subset of upgrades that locks and reports which ones were held back, naming the conflicting dependency when it can. A single incompatible dependency never costs you the rest:

$ uv-upsync
Resolved 2 packages in 153ms
Updated idna v2.0 -> v3.17
Updated 1 dependency in pyproject.toml
warning: Held back docutils v0.16 -> v0.23 (conflicts with sphinx)
Locked dependencies

With --resolve, an upgrade that does not lock at its latest version is bisected for the latest version that does, instead of being held back entirely:

$ uv-upsync --resolve
Updated idna v2.0 -> v3.17
Updated numpy v1.20 -> v2.0.2   # 2.4.6 needs a newer Python; 2.0.2 is the latest that fits
Updated 2 dependencies in pyproject.toml
Locked dependencies

Use --strict to instead roll back every upgrade and fail (exit code 2) if the result does not lock, or --no-lock to write the upgrades and skip locking entirely.

Configuration

uv-upsync reads defaults from a [tool.uv-upsync] table in your pyproject.toml, so you don't have to repeat them on every run:

[tool.uv-upsync]
exclude = ["click", "ruff"]               # never upgrade these packages
group = ["project", "test"]               # only these groups (omit for all)
upgrade-package = ["httpx"]               # only these packages
all-groups = true                         # upgrade every group
max-bump = "minor"                        # hold back major upgrades
prerelease = false                        # allow pre-release versions
resolve = false                           # bisect for the latest version that locks
index-url = "https://example.com/simple"  # PEP 691 index to query

Settings are resolved with the precedence command line > [tool.uv-upsync] > defaults: passing a flag always overrides the matching setting. The index is resolved as --index-url > [tool.uv-upsync].index-url > [[tool.uv.index]] > PyPI.

Examples

Preview the Upgrades

uv-upsync --dry-run

Upgrade a Single Package

uv-upsync --upgrade-package httpx

Exclude Packages

uv-upsync --exclude click --exclude ruff

Upgrade Specific Groups

# Only the project dependencies
uv-upsync --group project

# A couple of named groups
uv-upsync --group test --group docs

Fail CI When Dependencies Are Stale

uv-upsync --check

--check writes nothing and exits with a non-zero status when upgrades are available, which makes it easy to wire into a scheduled job or pre-merge gate.

Pre-commit

Add uv-upsync to your pre-commit configuration:

repos:
  - repo: https://github.com/pivoshenko/uv-upsync
    rev: v2.3.2
    hooks:
      - id: uv-upsync

Two hooks are available:

  • uv-upsync upgrades the bounds in pyproject.toml and re-locks (runs uv lock, so uv must be on your PATH)
  • uv-upsync-check fails the commit if any dependency can be upgraded, without writing changes

GitHub Action

Keep dependencies fresh on a schedule and open a pull request with the results:

name: upgrade-dependencies
on:
  schedule:
    - cron: "0 6 * * 1" # every Monday
  workflow_dispatch:

jobs:
  upsync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - id: upsync
        uses: pivoshenko/uv-upsync@v2.3.2
        with:
          args: --all-groups --format markdown
      - uses: peter-evans/create-pull-request@v6
        with:
          commit-message: "build: upgrade dependencies"
          title: "build: upgrade dependencies"
          body: ${{ steps.upsync.outputs.summary }}
          branch: build/uv-upsync

With --format markdown the action's summary output is a ready-made pull request body (⬆️ click 8.1.8 → 8.2.1 ...). To gate pull requests instead, run the action with args: --check and drop the pull request step.

Input Description Default
args Additional arguments passed to uv-upsync ""
version Version of uv-upsync to run latest
working-directory Directory to run in .
Output Description
summary The upgrade summary printed by uv-upsync

Metadata

Release files for uv-upsync 2.4.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for uv-upsync 2.4.2
File Size Uploaded
uv_upsync-2.4.2.tar.gz 68.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for uv-upsync 2.4.2
File Interpreter ABI Platform
uv_upsync-2.4.2-py3-none-any.whl Python 3 none any Details

Total release size: 89.8 kB

Release files / uv_upsync-2.4.2.tar.gz

Download URL uv_upsync-2.4.2.tar.gz
Size 68.2 kB
Tags Source
SHA-256 checksum
How to use checksums
48b48dd72b3f715f9f9f975b2a45879354eb7d92d1c8030fe575732f92aa26ee
BLAKE2b-256 checksum
How to use checksums
3d79d7977363985f84f6fbad683ab45bc7fef06915ab31b77eac34ba49661c4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / uv_upsync-2.4.2-py3-none-any.whl

Download URL uv_upsync-2.4.2-py3-none-any.whl
Size 21.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
95f479dfa92b485ede85d8a4d74176fa8154cd7da7e22ba7a99e33e6e089e039
BLAKE2b-256 checksum
How to use checksums
b6db839e6b0cdba11ff20bf526903aa0adc712c94ecb8ebcede4839b6e6fb68c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

2.4.2 This release

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.2

2 release files

2.3.1

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page