chore: rolling uv exclude-newer supply-chain quarantine#2616
Open
tonyandrewmeyer wants to merge 6 commits into
Open
chore: rolling uv exclude-newer supply-chain quarantine#2616tonyandrewmeyer wants to merge 6 commits into
tonyandrewmeyer wants to merge 6 commits into
Conversation
Add --locked to the project-scoped `uv run` invocations at the top level of .github/workflows/ (zizmor.yaml, integration.yaml). Without --locked, if a PR widens a version range in pyproject.toml without regenerating uv.lock, uv silently re-resolves in CI and the transitive-dependency delta never appears in the diff. --locked makes uv fail instead of re-resolving when uv.lock is out of sync with pyproject.toml, forcing a fresh uv.lock commit and making the resolution change reviewable. Not using --frozen: --frozen skips the freshness check entirely (it just uses the lock file as-is, even if stale relative to pyproject.toml), so it doesn't provide this guarantee. Scope: only bare project-scoped `uv run`/`uv sync` calls against the root uv.lock. The `uv run --script --no-project` and the working-directory=examples/* `uv run` invocations in example-charm-tests.yaml were left untouched -- the latter resolves against each example charm's own uv.lock (each examples/* directory has its own pyproject.toml/uv.lock), a separate resolution story from the root project. `uv tool install`, `uvx`, `uv build`, `uv export`, `uv add`/`uv remove` invocations are out of scope for --locked (they are not `uv run`/`uv sync`) and were left untouched, as were all pip/tox/poetry invocations.
Add [tool.uv].exclude-newer = "7 days" to pyproject.toml. uv will ignore any package release newer than 7 days old when resolving dependencies, across every uv resolution path: manual `uv add`, `uv lock` regenerations, uvx bootstraps, and CI re-resolves. This complements (does not replace) Dependabot's cooldown, which only protects Dependabot-authored PRs. exclude-newer is a rolling window -- "7 days" is evaluated relative to whenever the resolution runs, not a fixed date -- so it continuously quarantines newly published releases from every other route a bad or compromised release could enter the dependency tree. Reference: uv docs (exclude-newer accepts durations like "7 days"); Canonical Security "How-To: Secure a repo" -- Minimum release age.
Add [tool.uv].no-build = true to pyproject.toml. With this set, uv refuses to build or install any package from a source distribution (sdist) and will only install from wheels. Why: installing an sdist (via `pip install <sdist>` or `uv sync` falling back to one) runs that package's setup.py / PEP 517 build hooks at install time -- arbitrary code execution controlled by whatever is in the sdist. Wheels are pre-built and do not run install scripts, so restricting resolution to wheels closes this vector fleet-wide. Fleet verification (2026-07-02): 0 of 571 dependencies across the fleet's uv.lock files are sdist-only (confirmed 0/73 in this repo's own root uv.lock), so this is a zero-cost change today -- no package currently in use requires falling back to an sdist build. Escape hatch: if a future dependency is genuinely sdist-only and must be installed anyway, exempt it individually with [tool.uv].no-build-package = ["specific-pkg"] rather than reverting this setting. Reference: Canonical Security "How-To: Secure a repo" -- Install scripts section.
Replace the `[tool.uv]` block with the canonical fleet comment (rolling quarantine rationale), drop `no-build = true`, and drop `--locked` from CI workflow `uv run` / `uv sync` invocations. See canonical/pytest-jubilant#98 for the exemplar PR and canonical/charm-tech#22 (references/decisions.md) for the recorded deferral of `no-build` and `--locked`: uv has no allow-list to exempt the workspace project from `no-build`, and rolling `exclude-newer` is fundamentally incompatible with `--locked` (uv records the resolved-at-lock-time timestamp in `uv.lock`, so every day CI recomputes a different value and `--locked` errors). Rolling `exclude-newer` is the surviving pattern.
…exclude-newer The rolling '[tool.uv].exclude-newer = "7 days"' resolves to now() - 7 days at each invocation and uv records the absolute timestamp in uv.lock. tox-uv's uv-venv-lock-runner passes --locked to 'uv sync', so every run the newly-computed floor differs from the stored one, uv re-resolves, sees a config change, and errors. Rolling exclude-newer and --locked are fundamentally incompatible; exclude-newer is the security control with unique coverage (paths Dependabot cooldown doesn't reach), so --locked has to go.
Reverts the tox.ini runner change from uv-venv-runner back to uv-venv-lock-runner: uv-venv-runner uses 'uv pip install' with only the tox-declared dep groups, which skips the workspace install and left runtime deps (e.g. ops-scenario==8.9.0.dev0) unresolvable. Instead, add 'uv lock' before every tox invocation across framework-tests.yaml and example-charm-tests.yaml. That re-locks against the current '[tool.uv].exclude-newer = "7 days"' floor, so tox's uv-venv-lock-runner sees a fresh uv.lock and its internal 'uv sync --locked' succeeds. --locked stays as the security control inside tox; the rolling exclude-newer floor no longer breaks it.
dwilding
reviewed
Jul 5, 2026
dwilding
left a comment
Contributor
There was a problem hiding this comment.
I don't understand why the extra locks are needed. Especially the ones in example-charm-tests.yaml, which run in the charm projects where nothing has changed.
Contributor
Yeah, I have the same question. |
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.
Adds a rolling package-level cooldown in
[tool.uv]:uv refuses to resolve against any package published in the last 7 days, so a compromised release has a window to be caught / yanked upstream before it can enter this project. Complements (does not replace) the Dependabot cooldown, which only protects Dependabot-authored PRs —
exclude-neweralso covers manualuv add,uv lockregens,uvxbootstraps, and CI re-resolves, which Dependabot cooldown alone doesn't reach.