Repository navigation
Fix uv dry run missing inline [tool.uv] refusal (#979) - #980
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A uv project whose [tool.uv] or [tool.uv.sources] is written as an
inline table (sources = { ... }, [tool] uv = { ... }, dotted
uv.sources = { ... }) can't be wired, and the real `vendor` run
refused it with pypi_uv_lock_parse_failed. But that refusal was only
raised while wiring, after the dry run had already returned, so
`vendor --dry-run` previewed a clean vendor (exit 0) and the real run
downloaded the prebuilt wheel before failing (exit 1).
The uv preflight now checks the same table chain wiring will edit
([tool.uv] for a transitive package, then [tool.uv.sources]) and
refuses with the same code and message. Dry runs now preview the
refusal, and the real run refuses before any download or write.
Fixes #979
Assisted-by: Claude Code:claude-opus-5-5
e889171 to
951740b
Compare
main has failed socket-patch-core's lib tests since Gradle support (#646) and the digest helpers (#865) both landed. The guard test production_digests_go_through_the_helpers flags three files #646 added that still hash inline: crawlers/gradle_cache.rs, patch/jvm_jar.rs and patch/sidecars/maven.rs. That breaks test, test-release and coverage on every open PR. Each inline sha1/sha256 call now goes through sha1_hex_of or sha256_hex_of, which compute the same lowercase hex. Behaviour is unchanged. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
[agent]
Proposed patch for --- a/crates/socket-patch-core/src/utils/digest.rs
+++ b/crates/socket-patch-core/src/utils/digest.rs
@@ const PENDING_INLINE_DIGESTS: &[&str] = &[
- "crawlers/gradle_cache.rs",
- "patch/jvm_jar.rs",
- "patch/sidecars/maven.rs",
"utils/group_commit.rs",Once that's on Generated by Claude Code |
main has been red on test (macos/windows), test-release and coverage since #690: it moved crawlers/gradle_cache.rs, patch/jvm_jar.rs and patch/sidecars/maven.rs onto the utils::digest helpers but left them on PENDING_INLINE_DIGESTS. The guard test production_digests_go_through_the_helpers fails on a stale entry, so socket-patch-core's lib tests fail on main and on every PR based on it. Remove the three entries. No production behaviour changes. Assisted-by: Claude Code:claude-opus-5-5
…ght' into agent/fix-uv-inline-table-preflight
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit ef589a6. Configure here.
|
[agent]
No fix exists for it. I'll re-run the failed job once when the workflow run finishes. If it fails the same way a second time, I'll treat it as a real failure and look into it. Generated by Claude Code |
main is red on production_digests_go_through_the_helpers: #690 moved gradle_cache.rs, jvm_jar.rs and sidecars/maven.rs onto the utils::digest helpers, but PENDING_INLINE_DIGESTS still lists them, and the ratchet fails on a stale entry. Same three-line change as #889 and #980; it no-ops once main carries it. Assisted-by: Claude Code:claude-opus-5-5
|
[agent]
No fix exists for a hung Generated by Claude Code |
|
[agent] Ready for review at ef589a6.
Generated by Claude Code |
|
[agent] Ready to merge at
It's waiting only on a maintainer to merge it. Generated by Claude Code |
|
Ready for review (burn-down agent). Head Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #979
Refs #944 (only its remaining dry-run preview piece; that issue stays with #963's claim)
Summary
On a uv project whose
[tool.uv]or[tool.uv.sources]is written as an inline table,vendor --dry-runpreviewed a clean vendor (exit 0), but the real run refused withpypi_uv_lock_parse_failed(exit 1), and only after downloading the prebuilt wheel. With this PR the dry run previews the same refusal, and the real run refuses before any download or write.Root cause
The uv vendored backend can't add keys to a
[tool],[tool.uv]or[tool.uv.sources]that is an inline table or a non-table value, so it refuses withpyproject.toml [<path>] is not a standard table. That refusal was raised only byensure_tableinsidewire_uv. The preflightcheck_target_guards, whichpypi.rsruns before the prebuilt download and before the dry run returns, never checked the table chain.Fix
check_target_guards(crates/socket-patch-core/src/vendor/pypi_uv.rs) now runs a read-onlycheck_standard_tablesover the same chainwire_uvedits, in the same order:tool.uvfor a transitive package (the override-dependencies path), thentool.uv.sources. It returns the same code and detail. A missing link is fine (wire creates it). Header-less tables implied by a sub-table and dotted-key tables (uv.package = true) still count as standard tables and stay wireable.ensure_tableand the preflight share onenot_a_standard_tableconstructor, so the two messages can't drift apart.vendor,scan --mode vendoredandget --mode vendored, because all of them go through the samepypi.rspreflight. It also gives Keep the hosted pin when a vendored takeover is refused (#853, #944) #963's takeover dry-run preview the uv inline-sources gate that uv hosted → vendored takeover (scan/get --mode vendored) restores the package to PyPI before the uv vendored refusals run, so an inline[tool.uv] sources = {…}table (or a #928 marker split) leaves it unpatched in both modes, while --dry-run previews would_vendor #944 still needs.CI fix carried for
main: stale digest pending listmain(db83f01) is red ontest (macos/windows),test-releaseandcoverage.utils::digest::tests::production_digests_go_through_the_helpersfails because #690 movedcrawlers/gradle_cache.rs,patch/jvm_jar.rsandpatch/sidecars/maven.rsonto theutils::digesthelpers but left them onPENDING_INLINE_DIGESTS, and the guard fails on a stale entry. This PR's earlier port of #878 (Route Gradle digests through utils::digest) is now a no-op after mergingmain. Commitd456e5bdrops the three stale entries. It is test-only and no-ops oncemaincarries the same change. Other open PRs based onmainwill hit the same failure until it does.Reproduced on
main1c6c509locally: the guard test fails with left = the 6 real inline files, right = those 6 plus the 3 Gradle files. Afterd456e5bit passes, and CIcoverageandtest (macos-latest)are green onef589a6.Test evidence
Red before the fix, on
main+ tests only:vendor::pypi_uv::tests::guards_refuse_non_standard_uv_tables_like_wirefailed withunwrap_err() on an Ok value: Fresh(the preflight accepted the inline table).vendor::pypi::tests::uv_inline_sources_table_refused_in_dry_and_wet_runsfailed withdry_run=true: expected Refused, got Done { … success: true … vendor_prebuilt_downloaded … }. This reproduces the issue: the dry run reported success.Green after the fix: both pass.
Per-issue checklist:
vendor --dry-runpreviews success on a uv project with an inline[tool.uv]/sourcestable, but the real run refusespypi_uv_lock_parse_failed(exit 1) #979 inline[tool.uv] sources = {…}: unit test (preflight == wire error, files untouched) plus an orchestrator test (dry and wet runs bothRefused pypi_uv_lock_parse_failed, no.socket/vendordir, pair byte-identical)vendor --dry-runpreviews success on a uv project with an inline[tool.uv]/sourcestable, but the real run refusespypi_uv_lock_parse_failed(exit 1) #979[tool] uv = { sources = {…}, index = […] }: unit testvendor --dry-runpreviews success on a uv project with an inline[tool.uv]/sourcestable, but the real run refusespypi_uv_lock_parse_failed(exit 1) #979 dotted[tool] uv.sources = {…}: unit testvendor --dry-runpreviews success on a uv project with an inline[tool.uv]/sourcestable, but the real run refusespypi_uv_lock_parse_failed(exit 1) #979 transitive +[tool] uv = { constraint-dependencies = […] }names[tool.uv]: unit testLocal runs (Linux, toolchain 1.93.1, on the merge with
maindb83f01):cargo clippy --workspace --all-features -- -D warnings: cleancargo test --workspace --all-features --no-fail-fast: everything passes except 12 tests that make a path read-only (0o555) or unremovable and expect a write to fail. This container runs as root, and root ignores those permissions:covgap_commands_vendor::{vendor,revert,reconcile}_state_write_failure_*, 3in_process_redirectwrite-failure tests, 2repaircleanup-failure tests,copy_tree::relax_loop_must_not_traverse_symlinked_root,vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry,pypi_poetry::wire_write_failure_*andpypi_requirements::wire_failure_rolls_back_already_written_files. None of them touch this change, and CI runs as a non-root user.cargo fmt: the changed files are rustfmt-clean.npm/,pypi/,gem/): not affected. This is a Rust-only change.Why this cluster
#979 was the only untriaged issue this run, and its fix is small and self-contained. It also closes the preview gap that #963 leaves open on #944, so one change helps two issues.
🤖 Generated with Claude Code
https://claude.ai/code/session_01S9NhAHzAgkz5oUuRrbkyV3
Generated by Claude Code