Repository navigation
Install CI dependencies from uv.lock - #136
Merged
Merged
Conversation
The base venv was built with `uv pip install`, which ignores the lockfile and resolves the newest versions at the time the cache is created. Use `uv sync --locked` instead, so CI runs the locked versions (and fails if the lockfile is out of date), and include `uv.lock` in the cache key. Venvs created by uv don't include pip, so use `uv pip` in the remaining jobs.
`pytest-cov` and `pytest-github-actions-annotate-failures` were installed unpinned in every test job. Add them to the `dev` group so they come from `uv.lock` like everything else (the annotation plugin only activates on GitHub Actions).
Like the Linux base venv, install the locked dependencies instead of resolving them with pip at cache creation time.
prek itself now comes from `uv.lock`, so a prek version change needs a fresh hook environment cache.
`uv lock --upgrade` with uv 0.13.0. Notably mypy 2.4.0, pylint 4.1.3, pytest 9.1.1, pytest-asyncio 1.4.0, prek 0.5.5, aioesphomeapi 46.10.0 and uv 0.13.0.
TheJulianJES
marked this pull request as draft
October 13, 2026 00:40
TheJulianJES
commented
Oct 13, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #136 +/- ##
=======================================
Coverage 94.36% 94.36%
=======================================
Files 25 25
Lines 4362 4362
=======================================
Hits 4116 4116
Misses 246 246 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
It's uv's default project environment, so `UV_PROJECT_ENVIRONMENT` isn't needed. It also lets the prek hooks (`uv run --frozen --group dev`) reuse the cached venv instead of creating a second environment in `.venv`.
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.
CI currently builds the cached venvs with:
uv pip install -e . --group devfor Linux, and withpip install -e . --group devfor macOS and Windows.Those both ignore the
uv.lockfile that's tracked in the repo, so library versions will be whatever the newest version was when the venv cache was last rebuilt. This is also what caused ruff 0.17 to randomly appear in #128 and #129. I don't think this is intentional?This PR changes that to use the
uv.lockto create the CI venv from (withuv sync), similar to the recommendeduv syncapproach described in the README for the local environment/development.uv.lockis also added as a cache key.To not revert CI to old library versions temporarily, I ran
uv lock --upgradeand committed that here. If wanted, this can also be dropped from this PR and become a separate dependency upgrade PR, e.g. with: dev...TheJulianJES:tjj/uv-lock-upgrade. Might be cleaner?pytest-covandpytest-github-actions-annotate-failureswere added to thedevgroup (installed byuv syncby default, so also in CI). For zigpy, we have a separatecigroup to not installpytest-github-actions-annotate-failures(andpytest-xdist) in local environments but the package just doesn't do anything then when not in a GitHub runner.Lastly, the venv folder in CI is now the standard for uv:
.venv, notvenv. As prek config runs withuv run, this will no longer cause a second venv to be created just for prek in CI.Notes / questions
uv.lockupgrade: the second to last commit is onlyuv lock --upgradeand can be dropped from this PR, to upgrade the lockfile in a separate PR instead. Without it, CI would move back to the (older) locked versions for some packages, e.g. pytest 9.1.1 → 9.0.3 or prek 0.5.5 → 0.3.13. The prek hooks and the ESPHome tests were also checked with those older versions.uv.lockfromrevision = 3torevision = 5. That's most of the upgrade diff. Revision changes are backwards compatible, so older uv versions can still read it ("Changes to the revision will not cause older versions of uv to error", per the uv docs). uv 0.11.20 reads it fine.devvs.cigroup:pytest-github-actions-annotate-failuresis only needed in CI. It's inert outside GitHub Actions (it only activates whenGITHUB_ACTIONS=true), so having it indevdoesn't hurt. The zigpy repos (zigpy, zha, zha-device-handlers, zigpy-ota) put it in a separatecigroup instead, with CI runninguv sync --group ci. Should we do the same here, or keep it indevfor simplicity?uv.lock(and the pinned GitHub Actions) up to date, a Dependabot config with grouped updates could be added, similar to the zha repo: theuvecosystem with all Python dependencies in a single group and a short cooldown, plusgithub-actions. That way, there are no spammy PRs for every single dependency bump, but one bigger PR that can be merged every few weeks.Detailed AI-generated PR description
AI-generated PR description (CLICK TO EXPAND)
Why
Since #132, the prek hooks and
uv syncfor development use the versions pinned inuv.lock, but the CI test venvs still resolve fresh. Because those venvs are cached by a hash ofpyproject.toml,setup.pyand the Cargo files, the versions they contain depend on when the cache was last rebuilt, so CI is neither reproducible nor actually up to date. With this PR, CI, the hooks and local development all use the same locked versions, and updates happen through explicit lock bumps.For comparison: zigpy, zha, zha-device-handlers and zigpy-ota use
uv sync --group civiazigpy/workflows, and HA Core / aioesphomeapi / python-otbr-api install exact==pins from requirements files.Changes in detail
prepare-base(Linux):uv sync --lockedwithUV_PYTHONset tosetup-python'spython-path, so the venv always uses the interpreter its cache key refers to. The explicitpip/setuptools/prekinstall is gone;prek,uvandsetuptools(viasetuptools-rust) come from thedevgroup.uv sync --lockedstep (plussetup-uv) instead ofpython -m venv+pip install. The editable build still puts the Rust extension in-tree, where the extension cache picks it up, and theRebuild Rust extensionstep works in the uv-created venv.uv.lockis added to all base venv keys and to the prek key (prek itself now comes from the lock, so a prek version change needs a fresh hook cache).devgroup: addspytest-cov(used by all test jobs; harmless locally since--covisn't in the default options) andpytest-github-actions-annotate-failures(see thecigroup question above).venv→.venv:.venvis uv's default project environment, whichuv synccreates anduv runuses (and whatzigpy/workflowsand theuv syncdev setup use). Previously, the prek job activated the cachedvenv, but the hooks'uv run --frozen --group devignored it (VIRTUAL_ENV=venv does not match the project environment path .venv and will be ignored) and built a second environment in.venv. Now they reuse the cached one.uv pip installinstead ofpip install, since uv-created venvs have no pip.coveragenow comes frompytest-cov's locked dependency.backports-zstd). Notably mypy 2.1.0 → 2.4.0, pylint 4.0.5 → 4.1.3, pytest 9.0.3 → 9.1.1, pytest-asyncio 1.3.0 → 1.4.0, prek 0.3.13 → 0.5.5, aioesphomeapi 46.6.0 → 46.10.0, uv 0.11.14 → 0.13.0. All prek hooks (incl. the new mypy and pylint) pass without code changes.Testing
uv sync --lockedvenv passes the test suite (Python 3.14, with--cov) and all prek hooks with the upgraded lockfile. Without the upgrade commit, the prek hooks and the ESPHome tests were checked as well.