Repository navigation
Fix yarn classic check of dangling descriptors (#1379) - #1388
Mikola Lysenko (mikolalysenko) merged 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 |
|
Yarn 1 is not a high priority and for these weird features the best thing to do is pick the simplest option. If supporting them adds too much complexity then better to ignore for now. It doesn't seem like many packages would be installed using this mechanism and if a user did do it, then we probably wouldn't want to patch it. |
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