[pull] master from useblocks:master - #225
Merged
Merged
Conversation
…pgrade` job (#1951) ### Why Dependabot's uv updater cannot update this lock, for two measured reasons. **It pins one candidate version on every requirement line before it relocks.** This workspace legitimately locks some packages at two versions across its `[tool.uv] conflicts` splits — `docutils` 0.20.1 in the `typing` group beside the newest elsewhere, `myst-parser` 4.x in the `sphinx-7` cell beside 5.x elsewhere. uv refuses the universal pin, and the updater treats the refusal as fatal to the whole job: every group refresh died with "Dependabot can't resolve your Python dependency files". **Its default `versioning-strategy` rewrites manifest specifiers it has no reason to touch.** #1940 raised `matplotlib>=3.3.0` to `>=3.11.2` on a user-facing extra whose floor already allowed the release, and widened `click < 8.2` past the comment explaining the cap. Three merged pull requests (#1942, #1944, #1946) and a fourth (#1948, six more ignore rules, closed unmerged in favour of this) went into working around that. Meanwhile `uv lock --upgrade` does the job in one command: on master today it resolves cleanly across every split and moves 13 packages, including `docutils v0.20.1, v0.21.2 -> v0.20.1, v0.22.4` — the exact thing dependabot cannot express — and it never touches a manifest. ### What this does Adds `.github/workflows/uv-update.yaml` — `UV update`, monthly on `0 7 1 * *` (an hour after `Prek update`, so both land on the same morning and neither depends on the other) plus `workflow_dispatch` — modelled step for step on `prek-update.yaml`: the bot-app token, `actions/checkout@v7`, `astral-sh/setup-uv@v10.1.0` on the root `.python-version`, and one pull request from the fixed branch `uv-update` titled `⬆️ Update the uv lock (monthly)`. The steps: `uv lock --upgrade`, capturing uv's lock-diff lines (stderr, so `2>&1` into `$RUNNER_TEMP`); an assertion that **no manifest changed**, which fails the job loudly if one did; `uv sync --frozen` and `uv run --frozen prek run --all-files`, recording whether the hooks came out clean; the held-back list; and the composed body. The body reports **all three of uv's lock-diff verbs**, not just `Updated`. `Added` and `Removed` get bullets of their own — a package entering the dependency graph is the most review-worthy line a lock update can carry, and a body that drops it silently is worse than one that says nothing — and any other `<Verb> <name> v<version>` line uv may invent is printed as `unrecognised uv line:` rather than discarded, so the body announces a new verb instead of quietly shrinking. Measured on a real 18-line upgrade log: 18 lines in, 18 bullets out. Then `.github/dependabot.yml` loses its uv section — ignore rules, `ty` group and all — and gains ten lines saying why. `AGENTS.md`'s dependabot-review paragraph is replaced by one paragraph on the job, the same length as the one it replaces, with the history left in `dependabot.yml` where it belongs. `tools/tests/test_dependabot_config.py` fences the configuration so the uv entry cannot come back, and fences the replacement *as a command* in the `update` step — `uv lock --upgrade` also appears in prose in the same file, so a substring check would stay green while the job was gutted to a no-op relock. ### What stays with dependabot The **`github-actions`** ecosystem, untouched: that half has never had a problem here. And **security alerts and security-update pull requests**, which are a repository feature reading `uv.lock` independently of `dependabot.yml`'s version-update config — removing the uv section does not stop them. ### Two decisions, with their measurements **No cooldown**, unlike `prek update --cooldown-days 7`. `uv lock --upgrade --exclude-newer` is a *global index cutoff*, not a per-package delay, and it failed both halves of the test: at seven days it made the lock unresolvable (`Because only ty<=0.0.79 is available and sphinx-needs-workspace:typing depends on ty>=0.0.80,<0.1.dev0 …` — the `typing` group's own floor is younger than the window, and so would be any floor a release bump had just raised); and with a cutoff recent enough to resolve, it wrote `[options] exclude-newer` into `uv.lock`, after which a plain `uv lock --check` reported "The lockfile at `uv.lock` needs to be updated" and the `uv-lock` prek hook rewrote the lock and failed — on the job's own pull request. The workflow carries a comment saying so. Dependabot had no cooldown here either, so nothing is lost. **The held-back list comes from `uv tree --outdated --frozen --depth 1`**, run after the upgrade. `uv pip list --outdated` was tried first and cannot do it: it reads one installed environment, so `pydata-sphinx-theme` (behind the `theme-pds` extra) is invisible to it — as is every conflicting group. `uv tree` reads the lock, `--depth 1` is each member's own requirements, and running it after the upgrade leaves only what is held back rather than what was merely pending. Scored against the known positives: it flags `jsonschema-rs` (0.53.0, capped `<0.54.0`) and `pydata-sphinx-theme` (0.17.1, capped `<0.20.0`), and correctly does *not* flag `comment-parser` (already newest wherever installable) or `myst-parser` (already 5.1.0 by default; 4.0.1 survives only in the `sphinx-7` and `typing` cells, held by `sphinx~=7.4`). A grep over the manifests puts the specifier beside the versions — and the body says plainly what that column is: every specifier this workspace writes for that name, while what actually blocks the newer release may be one of those, a cap elsewhere in the graph, or a `[tool.uv] conflicts` split, with `uv lock --upgrade-package <name>` as the way to find out. The list is the **default resolution's** view; a package held back only in a matrix split is not in it, and the body says that too. ### Proving it without merging it A `workflow_dispatch` needs the file on the default branch, so the five `run:` blocks were extracted from the YAML *verbatim* (parsed with pyyaml, the way `tools/tests/test_ci_plantuml_steps.py` reads workflow YAML) and run locally under `bash -e` with the runner's environment variables. Three runs: * **on today's lock** — `changed=true`, the 13 `Updated` lines captured, manifests untouched, all eight hooks Passed against the upgraded lock (ty included), the held-back list carrying both known positives, and the body composed in full; * **with the lock already current** — `changed=false`, "no lock updates available; nothing to open a pull request for", and every later step skipped by its `if:`; * **with a floor edited by hand** (dependabot's own `matplotlib>=3.3.0` → `>=3.11.2`) — the assert step fails with `::error::uv lock --upgrade edited a manifest; this job only ever moves uv.lock` and `exit 1`. Plus, for the body's new verbs: a constructed log covering `Updated`/`Added`/`Removed`/an unknown verb, and a real 18-line upgrade log rebuilt from a two-week-old `uv.lock`. And for the fence: weakening the update step's `uv lock --upgrade` to `uv lock` turns the test red. `uv.lock` is deliberately **not** part of this pull request; the tree was returned to clean before anything was committed. ### After the merge Dispatch `UV update` once by hand as the rehearsal; it opens the first real pull request. Then delete the `ci/dependabot-ignore-unlockable` branch, kept on origin as the fallback until this landed. ### Review Built by one agent against a binding brief, reviewed by a second that re-ran every proof from its own extraction of the YAML and added 15 mutations of its own; its three findings (the dropped `Added`/`Removed` lines, the fence matching prose, the misleading "no upper bound" sentence) are the fix round folded in above, and it re-verified the two mechanisms afterwards (the invented verbs `Downgraded`/`Yanked` come out loud, five uv summary shapes stay ignored; the fence is red for a weakened command and green for weakened prose). Two constructed, not observed, residuals remain and are accepted: a version *pair* on an `Added`/`Removed` line would malform that bullet's PyPI link (the package is still named), and a hyphenated verb would slip the catch-all. Gates re-run by hand on the final head: `uv run poe lint` 8/8, `pytest tools/tests` 316 passed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )