Skip to content

feat: install git repositories that use pnpm #6734

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions .github/workflows/integration-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ jobs:
with:
node-version: ${{ env.node-version }}

- name: Enable Corepack
run: |
npm install -g corepack
corepack enable

- name: 'Check that the Yarn files don''t change on new installs (fix w/ "yarn install")'
run: |
node ./scripts/run-yarn.js --immutable --immutable-cache
Expand Down Expand Up @@ -254,6 +259,11 @@ jobs:
with:
node-version: ${{matrix.node}}.x

- name: Enable Corepack
run: |
npm install -g corepack
corepack enable

- uses: actions/download-artifact@v4
with:
name: yarn-artifacts
Expand Down
35 changes: 35 additions & 0 deletions .yarn/versions/4d0fa20f.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
releases:
"@yarnpkg/cli": minor
"@yarnpkg/core": minor
"@yarnpkg/plugin-git": minor
"@yarnpkg/plugin-github": minor

declined:
- "@yarnpkg/plugin-compat"
- "@yarnpkg/plugin-constraints"
- "@yarnpkg/plugin-dlx"
- "@yarnpkg/plugin-essentials"
- "@yarnpkg/plugin-exec"
- "@yarnpkg/plugin-file"
- "@yarnpkg/plugin-http"
- "@yarnpkg/plugin-init"
- "@yarnpkg/plugin-interactive-tools"
- "@yarnpkg/plugin-jsr"
- "@yarnpkg/plugin-link"
- "@yarnpkg/plugin-nm"
- "@yarnpkg/plugin-npm"
- "@yarnpkg/plugin-npm-cli"
- "@yarnpkg/plugin-pack"
- "@yarnpkg/plugin-patch"
- "@yarnpkg/plugin-pnp"
- "@yarnpkg/plugin-pnpm"
- "@yarnpkg/plugin-stage"
- "@yarnpkg/plugin-typescript"
- "@yarnpkg/plugin-version"
- "@yarnpkg/plugin-workspace-tools"
- "@yarnpkg/builder"
- "@yarnpkg/doctor"
- "@yarnpkg/extensions"
- "@yarnpkg/nm"
- "@yarnpkg/pnpify"
- "@yarnpkg/sdks"
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Yarn now accepts sponsors! Please take a look at our [OpenCollective](https://op
Features in `master` can be tried out by running `yarn set version from sources` in your project.
:::

- Yarn can now install git repositories that use pnpm (workspaces are supported too if pnpm@>=6.x is installed on the system).

- Fixes `preferInteractive` forcing interactive mode in non-TTY environments.
- `node-modules` linker now honors user-defined symlinks for `<workspace>/node_modules` directories
- `node-modules` linker supports hoisting into inner workspaces that are parents of other workspaces
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/master
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".

exec git update-server-info
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
57d05601ca0e00e0047b2ea8a0f30b0dc760e40b refs/heads/master
57d05601ca0e00e0047b2ea8a0f30b0dc760e40b refs/remotes/origin/HEAD
57d05601ca0e00e0047b2ea8a0f30b0dc760e40b refs/remotes/origin/master
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x5�1� �agNA:+���ۀv�(4-��b|���/�%h���T�d�!L(�6��s���d�%��3�ؿ�̑�<�CD��Y�,��N& 4�R���� �
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
xUͱ�0�ag���$��э�:8��j�
\��ֻV!�wG���W��V��a�x���c�3�PM�,�^ r��e���Eja�O�;eߦ4��s���Η�v��C7�}"�) fEv& �yt@�X�;��/'�6�
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
57d05601ca0e00e0047b2ea8a0f30b0dc760e40b refs/remotes/origin/master
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
57d05601ca0e00e0047b2ea8a0f30b0dc760e40b
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/master
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".

exec git update-server-info
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
d16bc461ce9bd42690625105cd50ae5936ebce34 refs/heads/master
d16bc461ce9bd42690625105cd50ae5936ebce34 refs/remotes/origin/HEAD
d16bc461ce9bd42690625105cd50ae5936ebce34 refs/remotes/origin/master
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x�A� =�}51<�;�b�6���x��L6V�xlKU*Y*�܇h�@n��|� :��0&���鉍[�F��g�J�&�2sm
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
x��I��V���W��U��6HyQ�1f2f0;̌1��럓��J��k��kQQ�~# p��m�������Ri� }
��0$Ȕ�a��1E�0f���i̛��T�i�>���G���_�;,�Q��GH�'Y�p��؇~���6��l(2���É��S6���:�;7�� ��sq<B�T�b�y����r��O�ʂ�ٿ�F�H�-�B� >{Y�r |6-���ױz](�i7mGg=��{a�6Ө5*��|�5���F~{@���*x�*���7� ��q������F��_.�VtΑm�hk�/J��w��/{�0�Q������]�ﯝ�7"J��(+� ��..yB�P�NG� Y�+r������1�UENoC��ޙ$i-� �"P��gB�d�2���t�-c���,�i4C)?K ����ɷ�I���J1�j�t���g�+q;���뙐&�,ዾ�Fc���6Ju�(;{W�W��t2Q�\ �Vz��ٰ�^��b1����=6"ϵE�� c`/��+M�9�_]ò�s���m�͝q�D�.��>�C^J5);2��l��U?0��*.��p�r��wb�D��׋"N�%3��}�TB $�Χ�̨��<��n�PCth�
�~h~e7�zu[s���;%�u`n�/�r�1,}[����!b�-?�ӗ���D�e�e����yd�N˥��%g��+�uZ�%^�bG d���7{�)�;��F������+;#o*���Hb������ƾ;#��5��~�w=�_�O�
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
d16bc461ce9bd42690625105cd50ae5936ebce34 refs/remotes/origin/master
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d16bc461ce9bd42690625105cd50ae5936ebce34
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,26 @@ describe(`Protocols`, () => {
),
);

test(
`it should use pnpm to setup pnpm repositories`,
makeTemporaryEnv(
{
dependencies: {
[`pnpm-project`]: tests.startPackageServer().then(url => `${url}/repositories/pnpm-project.git`),
},
},
async ({path, run, source}) => {
await expect(run(`install`, {
env: {
NODE_ENV: `production`,
},
})).resolves.toBeTruthy();

await expect(source(`require('pnpm-project')`)).resolves.toMatch(/\bpnpm\/[0-9]+/);
},
),
);

test(
`it should guarantee that all dependencies will be installed when using npm to setup npm repositories`,
makeTemporaryEnv(
Expand Down Expand Up @@ -263,6 +283,31 @@ describe(`Protocols`, () => {
),
);

test(
`it should support installing specific workspaces from pnpm repositories`,
makeTemporaryEnv(
{
dependencies: {
[`pkg-a`]: tests.startPackageServer().then(url => `${url}/repositories/pnpm-workspaces.git#workspace=pkg-a`),
[`pkg-b`]: tests.startPackageServer().then(url => `${url}/repositories/pnpm-workspaces.git#workspace=pkg-b`),
},
},
async ({path, run, source}) => {
await run(`install`);

await expect(source(`require('pkg-a/package.json')`)).resolves.toMatchObject({
name: `pkg-a`,
version: `1.0.0`,
});

await expect(source(`require('pkg-b/package.json')`)).resolves.toMatchObject({
name: `pkg-b`,
version: `1.0.0`,
});
},
),
);

