uv-upsync 2.4.1__tar.gz → 2.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/.editorconfig +4 -0
  2. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/.github/PULL_REQUEST_TEMPLATE.md +1 -1
  3. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/.github/workflows/ci.yaml +7 -10
  4. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/.github/workflows/release.yaml +22 -13
  5. uv_upsync-2.4.2/.python-version +1 -0
  6. uv_upsync-2.4.2/AGENTS.md +1 -0
  7. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/CHANGELOG.md +68 -0
  8. uv_upsync-2.4.2/CLAUDE.md +73 -0
  9. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/CODE_OF_CONDUCT.md +13 -0
  10. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/CONTRIBUTING.md +48 -14
  11. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/PKG-INFO +32 -30
  12. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/README.md +25 -25
  13. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/SECURITY.md +3 -3
  14. uv_upsync-2.4.1/action.yml → uv_upsync-2.4.2/action.yaml +1 -1
  15. uv_upsync-2.4.2/assets/logo.svg +1 -0
  16. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/cliff.toml +2 -0
  17. uv_upsync-2.4.2/justfile +23 -0
  18. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/pyproject.toml +8 -7
  19. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/__init__.py +1 -1
  20. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/__main__.py +4 -4
  21. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/commands.py +2 -2
  22. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/config.py +1 -1
  23. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/logging.py +6 -2
  24. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/parsers.py +1 -1
  25. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/pypi.py +2 -1
  26. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/report.py +1 -1
  27. uv_upsync-2.4.2/tests/__init__.py +3 -0
  28. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/conftest.py +1 -1
  29. uv_upsync-2.4.2/uv.lock +535 -0
  30. uv_upsync-2.4.1/.github/labels.yaml +0 -59
  31. uv_upsync-2.4.1/.github/workflows/labels.yaml +0 -34
  32. uv_upsync-2.4.1/.python-version +0 -1
  33. uv_upsync-2.4.1/CLAUDE.md +0 -60
  34. uv_upsync-2.4.1/assets/logo.svg +0 -2
  35. uv_upsync-2.4.1/justfile +0 -26
  36. uv_upsync-2.4.1/tests/__init__.py +0 -3
  37. uv_upsync-2.4.1/uv.lock +0 -521
  38. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/.gitignore +0 -0
  39. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/.pre-commit-hooks.yaml +0 -0
  40. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/LICENSE +0 -0
  41. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/exceptions.py +0 -0
  42. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/src/uv_upsync/uv.py +0 -0
  43. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_commands.py +0 -0
  44. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_config.py +0 -0
  45. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_exceptions.py +0 -0
  46. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_logging.py +0 -0
  47. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_parsers.py +0 -0
  48. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_pypi.py +0 -0
  49. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_report.py +0 -0
  50. {uv_upsync-2.4.1 → uv_upsync-2.4.2}/tests/test_uv.py +0 -0
@@ -13,3 +13,7 @@ trim_trailing_whitespace = true
13
13
  [{*.py,*.pyi,*.ipynb}]
14
14
  indent_size = 4
15
15
  tab_width = 4
16
+
17
+ [{*.rs}]
18
+ indent_size = 4
19
+ tab_width = 4
@@ -1,6 +1,6 @@
1
1
  # Pull Request Checklist
2
2
 
3
- <!-- Optional — uncomment if this PR closes an issue -->
3
+ <!-- Optional: uncomment if this PR closes an issue -->
4
4
  <!-- Resolves: #issue-number-here -->
5
5
 
6
6
  ## Summary
@@ -7,26 +7,26 @@ on:
7
7
  workflow_dispatch:
8
8
 
9
9
  concurrency:
10
- group: ci-${{ github.workflow }}-${{ github.ref }}
11
- cancel-in-progress: ${{ github.event_name == 'pull_request' }}
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
12
12
 
13
13
  permissions:
14
14
  contents: read
15
15
 
16
16
  jobs:
17
17
  ci:
18
- runs-on: ubuntu-latest
18
+ runs-on: ubuntu-24.04-arm
19
19
  steps:
20
20
  - name: Checkout repository
21
- uses: actions/checkout@v6
21
+ uses: actions/checkout@v7
22
22
 
23
23
  - name: Install just
24
- uses: extractions/setup-just@v3
24
+ uses: extractions/setup-just@v4
25
25
 
26
26
  - name: Install uv
27
- uses: astral-sh/setup-uv@v6
27
+ uses: astral-sh/setup-uv@v10.1.0
28
28
  with:
29
- python-version: "3.13"
29
+ python-version: "3.14"
30
30
 
31
31
  - name: Install dependencies
32
32
  run: just install
@@ -36,6 +36,3 @@ jobs:
36
36
 
37
37
  - name: Run tests
38
38
  run: just test
39
-
40
- - name: Run audit
41
- run: just audit
@@ -10,14 +10,18 @@ on:
10
10
  permissions:
11
11
  contents: write
12
12
 
13
+ concurrency:
14
+ group: release
15
+ cancel-in-progress: false
16
+
13
17
  jobs:
14
18
  tag:
15
- runs-on: ubuntu-latest
19
+ runs-on: ubuntu-24.04-arm
16
20
  outputs:
17
21
  tag: v${{ steps.version.outputs.version }}
18
22
  steps:
19
23
  - name: Checkout repository
20
- uses: actions/checkout@v6
24
+ uses: actions/checkout@v7
21
25
  with:
22
26
  fetch-depth: 0
23
27
 
@@ -30,20 +34,22 @@ jobs:
30
34
  run: echo "$RUNNER_TEMP/git-cliff/bin" >> "$GITHUB_PATH"
31
35
 
32
36
  - name: Install uv
33
- uses: astral-sh/setup-uv@v6
37
+ uses: astral-sh/setup-uv@v10.1.0
34
38
  with:
35
- python-version: "3.13"
39
+ python-version: "3.14"
36
40
 
37
41
  - name: Resolve version
38
42
  id: version
39
43
  run: |
40
44
  if [[ -n "${{ github.event.inputs.version }}" ]]; then
41
45
  VERSION="${{ github.event.inputs.version }}"
46
+ VERSION="${VERSION#v}"
42
47
  else
43
48
  VERSION=$(git-cliff --bumped-version)
44
49
  VERSION="${VERSION#v}"
45
50
  fi
46
51
  echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
52
+ echo "resolved version: ${VERSION}"
47
53
 
48
54
  - name: Update version
49
55
  run: uv version "${{ steps.version.outputs.version }}"
@@ -67,42 +73,45 @@ jobs:
67
73
 
68
74
  release:
69
75
  needs: tag
70
- runs-on: ubuntu-latest
76
+ runs-on: ubuntu-24.04-arm
71
77
  steps:
72
78
  - name: Checkout repository
73
- uses: actions/checkout@v6
79
+ uses: actions/checkout@v7
74
80
  with:
75
81
  ref: ${{ needs.tag.outputs.tag }}
76
82
  fetch-depth: 0
77
83
 
78
- - name: Generate Changelog
84
+ - name: Generate changelog
79
85
  uses: orhun/git-cliff-action@v4
80
86
  id: changelog
81
87
  with:
82
88
  args: --latest --strip header
83
89
 
84
90
  - name: Create GitHub Release
85
- uses: softprops/action-gh-release@v2
91
+ uses: softprops/action-gh-release@v3
86
92
  with:
87
93
  tag_name: ${{ needs.tag.outputs.tag }}
88
94
  body: ${{ steps.changelog.outputs.content }}
89
95
 
90
96
  publish:
91
97
  needs: [tag, release]
92
- runs-on: ubuntu-latest
98
+ runs-on: ubuntu-24.04-arm
99
+ permissions:
100
+ contents: read
101
+ id-token: write
93
102
  steps:
94
103
  - name: Checkout repository
95
- uses: actions/checkout@v6
104
+ uses: actions/checkout@v7
96
105
  with:
97
106
  ref: ${{ needs.tag.outputs.tag }}
98
107
 
99
108
  - name: Install uv
100
- uses: astral-sh/setup-uv@v6
109
+ uses: astral-sh/setup-uv@v10.1.0
101
110
  with:
102
- python-version: "3.13"
111
+ python-version: "3.14"
103
112
 
104
113
  - name: Build
105
114
  run: uv build
106
115
 
107
116
  - name: Publish to PyPI
