[Bug?]: Portal dependendency on package using workspace protocol fails.
Self-service
- [ ] I'd be willing to implement a fix
Describe the bug
Portal dependency on package from a workspace fails with following error:
➤ YN0000: ┌ Resolution step
➤ YN0001: │ Error: b@workspace:*: Workspace not found (b@workspace:*)
at Project.getWorkspaceByDescriptor (/sandbox/berry/packages/yarnpkg-core/sources/Project.ts:506:13)
at WorkspaceResolver.getCandidates (/sandbox/berry/packages/yarnpkg-core/sources/WorkspaceResolver.ts:41:36)
at MultiResolver.getCandidates (/sandbox/berry/packages/yarnpkg-core/sources/MultiResolver.ts:45:27)
at MultiResolver.getCandidates (/sandbox/berry/packages/yarnpkg-core/sources/MultiResolver.ts:45:27)
at fn (/sandbox/berry/packages/yarnpkg-core/sources/Project.ts:817:33)
at Object.prettifyAsyncErrors (/sandbox/berry/packages/yarnpkg-core/sources/miscUtils.ts:174:18)
at startDescriptorResolution (/sandbox/berry/packages/yarnpkg-core/sources/Project.ts:816:54)
➤ YN0000: └ Completed
➤ YN0000: Failed with errors in 0s 116ms
To reproduce
const {mkdir, writeFile} = require(`fs/promises`);
await mkdir(`workspace`);
await mkdir(`workspace/packages`);
await mkdir(`workspace/packages/a`);
await mkdir(`workspace/packages/b`);
await mkdir(`c`);
await writeFile(`workspace/package.json`, JSON.stringify({
"workspaces": ["packages/*"],
}));
await writeFile(`workspace/packages/a/package.json`, JSON.stringify({
name: `a`,
}));
await writeFile(`workspace/packages/b/package.json`, JSON.stringify({
name: `b`,
dependencies: {
b: `workspace:*`,
},
}));
await writeFile(`c/package.json`, JSON.stringify({
name: `c`,
dependencies: {
b: `portal:../workspace/packages/b`,
},
}));
await expect(yarn({cwd: `c`})).resolves.toBeTruthy();
Environment
System:
OS: Linux 6.0 Fedora Linux 37 (Workstation Edition)
CPU: (16) x64 AMD Ryzen 7 1700X Eight-Core Processor
Binaries:
Node: 18.12.1 - /tmp/xfs-d8db7e7b/node
Yarn: 3.3.0 - /tmp/xfs-d8db7e7b/yarn
npm: 8.19.2 - /usr/bin/npm
Additional context
I am not sure if this is supposed to work and therefore is a bug, so some context on what I am trying to achieve: I have a project A written in react. And a package B-react, which also depends react and on another framework-agnostic package B-universal, which both reside in a monorepo. This monorepo is a yarn workspace and uses yarn's PnP. A uses node-modules linker. The thing I want to do is to test a change which requires changing both B-universal and B-react in my application A. And this change is non-trivial and therefore it is not possible to directly publish it to npm - I need to somehow link my projects.
Ofc, there are workarounds like using yarn pack and pointing resolutions to resulting tarballs or using unplug. But I would very much like to be able to directly work in my original repository so that there is no extra step to get the changes into my app nor to commiting the changes.
This issue reproduces on master:
Error: expect(received).resolves.toBeTruthy()
Received promise rejected instead of resolved
Rejected to value: [Error: Command failed: /usr/bin/node /github/workspace/scripts/actions/../run-yarn.js
➤ YN0000: ┌ Resolution step
::group::Resolution step
➤ YN0001: │ Error: b@workspace:*: Workspace not found (b@workspace:*)
at Project.getWorkspaceByDescriptor (/github/workspace/packages/yarnpkg-core/sources/Project.ts:506:13)
at WorkspaceResolver.getCandidates (/github/workspace/packages/yarnpkg-core/sources/WorkspaceResolver.ts:41:36)
at MultiResolver.getCandidates (/github/workspace/packages/yarnpkg-core/sources/MultiResolver.ts:45:27)
at MultiResolver.getCandidates (/github/workspace/packages/yarnpkg-core/sources/MultiResolver.ts:45:27)
at fn (/github/workspace/packages/yarnpkg-core/sources/Project.ts:817:33)
at Object.prettifyAsyncErrors (/github/workspace/packages/yarnpkg-core/sources/miscUtils.ts:174:18)
at startDescriptorResolution (/github/workspace/packages/yarnpkg-core/sources/Project.ts:816:54)
::endgroup::
➤ YN0000: └ Completed
➤ YN0000: Failed with errors in 0s 53ms
]
at expect (/github/workspace/.yarn/cache/expect-npm-24.8.0-8c7640c562-44ff9ab1e7.zip/node_modules/expect/build/index.js:138:15)
at module.exports (evalmachine.<anonymous>:32:7)
at async /github/workspace/.yarn/cache/@arcanis-sherlock-npm-2.0.3-558f52b79f-286d94b96d.zip/node_modules/@arcanis/sherlock/lib/executeRepro.js:57:13
at async executeInTempDirectory (/github/workspace/.yarn/cache/@arcanis-sherlock-npm-2.0.3-558f52b79f-286d94b96d.zip/node_modules/@arcanis/sherlock/lib/executeRepro.js:18:16)
at async executeRepro (/github/workspace/.yarn/cache/@arcanis-sherlock-npm-2.0.3-558f52b79f-286d94b96d.zip/node_modules/@arcanis/sherlock/lib/executeRepro.js:25:12)
at async ExecCommand.execute (/github/workspace/.yarn/cache/@arcanis-sherlock-npm-2.0.3-558f52b79f-286d94b96d.zip/node_modules/@arcanis/sherlock/lib/commands/exec.js:26:38)
at async ExecCommand.validateAndExecute (/github/workspace/.yarn/cache/clipanion-npm-2.0.0-rc.16-b9444aaf89-4061026d74.zip/node_modules/clipanion/lib/advanced/Command.js:161:26)
at async Cli.run (/github/workspace/.yarn/cache/clipanion-npm-2.0.0-rc.16-b9444aaf89-4061026d74.zip/node_modules/clipanion/lib/advanced/Cli.js:74:24)
at async Cli.runExit (/github/workspace/.yarn/cache/clipanion-npm-2.0.0-rc.16-b9444aaf89-4061026d74.zip/node_modules/clipanion/lib/advanced/Cli.js:83:28)
For the benefit of others who may be running into this issue: I was able to work around this issue adding a portal: resolution for every single transitive@workspace:* dependency of the original package that I wanted to bring in via portal:
For example, if I depend on a monorepo package b which in turn depends on other monorepo workspaces x and y, the relevant section of my package.json would look like this:
"resolutions": {
"x@workspace:*": "portal:../other-repo/packages/x",
"y@workspace:*": "portal:../other-repo/packages/y"
},
"dependencies": {
"b": "portal:../other-repo/packages/b"
}
This appears to work equally well whether using the pnp or node-modules linker.