Repository navigation
ci: keep a uv cache per Python version and skip unused source builds - #251
Conversation
setup-uv's default cache key carries the runner's system Python, not UV_PYTHON, so the whole quality matrix shared one entry. The first job to finish saved it, and the wheels 3.14t, 3.15 and 3.15t build from source were never kept: `uv sync` took 2.5-5 minutes on those jobs in every run. A cache-suffix per matrix version fixes that for quality and platform-smoke. The quality job also stops installing lupa and zensical, the slowest source builds there, which it never imports (Redis tests use the service container, the Docs job builds the docs). UV_NO_SYNC keeps the later `uv run` steps from syncing them back.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📜 Recent review details
WalkthroughThe quality job sets ChangesCI setup
Priority: ⬇️ Low Estimated code review effort: 1 (Trivial) | ~5 minutes Change: Other Suggested labels: Merge Risk: ⚪ Minimal · up to
|
Merging this PR will not alter performance
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
The tests are not what makes CI slow. pytest-xdist already runs them with
-n auto, in 17–24 s per job. The time goes touv syncon the newestinterpreters:
uv sync(run 38958788451). Several dev dependencies ship no wheels for 3.14t, 3.15 or
3.15t, so uv builds them from source: lupa, zensical, pydantic-core, msgspec,
cryptography, aiohttp, pyyaml, nh3. On 3.15t lupa takes 5:03 and zensical 5:09.
Those builds were never cached. setup-uv's default key carries the
runner's system Python and the lock hash
(
setup-uv-2-…-ubuntu-24.04-3.12.3-<hash>), notUV_PYTHON. All sevenqualityjobs therefore shared one entry. Whichever finished first saved it,and the 3.15 job logs
Cache hit occurred on key …, not saving cache, so itsbuilt wheels were discarded every run.
cache-suffix: ${{ matrix.python-version }}onsetup-uvinqualityand
platform-smoke. Each interpreter gets its own entry, so oncemainhas saved one, runs against the same
uv.lockrestore the built wheelsinstead of rebuilding them.
qualityskipslupaandzensical(--no-install-package), the twoslowest builds there. Neither is used in that job: Redis tests run against
the service container (
INTERLOCK_TEST_REDIS_URL), sofakeredisand itsLua engine are never imported, and the Docs job builds the docs. This also
shortens the runs that miss the cache, which happen once per
uv.lockchange.
UV_NO_SYNC: '1'at job level, so the lateruv runsteps do not syncthe skipped packages back. A plain
uv runwould reinstall them.platform-smokehandles the same problem with--no-sync.No package or test changes, and no changelog entry: like #212, this is
CI-internal.
Cache budget: the repository already sits at the 10 GB Actions cache cap
(146 entries), with LRU eviction.
main's per-version entries are reused onevery run and are the last to be evicted. If eviction starts hitting them,
the next lever is
prune-cache: true, which keeps only source-built wheels.Checklist
uv run ruff format --checkanduv run ruff checkpassuv run mypy,uv run pyrightanduv run pyrefly checkpassdocs/) for user-facing changes: none user-facingCHANGELOG.md[Unreleased]updated: not needed, CI-internalVerified locally by replaying the
qualityjob on 3.15t and 3.11 against areal Redis 7:
UV_NO_SYNC=1with the new install flags, then zizmor, ruff,mypy, pyright, pyrefly and
pytest --cov. Result: 853 passed and 100%coverage on both, with lupa and zensical absent after every step. Without
UV_NO_SYNC,uv runreinstalls lupa. zizmor (online) and prek pass.The first run of this branch misses by design, since the keys are new. The
effect shows on the next run against the same lock.
Related issues
None.
Changed
uvdependencies separately for each Python version in thequalityandplatform-smokejobs.lupaandzensicalinquality, and prevent lateruv runcommands from syncing them back in.lupainplatform-smokeand run its tests with--no-sync.Added
Fixed
uvcache entry keyed without the selected Python version.