Skip to content

ci: install uv.lock as committed instead of re-resolving - #681

Closed
fgmacedo wants to merge 1 commit into
mainfrom
fgmacedo/ci-677-uv-locked
Closed

fgmacedo wants to merge 1 commit into
mainfrom
fgmacedo/ci-677-uv-locked

Conversation

@fgmacedo

@fgmacedo fgmacedo commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Why

CI ran uv sync --all-extras --dev without --locked (python-package.yml:37, release.yml:30), so a stale uv.lock never failed and the release build could test versions other than the pinned ones. Fixes #677.

What changes

  • Both workflows sync with --locked and set UV_LOCKED: 1 at job level, so every uv run step also fails instead of re-locking when uv.lock disagrees with pyproject.toml.
  • The 7-day exclude-newer cooldown moves into [tool.uv] in pyproject.toml. The committed lock records exclude-newer-span = "P7D", which until now came only from a contributor's global uv config; without the project setting, --locked fails in CI on the current lock (see Evidence), so this is required, not optional.
  • docs/contributing.md states the minimum uv (0.9.17; older releases fail to parse exclude-newer = "7 days", drop [tool.uv] and rewrite the lock) and the exclude-newer-package escape hatch for releases younger than 7 days.

Evidence

CI-like environment: XDG_CONFIG_HOME pointed at an empty dir, so the global uv config is not read (--no-config is not a faithful stand-in: it also ignores [tool.uv]). uv 0.12.21.

Committed lock, main's pyproject.toml (no [tool.uv]):

$ XDG_CONFIG_HOME=$EMPTY uv lock --check
Resolving despite existing lockfile due to removal of global exclude newer
error: The lockfile at `uv.lock` needs to be updated, but `--check` was provided.

Committed lock, this branch:

$ XDG_CONFIG_HOME=$EMPTY uv lock --check
Resolved 104 packages in 3ms
$ XDG_CONFIG_HOME=$EMPTY uv sync --locked --all-extras --dev   # exit 0
$ XDG_CONFIG_HOME=$EMPTY UV_LOCKED=1 timeout 120 uv run pytest -n 4 -q
2631 passed, 25 skipped, 44 xfailed, 9 warnings in 25.22s

Deliberately stale lock (scratch copy, "tomli-w >=1.0" added to the dev group without relocking):

$ uv lock --check
error: The lockfile at `uv.lock` needs to be updated, but `--check` was provided.      # exit 1
$ uv sync --locked --all-extras --dev
error: The lockfile at `uv.lock` needs to be updated, but `--locked` was provided.     # exit 1
$ UV_LOCKED=1 uv run python -c 'print(1)'
error: The lockfile at `uv.lock` needs to be updated, but `UV_LOCKED=1` was provided.  # exit 1

Adversarial review (separate agent): uvx uv@0.13.0 lock --check passes (latest, what setup-uv@v10.2.0 installs by default); a user config with exclude-newer = "3 days" still passes (project setting wins); UV_LOCKED=1 uv build leaves uv.lock byte-identical; actionlint clean on both workflows.

Not verified

  • SonarCloud flags the edited uv sync lines with S8541 ("omitting --no-build can lead to the execution of setup scripts"). --no-build was tried and breaks the 3.15 job: pyyaml==6.0.3 has no 3.15 wheel (can't be installed because it is marked as --no-build but has no binary distribution). The finding needs a maintainer decision on SonarCloud; the risk is unchanged from main, which ran the same uv sync without --no-build.
  • release.yml was not run; only the shared uv sync --locked / UV_LOCKED path was exercised through python-package.yml on this PR.
  • uv build still resolves the build backend (hatchling, unpinned in [build-system]) outside the lock; out of scope here.
  • .readthedocs.yaml keeps --frozen (installs the lock without validating it), as accepted in CI re-resolves uv.lock instead of installing it as committed #677.
  • The cooldown is a resolution policy, not a CI gate: a lock holding packages younger than 7 days still passes --locked.

@fgmacedo fgmacedo added this to the 3.2.2 milestone Oct 13, 2026
Comment thread .github/workflows/python-package.yml Fixed
Comment thread .github/workflows/release.yml Fixed
@fgmacedo
fgmacedo force-pushed the fgmacedo/ci-677-uv-locked branch 2 times, most recently from f6e8c10 to 56ff13f Compare October 13, 2026 20:23
@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (73bf57c) to head (4072311).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #681   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           53        53           
  Lines         5787      5787           
  Branches       918       918           
=========================================
  Hits          5787      5787           
Flag Coverage Δ
unittests 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

CI ran `uv sync --all-extras --dev` without `--locked`, so a stale or
inconsistent uv.lock never failed and the release build could test
versions other than the pinned ones. Both workflows now sync with
`--locked` and set `UV_LOCKED=1` so later `uv run` steps do not re-lock.

The committed lock records a 7-day `exclude-newer` span that only
existed in a contributor's global uv config, so `--locked` would fail
in CI. Declaring the cooldown in `[tool.uv]` makes the lock reproducible
from the project alone.

Fixes #677

Signed-off-by: Fernando Macedo <fgmacedo@gmail.com>
@fgmacedo
fgmacedo force-pushed the fgmacedo/ci-677-uv-locked branch from 56ff13f to 4072311 Compare October 13, 2026 20:25
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

cache-suffix: "python${{ matrix.python-version }}"
- name: Install the project
run: uv sync --all-extras --dev
run: uv sync --locked --all-extras --dev

- name: Install the project
run: uv sync --all-extras --dev
run: uv sync --locked --all-extras --dev
@fgmacedo

Copy link
Copy Markdown
Owner Author

Closing: SonarCloud requires --no-build on the edited uv sync lines, and that breaks the 3.15 jobs until PyYAML ships 3.15 wheels. Tracked in #684.

@fgmacedo fgmacedo closed this Oct 13, 2026
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.

CI re-resolves uv.lock instead of installing it as committed

2 participants