From 8f05cba76afc0d37c9fcef37433dce214445c4db Mon Sep 17 00:00:00 2001 From: Austin Fahsl Date: Fri, 21 Oct 2022 16:32:08 -0700 Subject: [PATCH 1/6] feat(version): specify npmClientArgs with version command --- commands/version/command.js | 4 ++++ commands/version/index.js | 10 ++++++++-- core/lerna/schemas/lerna-schema.json | 10 ++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/commands/version/command.js b/commands/version/command.js index dee6d6e76c..f840931b93 100644 --- a/commands/version/command.js +++ b/commands/version/command.js @@ -168,6 +168,10 @@ exports.builder = (yargs, composed) => { requiresArg: true, defaultDescription: "v", }, + "npm-client-args": { + describe: "Additional arguments to pass to the npm client when performing 'npm install'.", + type: "array", + }, y: { describe: "Skip all confirmation prompts.", alias: "yes", diff --git a/commands/version/index.js b/commands/version/index.js index 8f210e827f..c08fc1db1d 100644 --- a/commands/version/index.js +++ b/commands/version/index.js @@ -616,11 +616,13 @@ class VersionCommand extends Command { ); } + const npmClientArgs = this.options.npmClientArgs || []; + if (this.options.npmClient === "pnpm") { chain = chain.then(() => { this.logger.verbose("version", "Updating root pnpm-lock.yaml"); return childProcess - .exec("pnpm", ["install", "--lockfile-only", "--ignore-scripts"], this.execOpts) + .exec("pnpm", ["install", "--lockfile-only", "--ignore-scripts", ...npmClientArgs], this.execOpts) .then(() => { const lockfilePath = path.join(this.project.rootPath, "pnpm-lock.yaml"); changedFiles.add(lockfilePath); @@ -634,7 +636,11 @@ class VersionCommand extends Command { chain = chain.then(() => { this.logger.verbose("version", "Updating root package-lock.json"); return childProcess - .exec("npm", ["install", "--package-lock-only", "--ignore-scripts"], this.execOpts) + .exec( + "npm", + ["install", "--package-lock-only", "--ignore-scripts", ...npmClientArgs], + this.execOpts + ) .then(() => { changedFiles.add(lockfilePath); }); diff --git a/core/lerna/schemas/lerna-schema.json b/core/lerna/schemas/lerna-schema.json index 2fd7e24cce..8b0c3d6ab6 100644 --- a/core/lerna/schemas/lerna-schema.json +++ b/core/lerna/schemas/lerna-schema.json @@ -1123,6 +1123,9 @@ "npmClient": { "$ref": "#/$defs/globals/npmClient" }, + "npmClientArgs": { + "$ref": "#/$defs/globals/npmClientArgs" + }, "loglevel": { "$ref": "#/$defs/globals/loglevel" }, @@ -1423,6 +1426,13 @@ "default": "npm", "enum": ["npm", "yarn", "pnpm"] }, + "npmClientArgs": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Arguments to pass to the npm client when running commands." + }, "loglevel": { "type": "string", "description": "The level of logging to use when running commands. Defaults to info if unspecified.", From 74e212a6269f8c639a2a399dcbe535fc0c53d1a3 Mon Sep 17 00:00:00 2001 From: Austin Fahsl Date: Fri, 18 Nov 2022 15:17:42 -0500 Subject: [PATCH 2/6] chore(e2e): add e2e coverage for npmClientArgs on version --- .../lerna-version/npm-client-args.spec.ts | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 e2e/tests/lerna-version/npm-client-args.spec.ts diff --git a/e2e/tests/lerna-version/npm-client-args.spec.ts b/e2e/tests/lerna-version/npm-client-args.spec.ts new file mode 100644 index 0000000000..1b40672de8 --- /dev/null +++ b/e2e/tests/lerna-version/npm-client-args.spec.ts @@ -0,0 +1,59 @@ +import { Fixture } from "../../utils/fixture"; +import { normalizeCommitSHAs, normalizeEnvironment } from "../../utils/snapshot-serializer-utils"; + +expect.addSnapshotSerializer({ + serialize(str: string) { + return normalizeCommitSHAs(normalizeEnvironment(str)); + }, + test(val: string) { + return val != null && typeof val === "string"; + }, +}); + +describe("lerna-version-npm-client-args", () => { + let fixture: Fixture; + + beforeEach(async () => { + fixture = await Fixture.create({ + name: "lerna-version-npm-client-args", + packageManager: "npm", + initializeGit: true, + runLernaInit: true, + installDependencies: true, + }); + await fixture.lerna("create package-a -y"); + + // eslint-plugin-react-app@6.2.2 requires a peer dependency of eslint@"6.x". + // Without it, the npm install at the end of `lerna version` will fail if + // --legacy-peer-deps is not passed correctly. + await fixture.updateJson("package.json", (json) => ({ + ...json, + dependencies: { + ...(json.dependencies as Record), + "eslint-plugin-react-app": "6.2.2", + eslint: "8.25.0", + }, + })); + await fixture.createInitialGitCommit(); + await fixture.exec("git push origin test-main"); + }); + afterEach(() => fixture.destroy()); + + it("should add npmClientArgs to npm install at the end of the version command", async () => { + const output = await fixture.lerna("version 3.3.3 -y --npmClientArgs=--legacy-peer-deps"); + expect(output.combinedOutput).toMatchInlineSnapshot(` + lerna notice cli v999.9.9-e2e.0 + lerna info current version 0.0.0 + lerna info Assuming all packages changed + + Changes: + - package-a: 0.0.0 => 3.3.3 + + lerna info auto-confirmed + lerna info execute Skipping releases + lerna info git Pushing tags... + lerna success version finished + + `); + }); +}); From e682ad04a4cc17813460c99283970c2ce3fa2cc4 Mon Sep 17 00:00:00 2001 From: Austin Fahsl Date: Fri, 16 Dec 2022 13:42:54 -0600 Subject: [PATCH 3/6] chore(e2e): pre-install dependencies to prevent caching error --- .../lerna-version => version/src}/npm-client-args.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename e2e/{tests/lerna-version => version/src}/npm-client-args.spec.ts (84%) diff --git a/e2e/tests/lerna-version/npm-client-args.spec.ts b/e2e/version/src/npm-client-args.spec.ts similarity index 84% rename from e2e/tests/lerna-version/npm-client-args.spec.ts rename to e2e/version/src/npm-client-args.spec.ts index 1b40672de8..d2e7742326 100644 --- a/e2e/tests/lerna-version/npm-client-args.spec.ts +++ b/e2e/version/src/npm-client-args.spec.ts @@ -1,5 +1,4 @@ -import { Fixture } from "../../utils/fixture"; -import { normalizeCommitSHAs, normalizeEnvironment } from "../../utils/snapshot-serializer-utils"; +import { Fixture, normalizeCommitSHAs, normalizeEnvironment } from "@lerna/e2e-utils"; expect.addSnapshotSerializer({ serialize(str: string) { @@ -34,13 +33,16 @@ describe("lerna-version-npm-client-args", () => { eslint: "8.25.0", }, })); + await fixture.exec( + "npm install eslint-plugin-react-app@6.2.2 eslint@8.25.0 --save=false --legacy-peer-deps" + ); await fixture.createInitialGitCommit(); await fixture.exec("git push origin test-main"); }); afterEach(() => fixture.destroy()); it("should add npmClientArgs to npm install at the end of the version command", async () => { - const output = await fixture.lerna("version 3.3.3 -y --npmClientArgs=--legacy-peer-deps"); + const output = await fixture.lerna("version 3.3.3 -y --npm-client-args=--legacy-peer-deps"); expect(output.combinedOutput).toMatchInlineSnapshot(` lerna notice cli v999.9.9-e2e.0 lerna info current version 0.0.0 From c7d4333fbc19b4bc55403d4dc00e27114ffbb6a1 Mon Sep 17 00:00:00 2001 From: Austin Fahsl Date: Fri, 16 Dec 2022 14:28:00 -0600 Subject: [PATCH 4/6] chore(docs): update version docs to include npmClientArgs option --- commands/version/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/commands/version/README.md b/commands/version/README.md index f30c5ec5a7..b6b2f8b0dd 100644 --- a/commands/version/README.md +++ b/commands/version/README.md @@ -70,6 +70,7 @@ Running `lerna version --conventional-commits` without the above flags will rele - [`--no-granular-pathspec`](#--no-granular-pathspec) - [`--no-private`](#--no-private) - [`--no-push`](#--no-push) + - [`--npm-client-args`](#--npm-client-args) - [`--preid`](#--preid) - [`--signoff-git-commit`](#--signoff-git-commit) - [`--sign-git-commit`](#--sign-git-commit) @@ -398,6 +399,14 @@ Note that this option does _not_ exclude [private scoped packages](https://docs. By default, `lerna version` will push the committed and tagged changes to the configured [git remote](#--git-remote-name). Pass `--no-push` to disable this behavior. +### `--npm-client-args` + +This option allows arguments to be passed to the `npm install` that `lerna version` performs to update the lockfile. + +For example: + +`lerna version 3.3.3 --npm-client-args=--legacy-peer-deps` + ### `--preid` ```sh From 9c6ac07e1c5014c49ec78819ab7f7f528d0a5bbc Mon Sep 17 00:00:00 2001 From: Austin Fahsl Date: Fri, 16 Dec 2022 14:53:32 -0600 Subject: [PATCH 5/6] chore(docs): add explicit support for lerna.json options --- commands/version/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/commands/version/README.md b/commands/version/README.md index b6b2f8b0dd..98fa91b718 100644 --- a/commands/version/README.md +++ b/commands/version/README.md @@ -407,6 +407,15 @@ For example: `lerna version 3.3.3 --npm-client-args=--legacy-peer-deps` +This can also be set in `lerna.json`: + +```json +{ + ... + "npmClientArgs": ["--legacy-peer-deps", "--production"] +} +``` + ### `--preid` ```sh From 27ec0e38879d618338877ce48bbe44b6d18bd0d4 Mon Sep 17 00:00:00 2001 From: Austin Fahsl Date: Mon, 19 Dec 2022 11:09:16 -0600 Subject: [PATCH 6/6] chore(version): improve usability of passing multiple args --- commands/version/README.md | 21 ++++++++++++++- commands/version/index.js | 3 ++- core/lerna/schemas/lerna-schema.json | 3 +++ e2e/version/src/npm-client-args.spec.ts | 36 +++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/commands/version/README.md b/commands/version/README.md index 98fa91b718..9800481996 100644 --- a/commands/version/README.md +++ b/commands/version/README.md @@ -405,7 +405,13 @@ This option allows arguments to be passed to the `npm install` that `lerna versi For example: -`lerna version 3.3.3 --npm-client-args=--legacy-peer-deps` +```sh +lerna version 3.3.3 --npm-client-args=--legacy-peer-deps + +lerna version 3.3.3 --npm-client-args="--legacy-peer-deps,--force" + +lerna version 3.3.3 --npm-client-args="--legacy-peer-deps --force" +``` This can also be set in `lerna.json`: @@ -416,6 +422,19 @@ This can also be set in `lerna.json`: } ``` +or specifically for the version command: + +```json +{ + ... + "command": { + "version": { + "npmClientArgs": ["--legacy-peer-deps", "--production"] + } + } +} +``` + ### `--preid` ```sh diff --git a/commands/version/index.js b/commands/version/index.js index c08fc1db1d..b9abcbc1cd 100644 --- a/commands/version/index.js +++ b/commands/version/index.js @@ -616,7 +616,8 @@ class VersionCommand extends Command { ); } - const npmClientArgs = this.options.npmClientArgs || []; + const npmClientArgsRaw = this.options.npmClientArgs || []; + const npmClientArgs = npmClientArgsRaw.reduce((args, arg) => args.concat(arg.split(/\s|,/)), []); if (this.options.npmClient === "pnpm") { chain = chain.then(() => { diff --git a/core/lerna/schemas/lerna-schema.json b/core/lerna/schemas/lerna-schema.json index 8b0c3d6ab6..4db8c6eb07 100644 --- a/core/lerna/schemas/lerna-schema.json +++ b/core/lerna/schemas/lerna-schema.json @@ -1067,6 +1067,9 @@ "npmClient": { "$ref": "#/$defs/globals/npmClient" }, + "npmClientArgs": { + "$ref": "#/$defs/globals/npmClientArgs" + }, "loglevel": { "$ref": "#/$defs/globals/loglevel" }, diff --git a/e2e/version/src/npm-client-args.spec.ts b/e2e/version/src/npm-client-args.spec.ts index d2e7742326..c04b8c466d 100644 --- a/e2e/version/src/npm-client-args.spec.ts +++ b/e2e/version/src/npm-client-args.spec.ts @@ -58,4 +58,40 @@ describe("lerna-version-npm-client-args", () => { `); }); + + it("should support multiple arguments, comma delimited", async () => { + const output = await fixture.lerna('version 3.3.3 -y --npm-client-args="--legacy-peer-deps,--fund"'); + expect(output.combinedOutput).toMatchInlineSnapshot(` + lerna notice cli v999.9.9-e2e.0 + lerna info current version 0.0.0 + lerna info Assuming all packages changed + + Changes: + - package-a: 0.0.0 => 3.3.3 + + lerna info auto-confirmed + lerna info execute Skipping releases + lerna info git Pushing tags... + lerna success version finished + + `); + }); + + it("should support multiple arguments, space delimited", async () => { + const output = await fixture.lerna('version 3.3.3 -y --npm-client-args="--legacy-peer-deps --fund"'); + expect(output.combinedOutput).toMatchInlineSnapshot(` + lerna notice cli v999.9.9-e2e.0 + lerna info current version 0.0.0 + lerna info Assuming all packages changed + + Changes: + - package-a: 0.0.0 => 3.3.3 + + lerna info auto-confirmed + lerna info execute Skipping releases + lerna info git Pushing tags... + lerna success version finished + + `); + }); });