Repository navigation
Open a weekly PR that refreshes uv.lock - #2569
Merged
Merged
Conversation
CI's test suite installs uv.lock exactly as committed, so a new upstream release reaches it only when the lock changes. This workflow runs `uv lock --upgrade` on main every Monday and opens a PR with the result. It runs as two jobs because resolving can run a dependency's build backend. `lock` resolves with no secrets, a read-only GITHUB_TOKEN and no uv cache, and passes the new uv.lock on as an artifact. `publish` starts on a fresh runner, mints the org GitHub App token (scoped to contents and pull requests) so the PR gets CI, runs no dependency code, and makes every decision itself. It keeps at most one update PR open. It refreshes that PR while every commit on it, other than merges of main, is the workflow's own and it changes only the lock and the fragment; it leaves the PR alone once anyone else commits, and closes it when main's lock is already current. Fixes #2568 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The close step compared the branch head and then deleted it over REST, so a push landing between the two was deleted. A git push delete with --force-with-lease on the inspected head does both in one step. Also say that GITHUB_TOKEN PR runs wait for approval rather than not running. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
October 22, 2026 14:08
Collaborator
Author
|
Merging at
After merge I'll dispatch 🤖 Generated with Claude Code |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Fixes #2568
What and why
CI's test suite installs
uv.lockexactly as committed (uv sync --frozenin.github/actions/test-environment), so a new dependency release reaches CI only when someone updates the lock. The lock was last refreshed on 10/11 (a6050ea). Today,uv lock --upgradeon main updates 26 packages, including policyengine-core 3.33.2 → 3.33.12.This adds
.github/workflows/weekly-uv-lock.yaml, modelled on policyengine-us'sweekly-uv-lock.yaml(which has been disabled there since March). It runsuv lock --upgradeon main every Monday at 06:00 UTC, or onworkflow_dispatch, and opens a PR with the result. The PR body lists everyUpdated/Added/Removedline uv prints. The PR carries a.changedfragment, so merging it makes a patch release, as policyengine-us's does. It also adds a "Dependencies" section to.github/CONTRIBUTING.md.How it works
Two jobs, because resolving can run a dependency's build backend:
lock: checks outgithub.shawithpersist-credentials: false, then runsuv lock --upgradewith no secrets, a read-onlyGITHUB_TOKENand no uv cache. It uploads the newuv.lockand uv's summary lines as an artifact.publish: starts on a fresh runner and mints the org GitHub App token first (APP_ID/APP_PRIVATE_KEY, asversioning.yamluses), scoped to contents and pull requests. GitHub starts no workflows for a push made withGITHUB_TOKENand holds the runs for a PR opened with it until someone approves them, so the App token is what lets the PR's CI start on its own. This job runs no dependency code. It treats the artifact as data: it copiesuv.lock, and keeps only well-formed summary lines for the body. It makes every decision itself.Both jobs run only in
PolicyEngine/policyengine-ukand only onmain.At most one update PR (branch
bot/weekly-uv-lock-update). This departs from policyengine-us, which force-pushes the branch every week and skips creating a PR if one exists. Here:uv.lockand the fragment. So a red PR turns green by itself once upstream fixes its release, and "Update branch" doesn't stop the refresh.git pushwith--force-with-leaseon the head that was checked, so a push that lands in between keeps it.--force-with-leaseon the head it inspected. Fork PRs that reuse the branch name are ignored.PR writes are REST calls (
gh api).gh pr editalso reads project fields, which a token scoped to contents and pull requests can't read. GitHub's "Permissions required for GitHub Apps" page lists the endpoints used under Pull requests (write) and Contents (write).Behaviour that must hold (tested below)
Test plan
actionlint1.7.12 (with shellcheck): clean.A local harness runs both jobs'
run:steps in order, against a bare git remote and a RESTghstub, with the artifact handed between fresh clones. It passes 69/69 checks over 19 scenarios:Four deliberate workflow mutations each turn at least one check red. The harness needs network access (it runs
uv lockagainst PyPI) and isn't committed.Review: an Opus reviewer requested changes in round 1 and again in round 2. Round 2's must-fix was that the App private key was used in the same job that had already run dependency code, which is why there are now two jobs. Round 3 approved; its should-fix (no uv cache in
lock) and nits are applied. Round 4 (GPT-6.1 Sol, which ran the harness and reproduced the bug) requested changes: the close step checked the branch head and deleted the branch in two separate calls, so a push landing in between was deleted. That is fixed in the latest commit, with a harness case that injects the push at the moment of the delete.Not testable before merge: the real App token, the push to github.com and the REST permissions. After merge, one
workflow_dispatchrun will open the first update PR. I expect about 26 updates, including policyengine-core 3.33.12, and that PR's CI is the full suite on them.Interactions
axiom: n/a: CI workflow
🤖 Generated with Claude Code