108
- run: uv publish --token ${{ secrets.PYPI_TOKEN }}
117
+ run: uv publish --trusted-publishing always
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1 @@
1
+ CLAUDE.md
@@ -2,6 +2,70 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.4.2] - 2026-09-20
6
+
7
+ ### Bug fixes
8
+
9
+ - Import Self from typing-extensions for python 3.10
10
+ - Import Self under TYPE_CHECKING to restore Python 3.10 support
11
+ - **commands**: Widen write_dl rows annotation to Iterable
12
+
13
+ ### Build
14
+
15
+ - Bump python to 3.14
16
+ - Update dependencies
17
+ - Update dependencies
18
+ - Update dependencies
19
+ - **deps**: Update dependency lockfile
20
+ - **deps**: Update dependencies
21
+ - **deps**: Update dependencies
22
+
23
+ ### CI/CD
24
+
25
+ - Pin workflow python to 3.14 and rename action.yml to yaml
26
+ - Pin setup-uv to v10.1.0
27
+ - Drop label sync in favor of terraform
28
+ - Publish to pypi via trusted publishing instead of a token
29
+ - Ignore rules newly stabilized in ruff 0.16
30
+ - Drop ruff format --check from lint; suppress more ty rules
31
+ - Use uv run pytest for project venv; format example file
32
+ - Fix action versions and test recipe failures
33
+ - Drop hashFiles guard; move .no-tests sentinel handling into justfile
34
+ - Flatten to one job per language
35
+ - Bump action versions to latest major
36
+ - Standardize workflow to per-language parallel pipelines on ubuntu-24.04-arm
37
+
38
+ ### Documentation
39
+
40
+ - Use absolute raw url for logo and refresh version notes
41
+ - Rewrite CLAUDE.md from scratch
42
+ - Regenerate CLAUDE.md and add AGENTS.md
43
+ - **release**: Drop trusted publishing header comments
44
+ - Add pull request template
45
+ - Shorten module docstring to fit the line-length limit
46
+ - Regenerate CLAUDE.md
47
+ - Document the module docstring convention
48
+ - Normalize module and package docstrings
49
+ - Normalize punctuation and drop AI-flavored phrasing
50
+ - Refresh CLAUDE.md for current justfile + CI shape
51
+ - **ci**: Document required secrets at top of workflow files
52
+
53
+ ### Miscellaneous
54
+
55
+ - **assets**: Drop svg repo attribution comments
56
+ - Repository housekeeping
57
+ - Symlink AGENTS.md to CLAUDE.md
58
+ - Remove local pull request template
59
+ - **deps**: Update locked dependencies
60
+ - Update dependency lockfile
61
+ - Add editorconfig
62
+ - **justfile**: Use uv lock --upgrade for update, scope pyupgrade to . excluding .venv
63
+ - Standardize justfile recipes and refresh CLAUDE.md
64
+
65
+ ### Refactor
66
+
67
+ - **justfile**: Standardize recipe names and ordering
68
+
5
69
  ## [2.4.1] - 2026-05-31
6
70
 
7
71
  ### Build
@@ -24,6 +88,10 @@ All notable changes to this project will be documented in this file.
24
88
 
25
89
  - Tidy logging and parser internals
26
90
 
91
+ ### Release
92
+
93
+ - V2.4.1
94
+
27
95
  ## [2.4.0] - 2026-05-30
28
96
 
29
97
  ### Bug fixes
