Skip to content

ci: install the declared floors wheel-only without letting the resolver climb - #139

Merged
lesnik512 merged 3 commits into
mainfrom
ci/floors-readback
Sep 27, 2026
Merged

lesnik512 merged 3 commits into
mainfrom
ci/floors-readback

Conversation

@lesnik512

@lesnik512 lesnik512 commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

The floors job now installs each declared floor exactly, so a floor with no wheel fails the job instead of passing on a higher version. It uses two uv commands and no script.

The gap

--only-binary PyYAML doesn't make a floor with no wheel fail. It makes that version ineligible, and --resolution lowest-direct then climbs to the lowest version that has a wheel, then passes. This is how PyYAML>=6 resolved 6.0.1 and 6.0.2 on 3.12 and 3.13 while the job stayed green (#135). uv has no option that turns the climb into an error. Its maintainers treat skipping versions without wheels as intended (astral-sh/uv#16186).

The fix

- run: uv pip compile pyproject.toml --all-extras --no-deps --resolution lowest-direct -o floors.txt
- run: uv pip install -r pyproject.toml --all-extras --constraints floors.txt --no-build
  1. Pin the floors. The compile resolves each direct dependency's floor for this interpreter with builds allowed, so a version with no wheel isn't skipped. --no-deps limits the output to direct dependencies.
  2. Install them wheel-only. A floor with no wheel then fails with uv's own explanation.

-r pyproject.toml installs the dependencies but not the project. So --no-build needs no carve-out, and the smoke import reads compose2pod from the checkout.

This follows what larger projects do: sunpy, jwst, napari, scikit-image and scikit-learn all test exact minimum pins rather than a lowest resolution. It needs no generator script, so the rollout to other repos is a change to _checks.yml only, which also works for repos that currently use uv sync --no-install-project.

Verified

Known limits

  • A floor excluded by requires-python. The compile would still move up past a declared floor whose own requires-python excludes this interpreter.
  • A dependency with no floor. The compile warns that it is unpinned and pins an ancient version, which then fails the wheel-only install. The failure is loud, but the message doesn't name the cause. Lint for published dependencies declared with no lower bound .github#108 tracks a proper lint for it.

@lesnik512 lesnik512 changed the title ci: fail the floors job when a floor resolves above its declaration ci: pin the declared dependency floors exactly in the floors job Sep 25, 2026
@lesnik512 lesnik512 changed the title ci: pin the declared dependency floors exactly in the floors job ci: install the declared floors wheel-only without letting the resolver climb Sep 27, 2026
@lesnik512
lesnik512 merged commit 9a045fd into main Sep 27, 2026
15 checks passed
@lesnik512
lesnik512 deleted the ci/floors-readback branch September 27, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant