Skip to content
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

feat(version): use npmClientArgs in npm install after lerna version #3434

Merged
merged 6 commits into from Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 37 additions & 0 deletions commands/version/README.md
Expand Up @@ -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)
Expand Down Expand Up @@ -398,6 +399,42 @@ 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:

```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`:

```json
{
...
"npmClientArgs": ["--legacy-peer-deps", "--production"]
}
```

or specifically for the version command:

```json
{
...
"command": {
"version": {
"npmClientArgs": ["--legacy-peer-deps", "--production"]
}
}
}
```

### `--preid`

```sh
Expand Down
4 changes: 4 additions & 0 deletions commands/version/command.js
Expand Up @@ -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",
Expand Down
11 changes: 9 additions & 2 deletions commands/version/index.js
Expand Up @@ -616,11 +616,14 @@ class VersionCommand extends Command {
);
}

const npmClientArgsRaw = this.options.npmClientArgs || [];
const npmClientArgs = npmClientArgsRaw.reduce((args, arg) => args.concat(arg.split(/\s|,/)), []);

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);
Expand All @@ -634,7 +637,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);
});
Expand Down
13 changes: 13 additions & 0 deletions core/lerna/schemas/lerna-schema.json
Expand Up @@ -1067,6 +1067,9 @@
"npmClient": {
"$ref": "#/$defs/globals/npmClient"
},
"npmClientArgs": {
"$ref": "#/$defs/globals/npmClientArgs"
},
"loglevel": {
"$ref": "#/$defs/globals/loglevel"
},
Expand Down Expand Up @@ -1123,6 +1126,9 @@
"npmClient": {
"$ref": "#/$defs/globals/npmClient"
},
"npmClientArgs": {
"$ref": "#/$defs/globals/npmClientArgs"
},
"loglevel": {
"$ref": "#/$defs/globals/loglevel"
},
Expand Down Expand Up @@ -1423,6 +1429,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.",
Expand Down
97 changes: 97 additions & 0 deletions e2e/version/src/npm-client-args.spec.ts
@@ -0,0 +1,97 @@
import { Fixture, normalizeCommitSHAs, normalizeEnvironment } from "@lerna/e2e-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<string, string>),
"eslint-plugin-react-app": "6.2.2",
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 --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
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, 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

`);
});
});