@@ -0,0 +1,73 @@
1
+ # uv-upsync
2
+
3
+ ## What This Is
4
+
5
+ A single-command CLI that raises the **lower bounds of dependency specifiers in `pyproject.toml`** to the latest published versions, then re-locks with `uv`.
6
+
7
+ The distinction that defines the whole project: `uv lock --upgrade` refreshes the **lockfile** but leaves `httpx>=0.24.0` written as `>=0.24.0` forever. `uv-upsync` rewrites the human-authored bound in `pyproject.toml` itself, and does so surgically - only the version token is replaced, so operators, extras, environment markers, spacing and comments survive verbatim.
8
+
9
+ Published to PyPI as `uv-upsync`. `README.md` owns the option table, the `[tool.uv-upsync]` keys and the usage examples.
10
+
11
+ ## Distribution Surfaces
12
+
13
+ Any change to the CLI flags has to land in four places, not one:
14
+
15
+ 1. `src/uv_upsync/__main__.py` - the click options
16
+ 2. `README.md` - the options table and the `[tool.uv-upsync]` example block
17
+ 3. `action.yaml` - the composite GitHub Action (passes `inputs.args` through to `uvx uv-upsync`, captures stdout into a `summary` output for PR bodies)
18
+ 4. `.pre-commit-hooks.yaml` - the `uv-upsync` and `uv-upsync-check` hooks, both `pass_filenames: false` and gated on `^pyproject\.toml$`
19
+
20
+ A new config key also needs a branch in `config.load_config` plus its validator, and the corresponding `flag = flag or settings.flag` line in `cli`.
21
+
22
+ ## Invariants Worth Knowing Before Editing
23
+
24
+ - **Only lower bounds are raised.** `UPGRADABLE_OPERATORS = {">=", ">", "~="}`; `==`/`===` are never touched, and a specifier with more or fewer than exactly one lower-bound clause is skipped entirely. This conservatism mirrors uv's `--upgrade` and is deliberate
25
+ - **Compound specifiers keep their cap.** `upgradable_specifier` splits off a residual `SpecifierSet` (the `<2.0`, the `!=`s) that every candidate version must still satisfy
26
+ - **`_replace_version` is a token swap, not a re-serialization.** It partitions on `;` to protect markers, then does a single `str.replace` from the operator onward. Do not "improve" this into a `str(Requirement)` round-trip - that would normalize the author's formatting, which is exactly what the tool promises not to do
27
+ - **Settings precedence is CLI > `[tool.uv-upsync]` > defaults**, implemented in `cli` as `flag = flag or settings.flag`. This means a falsy CLI value cannot override a truthy config value, which is intended for the flag-shaped options
28
+ - **The lock strategy has three modes.** The full upgrade set is tried first. On failure: `--strict` restores the deep-copied `backup` document and exits 2; the default best-effort mode re-locks incrementally to keep the maximal subset that resolves; `--resolve` additionally binary-searches `eligible_versions` for the highest version of a failing package that does lock. `_apply_with_lock` always rewrites the accepted set at the end, because the last trial may have left a failing candidate on disk
29
+ - **Exit codes:** `0` success, `1` from `--check` when upgrades exist, `2` (`ERROR_EXIT_CODE`) for any error. `main()` catches everything and renders uv-style `error:` lines instead of tracebacks, re-raising the traceback only under `--verbose`
30
+ - **Non-text `--format` implies quiet.** `logger.configure(quiet=quiet or output_format != "text", ...)` keeps stdout parseable
31
+
32
+ ## Architecture
33
+
34
+ Single flow, no plugin system, no async. `__main__.py` is the orchestrator and everything else is a leaf module it calls.
35
+
36
+ ```
37
+ __main__.cli
38
+ -> config.load_config read [tool.uv-upsync] defaults
39
+ -> parsers.iter_dependency_groups locate the live tomlkit arrays
40
+ -> pypi.PyPIClient.fetch_many concurrent PEP 691 lookups
41
+ -> parsers.plan_updates compute the bumps (pure, no mutation)
42
+ -> __main__._apply_with_lock write + `uv lock`, with fallback strategies
43
+ -> report.render / logging.Logger emit the summary
44
+ ```
45
+
46
+ The module boundaries that carry a rule (the rest is `ls src/uv_upsync/`):
47
+
48
+ - `__main__.py` owns the entire click command surface - every flag is declared there - plus the write/lock/rollback orchestration
49
+ - `parsers.py` owns all TOML and specifier logic: group iteration, requirement parsing, eligibility, bump policy, surgical rewrite, conflict extraction from uv's stderr
50
+ - `report.py` is JSON and Markdown renderers only - text output belongs to `logging.Logger`, not to this module
51
+
52
+ ## Commands
53
+
54
+ `just --list` and `CONTRIBUTING.md` carry the recipe table; CI runs the same recipes, so a green `just check` locally means a green CI. Two things the table does not say:
55
+
56
+ - `just format` and `just lint` invoke ruff and ty via `uvx`, not from the project venv, so they resolve the latest release rather than the pinned one in `[dependency-groups]`. Version skew between the two is expected and occasionally shows up as new lint findings
57
+ - `just update` runs `uvx uv-upsync` against this repo - the tool eats its own dogfood here
58
+
59
+ Run the CLI itself with `uv run uv-upsync ...` (entry point `uv_upsync.__main__:main`).
60
+
61
+ ## Conventions
62
+
63
+ - Module docstrings follow the house phrasing `"""Module that contains ..."""`. Docstrings take sentence punctuation; code comments never end with a period
64
+ - **Tests mirror modules one-to-one** - `tests/test_<module>.py`. Mocking is `pytest-mock`'s `mocker` fixture, never `unittest.mock` directly. `conftest.py` resets `Logger._instance` between tests via an autouse fixture, because the logger is a process-wide singleton
65
+ - Everything else - ruff select and ignores, import style, line length, pytest `addopts` - lives in `pyproject.toml` and is enforced by `just lint`. Add a targeted `# noqa: RULE` at the site (as `__main__.cli` does) rather than widening the global ignores
66
+
67
+ ## Release
68
+
69
+ Fully automated - **do not bump the version in `pyproject.toml` by hand.** The `Release` workflow is `workflow_dispatch` only; git-cliff derives the next version from the commit history (or takes the `version` input), `uv version` writes it, `CHANGELOG.md` is regenerated, the tag is pushed, and PyPI publication goes through trusted publishing.
70
+
71
+ This makes **Conventional Commits load-bearing**: `cliff.toml` sets `filter_unconventional = true`, so a commit that doesn't match a known prefix is dropped from the changelog entirely, and `features_always_bump_minor` / `breaking_always_bump_major` decide the version. Use `<type>(<scope>): <subject>` with scopes like `parsers`, `pypi`, `config`, `cli`. `CONTRIBUTING.md` has the full prefix table, the branch pattern and the CI/CD workflow table.
72
+
73
+ `AGENTS.md` is a symlink to this file - edit `CLAUDE.md`, never the symlink.
@@ -1,5 +1,18 @@
1
1
  # Contributor Covenant Code of Conduct
