Repository navigation
Fix yarn classic check of dangling descriptors (#1379) - #1388
Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
vendor --check reported a yarn classic lock as healthy when an older release had vendored a patch that adds a dependency without locking it, so yarn 1 installed that dependency unpinned and offline installs failed. vendor --check now fails such an entry and names the missing descriptors, and repair reports it instead of leaving it silently. Fixes #1379 Assisted-by: Claude Code:claude-opus-5-5
The new yarn classic check also flagged a dependency that the package already listed before vendoring but that yarn 1 never locks, such as a workspace member, so vendor --check and repair failed on healthy projects. It now reports only dependencies the original lock entry did not name, and the contract describes the new vendor --check failure. Refs #1379 Assisted-by: Claude Code:claude-opus-5-5
|
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 f22885a. Configure here.
|
Ready for review at
Generated by Claude Code |
|
[final reviewer] Review of Question. Should Today the only exemption is "the recorded pre-vendor block already named it". That leaves two cases where
Both are rare. Fixing them means reading the workspace globs (no shared helper exists for yarn 1 yet). Not fixing them means a CI check that some users can't turn green. Please pick one:
Smaller notes (non-blocking):
Labelled Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1379
Summary
Releases since #591 refuse to write a yarn classic
yarn.lockblock whosedependencies:/optionalDependencies:sub-map names a descriptor (name@range) that has no lock block. But a lock an older release already vendored in that state was still reported healthy:vendor --checkreturnedvendor_check_ok(exit 0) andrepairleft it alone. Meanwhile yarn 1 installs that dependency unpinned, and--offlineinstalls fail. I confirmed with real yarn 1.22.22 thatyarn install --frozen-lockfileaccepts such a lock silently.Now:
vendor --checkfails the entry withvendor_check_failed, and the reason names the dangling descriptors.repairreports the entryfailedwithvendor_dep_manifest_unlocked(the code new runs already refuse with) and leaves the lock as it is.yarn install(without--frozen-lockfile) to lock the descriptors, then commityarn.lock. I verified with real yarn 1.22.22 that this adds the missing block and keeps the vendoredfile:resolution.Root cause
The check that refuses new writes (
unlocked_descriptors, which reads the patchedpackage.json) had no read-side twin over the lock blocks already wired to an entry. So nothing ever audited a lock written before that refusal existed.Changes
formats/yarn/classic_deps.rs:block_dep_descriptorsreads a block's own sub-maps back (quoted or bare tokens, the same waysplit_key_patternsreads keys).unlocked_amongis the shared "which of these descriptors has no block" check.unlocked_descriptorsnow goes through it too.vendor/yarn_classic_lock.rs:dangling_descriptors(entry, root)checks every block whoseresolvedpoints into the entry's uuid dir. It skips descriptors that the recorded pre-vendor block already named, because yarn 1 writes no block for a workspace member or alink:dependency, and those are upstream's, not the patch's.vendor/npm_flavor.rs:dangling_lock_dependenciesdispatches by flavor.check_npm_wiring(used byvendor --check) calls it for the non-package-lock flavors.commands/vendored_backend/repair.rs: a healthy npm entry whose lock has dangling descriptors is reported as failed.CLI_CONTRACT.md: documents the newvendor --checkdrift cause and therepairuse ofvendor_dep_manifest_unlocked.Test evidence
covgap_commands_vendor::yarn_classic_check_and_repair_flag_a_dangling_dependency_descriptor,yarn_classic_lock::tests::issue_1379_check_flags_a_dangling_descriptor_an_old_release_wrotefailed/vendor_dep_manifest_unlocked, lock unchanged)issue_1379_check_ignores_an_unlocked_descriptor_upstream_hadclassic_deps::tests::block_dep_descriptors_reads_the_blocks_own_sub_maps,yarn_token_reads_quoted_and_bare_tokensCommands run locally:
cargo fmt --all -- --check: cleancargo clippy --workspace --all-features -- -D warnings: cleancargo test --workspace --all-features --no-fail-fast: 13897 passed, 13 failed. Each failure is environmental and none touch this change. 12 rely on chmod-based write failures, which the sandbox's root user bypasses (*_state_write_failure_*,*_unremovable*,wire_*_failure_*,relax_loop_must_not_traverse_symlinked_root,*write_failures*,*invalidation_failure*,repair_cleanup_failure*). The other one,e2e_bun_lockb::binary_shared_bundled_record_hosted_pin_is_managed, needspatches-api.socket.dev, which the sandbox can't reach.scripts/yarn-classic-vex-matrix.sh 1.22.22(real yarn, all 4 suites): 65/65 cells pass./code-review high
Fixed: false positives on upstream-unlocked descriptors such as workspace members (findings 1 and 3), the contract's
vendor --checksection (5),\\-escape handling consistent with key parsing (6), the shared uuid predicate (7), and the duplicated flavor dispatch (8). Not changed:repairruns the new check only for an artifact it judges healthy. For a missing or corrupt artifact it still redownloads first, because the remedy (yarn install) needs the vendored tarball on disk. Failing before the redownload would leave the user stuck. The nextrepairorvendor --checkreports the dangling descriptor.🤖 Generated with Claude Code
https://claude.ai/code/session_01JKRFFfsrTtKJs3Sj5BDygE
Generated by Claude Code