test(
`it should not use Corepack to fetch Yarn Classic`,
makeTemporaryEnv(
Expand Down
38 changes: 37 additions & 1 deletion packages/yarnpkg-core/sources/scriptUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,47 @@ export async function prepareExternalProject(cwd: PortablePath, outputPath: Port

return 0;
}],

[PackageManager.Pnpm, async () => {
// Remove environment variables that limit the install to just production dependencies
delete env.NODE_ENV;

const install = await execUtils.pipevp(`pnpm`, [`install`], {cwd, env, stdin, stdout, stderr, end: execUtils.EndStrategy.ErrorCode});
if (install.code !== 0)
return install.code;

const packStream = new PassThrough();
const packPromise = miscUtils.bufferStream(packStream);

packStream.pipe(stdout);

// It seems that pnpm doesn't support specifying the pack output path,
// so we have to extract the stdout on top of forking it to the logs.

// - `pnpm pack` doesn't support the `--filter` flag so we have to use `pnpm exec`
// - We have to use the `--pack-destination` flag because otherwise pnpm generates the tarball inside the workspace cwd
// - Only pnpm@>=6.x supports the `--pack-destination` flag (and previous versions throw an error)
const packArgs = workspace !== null
? [`--filter`, workspace, `exec`, `pnpm`, `pack`, `--pack-destination`, npath.fromPortablePath(cwd)]
: [`pack`];

const pack = await execUtils.pipevp(`pnpm`, packArgs, {cwd, env, stdin, stdout: packStream, stderr});
if (pack.code !== 0)
return pack.code;

const packOutput = (await packPromise).toString().trim().replace(/^.*\n/s, ``);
const packTarget = ppath.resolve(cwd, npath.toPortablePath(packOutput));

// Only then can we move the pack to its rightful location
await xfs.renamePromise(packTarget, outputPath);

return 0;
}],
]);

const workflow = workflows.get(effectivePackageManager);
if (typeof workflow === `undefined`)
throw new Error(`Assertion failed: Unsupported workflow`);
throw new Error(`Assertion failed: Unsupported workflow: "${effectivePackageManager}"`);

const code = await workflow();
if (code === 0 || typeof code === `undefined`)
Expand Down