2
2
 
3
+ - [Contributor Covenant Code of Conduct](#contributor-covenant-code-of-conduct)
4
+ - [Our Pledge](#our-pledge)
5
+ - [Our Standards](#our-standards)
6
+ - [Enforcement Responsibilities](#enforcement-responsibilities)
7
+ - [Scope](#scope)
8
+ - [Enforcement](#enforcement)
9
+ - [Enforcement Guidelines](#enforcement-guidelines)
10
+ - [Correction](#correction)
11
+ - [Warning](#warning)
12
+ - [Temporary Ban](#temporary-ban)
13
+ - [Permanent Ban](#permanent-ban)
14
+ - [Attribution](#attribution)
15
+
3
16
  ## Our Pledge
4
17
 
5
18
  We as members, contributors, and leaders pledge to make participation in our community a
@@ -1,8 +1,20 @@
1
1
  # Contributing
2
2
 
3
+ - [Contributing](#contributing)
4
+ - [Reporting Bugs](#reporting-bugs)
5
+ - [How to Submit a Bug Report](#how-to-submit-a-bug-report)
6
+ - [Suggesting Enhancements](#suggesting-enhancements)
7
+ - [How to Submit an Enhancement](#how-to-submit-an-enhancement)
8
+ - [Code Contributions](#code-contributions)
9
+ - [Local Development](#local-development)
10
+ - [CI/CD](#cicd)
11
+ - [Branches](#branches)
12
+ - [Commits](#commits)
13
+ - [Pull Requests](#pull-requests)
14
+
3
15
  Thank you for taking the time to contribute.
4
16
 
5
- These guidelines are intended to make contributions consistent and easy to review across repositories. They are guidance, not hard rules, and maintainers may adapt them when needed.
17
+ These guidelines are intended to make contributions consistent and easy to review across repositories. They are guidance, not hard instructions, and maintainers may adapt them when needed.
6
18
 
7
19
  ## Reporting Bugs
8
20
 
@@ -13,9 +25,9 @@ When opening a bug report, include enough context for someone else to reproduce
13
25
  > [!NOTE]
14
26
  > If you find a closed issue that looks similar, open a new issue and link the previous one.
15
27
 
16
- ### How To Submit a Bug Report
28
+ ### How to Submit a Bug Report
17
29
 
18
- Use the bug issue template and provide the following:
30
+ Open a bug report and provide the following:
19
31
 
20
32
  - A clear, descriptive title
21
33
  - Reproduction steps (minimal and reliable if possible)
@@ -32,9 +44,9 @@ Before submitting an enhancement, check whether a similar request already exists
32
44
 
33
45
  Enhancement requests can include new features, changes to existing behavior, usability improvements, or performance improvements.
34
46
 
35
- ### How To Submit an Enhancement
47
+ ### How to Submit an Enhancement
36
48
 
37
- Use the feature request template and provide the following:
49
+ Open a feature request and provide the following:
38
50
 
39
51
  - A clear problem statement
40
52
  - The proposed solution
@@ -47,15 +59,37 @@ Concrete examples, API sketches, UI mockups, or references are helpful when rele
47
59
 
48
60
  ### Local Development
49
61
 
50
- 1. Fork the repository and create a branch for your change.
51
- 2. Set up the project using the repository's README or development docs.
52
- 3. Run the project's tests and quality checks locally before opening a pull request.
62
+ This repo needs [uv](https://docs.astral.sh/uv), which manages Python 3.14 for you, and `just`.
63
+
64
+ This project uses [`just`](https://github.com/casey/just) as its task runner. Run `just --list` for the full set; these are the ones you need day to day:
53
65
 
54
- When a repository includes helper scripts or task runners, prefer using those documented commands.
66
+ | Command | What it does |
67
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
68
+ | `just install` | Installs every dependency group and extra into the project virtualenv |
69
+ | `just format` | Rewrites the sources in place: modernizes syntax to Python 3.10+ with pyupgrade, then applies ruff's safe fixes and formatting |
70
+ | `just lint` | Lints the project with ruff and type-checks it with ty, without changing any file |
71
+ | `just test` | Runs the test suite, skipped when the `.no-tests` sentinel is present |
72
+ | `just check` | Runs `lint` then `test` in sequence |
73
+ | `just update` | Refreshes the lockfile to the latest resolvable versions, then raises the dependency lower bounds in `pyproject.toml` with uv-upsync |
74
+
75
+ 1. Fork the repository and clone your fork locally
76
+ 2. Create a branch using the naming pattern described below
77
+ 3. Make your changes, then run `just check` before opening a pull request
55
78
 
56
79
  > [!IMPORTANT]
57
80
  > Behavioral code changes should include or update tests.
58
81
 
82
+ ### CI/CD
83
+
84
+ Workflows live in `.github/workflows`:
85
+
86
+ | Workflow | Trigger | What it does |
87
+ | --- | --- | --- |
88
+ | CI | Push to `main`, pull requests, `workflow_dispatch` | Single `ci` job on `ubuntu-24.04-arm`; installs `just` and uv pinned to Python 3.14, installs the project dependencies, then lints, type-checks and tests the project |
89
+ | Release | `workflow_dispatch` (optional `version` input) | Three chained jobs on `ubuntu-24.04-arm`: `tag` takes the version from the `version` input or derives the next one from the commit history with git-cliff, bumps the project version, regenerates `CHANGELOG.md` and pushes the release commit and its tag to `main`; `release` (needs `tag`) publishes the GitHub Release with the generated notes; `publish` (needs `tag` and `release`) builds the package and uploads it to PyPI via trusted publishing |
90
+
91
+ CI must be green before a pull request is merged.
92
+
59
93
  ### Branches
60
94
 
61
95
  Branch names follow the pattern `<type>/<short-description>` using the same type prefixes as commits.
@@ -70,7 +104,7 @@ docs/update-sync-flow-diagram
70
104
  refactor/mcps-schema-alignment
71
105
  ```
72
106
 
73
- A branch covering multiple unrelated changes should be split — one concern per branch makes review and bisect much easier.
107
+ A branch covering multiple unrelated changes should be split. One concern per branch makes review and bisect much easier.
74
108
 
75
109
  ### Commits
76
110
 
@@ -86,10 +120,10 @@ This project follows [Conventional Commits](https://www.conventionalcommits.org/
86
120
  [optional body]
87
121
  ```
88
122
 
89
- - **type** — one of the prefixes from the table below
90
- - **scope** — the module, command, or area being changed (e.g. `sync`, `mcps`, `github`, `landing`, `config`); omit when the change is truly cross-cutting
91
- - **subject** — imperative mood, lowercase, no trailing period, 72 characters or fewer
92
- - **body** — optional; use it to explain *why*, not *what*; wrap at 72 characters
123
+ - **type** - one of the prefixes from the table below
124
+ - **scope** - the module, command, or area being changed (e.g. `sync`, `mcps`, `github`, `landing`, `config`); omit when the change is truly cross-cutting
125
+ - **subject** - imperative mood, lowercase, no trailing period, 72 characters or fewer
126
+ - **body** - optional; use it to explain _why_, not _what_; wrap at 72 characters
93
127
 
94
128
  **Type prefixes**
95
129
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: uv-upsync
3
- Version: 2.4.1
3
+ Version: 2.4.2
4
4
  Summary: uv-upsync - is a tool for automated dependency updates and version bumping in pyproject.toml.
5
5
  Project-URL: Homepage, https://github.com/pivoshenko/uv-upsync
6
6
  Project-URL: Repository, https://github.com/pivoshenko/uv-upsync
@@ -22,19 +22,21 @@ Classifier: Programming Language :: Python :: 3.10
22
22
  Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
25
26
  Classifier: Topic :: Scientific/Engineering
26
27
  Classifier: Topic :: Software Development
27
28
  Classifier: Topic :: Software Development :: Libraries
28
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
29
30
  Requires-Python: >=3.10
30
- Requires-Dist: click~=8.4.1
31
+ Requires-Dist: click~=8.5.0
31
32
  Requires-Dist: httpx~=0.28.1
32
- Requires-Dist: packaging~=26.2
33
- Requires-Dist: tomlkit~=0.15.0
33
+ Requires-Dist: packaging~=26.3
34
+ Requires-Dist: tomlkit~=0.15.1
35
+ Requires-Dist: typing-extensions~=4.16.0
34
36
  Description-Content-Type: text/markdown
35
37
 
36
38
  <h1 align="left">
37
- <img src="assets/logo.svg" alt="" height="40" align="left" style="vertical-align: middle; margin-right: 12px;">
39
+ <img src="https://raw.githubusercontent.com/pivoshenko/uv-upsync/main/assets/logo.svg" alt="" height="40" align="left" style="vertical-align: middle; margin-right: 12px;">
38
40
  uv-upsync
39
41
  </h1>
40
42
 
@@ -60,26 +62,26 @@ Description-Content-Type: text/markdown
60
62
 
61
63
  `uv-upsync` is a [uv]-native tool for automated dependency updates and version bumping in `pyproject.toml`.
62
64
 
63
- `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 — all while preserving your formatting, comments, operators, extras and environment markers.
65
+ `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.
64
66
 
65
67
  [uv]: https://github.com/astral-sh/uv
66
68
 
67
69
  ### Features
68
70
 
69
- - **Built for the uv ecosystem** — familiar flags (`--project`, `--upgrade-package`, `--all-groups`, `--offline`, `--no-cache`, `--color`), uv-style output and a `uv lock` round-trip with automatic rollback on failure
70
- - **Index-aware** — resolves versions from the [PEP 691] index configured for your project via `[[tool.uv.index]]`, so private indexes work out of the box
71
- - **Correct by construction** — specifiers are parsed with [`packaging`], the canonical PEP 440/508 implementation, not regular expressions
72
- - **Conservative** — only raises lower bounds (`>=`, `>`, `~=`); pinned (`==`) requirements are never touched
73
- - **Range-aware** — 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 (`!=`)
74
- - **Controlled** — `--max-bump patch|minor|major` holds back larger jumps (auto-apply minors, review majors), and `--prerelease` opts into pre-release versions
75
- - **Format-preserving** — only the version token is rewritten; everything else, including comments and markers, is kept verbatim
76
- - **Fast** — version lookups are fetched concurrently and cached
77
- - **Selective** — target specific groups or packages, or exclude packages
78
- - **Configurable** — persist defaults in a `[tool.uv-upsync]` table, overridable per run
79
- - **Resilient** — by default an upgrade that does not resolve is held back individually instead of failing the whole run (`--strict` to opt out)
80
- - **Safe** — `--dry-run` to preview and `--check` for CI
81
- - **Scriptable** — `--format json` for tooling and `--format markdown` for pull request bodies
82
- - **Integrated** — ships a [pre-commit] hook and a GitHub Action
71
+ - 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
72
+ - Versions are resolved from the [PEP 691] index configured for your project via `[[tool.uv.index]]`, so private indexes work out of the box
73
+ - Specifiers are parsed with [`packaging`], the canonical PEP 440/508 implementation, not regular expressions
74
+ - Only lower bounds (`>=`, `>`, `~=`) are raised; pinned (`==`) requirements are never touched
75
+ - 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 (`!=`)
76
+ - `--max-bump patch|minor|major` holds back larger jumps (auto-apply minors, review majors), and `--prerelease` opts into pre-release versions
77
+ - Only the version token is rewritten; everything else, including comments and markers, is kept verbatim
78
+ - Version lookups are fetched concurrently and cached
79
+ - Target specific groups or packages, or exclude packages
80
+ - Defaults live in a `[tool.uv-upsync]` table and can be overridden per run
81
+ - By default an upgrade that does not resolve is held back individually instead of failing the whole run (`--strict` to opt out)
82
+ - `--dry-run` previews the changes, `--check` gates CI
83
+ - `--format json` for tooling, `--format markdown` for pull request bodies
84
+ - Ships a [pre-commit] hook and a GitHub Action
83
85
 
84
86
  ## Installation
85
87
 
@@ -148,7 +150,7 @@ Audited 12 dependencies, all up to date
148
150
 
149
151
  ### Resolution
150
152
 
151
- 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) — so a single incompatible dependency never costs you the rest:
153
+ 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:
152
154
 
153
155
  ```console
154
156
  $ uv-upsync
@@ -191,25 +193,25 @@ Settings are resolved with the precedence **command line > `[tool.uv-upsync]` >
191
193
 
192
194
  ## Examples
193
195
 
194
- ### Preview the upgrades
196
+ ### Preview the Upgrades
195
197
 
196
198
  ```shell
197
199
  uv-upsync --dry-run
198
200
  ```
199
201
 
200
- ### Upgrade a single package
202
+ ### Upgrade a Single Package
201
203
 
202
204
  ```shell
203
205
  uv-upsync --upgrade-package httpx
204
206
  ```
205
207
 
206
- ### Exclude packages
208
+ ### Exclude Packages
207
209
 
208
210
  ```shell
209
211
  uv-upsync --exclude click --exclude ruff
210
212
  ```
211
213
 
212
- ### Upgrade specific groups
214
+ ### Upgrade Specific Groups
213
215
 
214
216
  ```shell
215
217
  # Only the project dependencies
@@ -219,7 +221,7 @@ uv-upsync --group project
219
221
  uv-upsync --group test --group docs
220
222
  ```
221
223
 
222
- ### Fail CI when dependencies are stale
224
+ ### Fail CI When Dependencies Are Stale
223
225
 
224
226
  ```shell
225
227
  uv-upsync --check
@@ -241,8 +243,8 @@ repos:
241
243
 
242
244
  Two hooks are available:
243
245
 
244
- - **`uv-upsync`** — upgrade the bounds in `pyproject.toml` and re-lock (runs `uv lock`, so `uv` must be on your `PATH`)
245
- - **`uv-upsync-check`** — fail the commit if any dependency can be upgraded, without writing changes
246
+ - `uv-upsync` upgrades the bounds in `pyproject.toml` and re-locks (runs `uv lock`, so `uv` must be on your `PATH`)
247
+ - `uv-upsync-check` fails the commit if any dependency can be upgraded, without writing changes
246
248
 
247
249
  ## GitHub Action
248
250
 
@@ -272,7 +274,7 @@ jobs:
272
274
  branch: build/uv-upsync
273
275
  ```
274
276
 
275
- 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.
277
+ 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.
276
278
 
277
279
  | Input | Description | Default |
278
280
  | ------------------- | ------------------------------------------ | ------- |