Skip to content

Install CI environments from uv.lock - #8

Merged
mahdi-shafiei merged 1 commit into
mainfrom
ci/install-from-the-lock
Aug 27, 2026
Merged

Install CI environments from uv.lock#8
mahdi-shafiei merged 1 commit into
mainfrom
ci/install-from-the-lock

Conversation

@mahdi-shafiei

Copy link
Copy Markdown
Collaborator

Install CI environments from uv.lock

What

The composite action .github/actions/setup-diffbio stops running uv pip install -e and parses the extras into a uv sync --locked call, ported line for line from artifex's setup-artifex.

Why

uv pip install -e ".[dev]" resolves fresh and ignores uv.lock. The next
uv run re-syncs the project's default dependencies from uv.lock. The result is
an environment that is part freshly resolved and part locked, which no single resolution
ever validated, and which changes from one day to the next because nobody pinned it.

It is not theoretical. On 2026-08-27 it produced two unrelated-looking CI failures across
this ecosystem:

  • The editable install pulled twine 7.0.0, which requires packaging>=26.1; uv run
    then reverted packaging to the locked version and twine died on
    ImportError: cannot import name 'errors' from 'packaging'.
  • The same step pulled ruff 0.16.5 against a lock pinning 0.15.2, and the lint gate
    reported 33 errors on a tree that is clean under every 0.15 release.

Both are the same defect: the gate depends on when it runs, not on what the repository
declares.

The pattern this adopts

artifex already solved this in .github/actions/setup-artifex, and its own comment says
why:

Resolve from uv.lock rather than from the pyproject floors. Installing unpinned let
every tool drift to its newest release between runs, so a run could fail on a dependency
change no commit had made.

This brings that pattern here rather than inventing a new one.

Verification

Every referenced extra is declared in pyproject.toml, checked by parsing the manifest
rather than by eye. Every changed workflow parses as YAML. The replacement was run locally
on a clean checkout: uv sync --locked --extra dev installs exactly the versions
uv.lock pins, where uv pip install -e ".[dev]" installed newer ones.

Deliberately not changed

Installing a built wheel into an isolated virtual environment, installing a sibling
package from git, and installing type stubs that are absent from the lock. Those are not
this defect and are left alone.

Ports artifex's uv sync block, and pins the interpreter for the sync step: uv sync selects
its own Python and does not inherit the one uv venv just created, so it resolved against
3.14 and refused the lock because tensorflow 2.20.0 has no cp314 wheel.
@mahdi-shafiei
mahdi-shafiei force-pushed the ci/install-from-the-lock branch from c8c13e6 to 942851d Compare August 27, 2026 22:03
@mahdi-shafiei
mahdi-shafiei merged commit 57ae4b3 into main Aug 27, 2026
14 checks passed
@mahdi-shafiei
mahdi-shafiei deleted the ci/install-from-the-lock branch August 28, 2026 22:11
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