Lower bound rollout
Rolling out --resolution lowest-direct
A realistic bulk-edit scenario from the
design series: you've read that
CI tests should use --resolution lowest-direct alongside --frozen, and you want to
roll this out across every repo that has a pytest CI workflow.
Motivation
The motivating example here can be seen in the MCP Python SDK's workflow:
test:
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
dep-resolution:
- name: lowest-direct
install-flags: "--upgrade --resolution lowest-direct"
- name: locked
install-flags: "--frozen"
Note the extra leg in its test version matrix.
In addition to the typical approach on the locked leg,
the lowest-direct leg uses the lowest compatible versions for direct dependencies (and latest for transitives),
catching invalid lockfiles which pin lower bounds that will install but don't actually work
(breaking the tests at runtime).
For further details see uv's resolution docs.
Step 1: find the target repos
Which repos have pytest in a CI workflow and use uv?
nave search workflow:pytest workflow:uv
Narrow further to those whose pyproject.toml has a requires-python bound worth
testing at the lower end:
nave search \
workflow:pytest workflow:uv \
--match 'pyproject:project.requires-python^=>='
Step 2: see what currently exists
Does any of your fleet already have a dep-resolution matrix? If so, you want to
align with it rather than create a second pattern:
nave search workflow:dep-resolution --explain
If zero results, you're greenfielding. If there are some, go read those first.
Step 3: build a template of the current workflows
To see the shared shape of your pytest workflows before you mutate them:
nave build --where workflow:uv --match 'workflow:run*=pytest'
This gives you the anti-unified template, with holes showing exactly which parts vary today. The codemod needs to slot into those holes cleanly.
Step 4: create a pen
nave pen create \
workflow:uv \
--match workflow:run*=pytest \
--name nave/lowest-direct
This clones the matching repos into ~/.local/share/nave/pens/lowest-direct/ and
creates a branch nave/lowest-direct in each. The cache is untouched.
Inspect:
nave pen show nave/lowest-direct
nave pen status nave/lowest-direct
Step 5: apply the edit
🚧 Declarative codemods are still under design. For now, use pen exec to run an
arbitrary command in each repo:
nave pen exec nave/lowest-direct --commit --message \
"ci: add --resolution lowest-direct to test matrix" -- \
python path/to/edit-workflow.py
--commit commits the result in each repo; add --push-changes to push branches.
Validate before pushing:
nave schemas validate nave/lowest-direct --check-actions
--check-actions is important here — you're editing workflow files, and a mistyped
action input will only show up at CI runtime otherwise.
Step 6: open PRs
🚧 nave pen open is planned but not yet shipped.
In the meantime, use gh pr create inside each repo, or script the loop manually.