From 6c40a95a34a8521f552017e347e6046b7d7c77ef Mon Sep 17 00:00:00 2001 From: Austin Fahsl Date: Tue, 29 Nov 2022 16:02:48 -0500 Subject: [PATCH] fix(run): detect target configuration in package.json files (#3432) --- commands/run/index.js | 24 +++--- .../lerna-run-nx-include-dependencies.spec.ts | 73 +++++++++++++++++-- .../lerna-run-nx-incompatible-options.spec.ts | 8 +- website/docs/lerna-and-nx.md | 2 +- website/docs/lerna6-obsolete-options.md | 15 ++-- website/package.json | 5 ++ 6 files changed, 99 insertions(+), 28 deletions(-) diff --git a/commands/run/index.js b/commands/run/index.js index 412c2257bf8..d9df84a2429 100644 --- a/commands/run/index.js +++ b/commands/run/index.js @@ -188,7 +188,7 @@ class RunCommand extends Command { } } - runScriptsUsingNx() { + async runScriptsUsingNx() { if (this.options.ci) { process.env.CI = "true"; } @@ -199,7 +199,7 @@ class RunCommand extends Command { } performance.mark("init-local"); this.configureNxOutput(); - const { targetDependencies, options, extraOptions } = this.prepNxOptions(); + const { targetDependencies, options, extraOptions } = await this.prepNxOptions(); if (this.packagesWithScript.length === 1) { const { runOne } = require("nx/src/command-line/run-one"); @@ -231,14 +231,18 @@ class RunCommand extends Command { } } - prepNxOptions() { + async prepNxOptions() { const nxJsonExists = existsSync(path.join(this.project.rootPath, "nx.json")); const { readNxJson } = require("nx/src/config/configuration"); const nxJson = readNxJson(); const targetDependenciesAreDefined = Object.keys(nxJson.targetDependencies || nxJson.targetDefaults || {}).length > 0; - const mimicLernaDefaultBehavior = !(nxJsonExists && targetDependenciesAreDefined); + + const hasProjectSpecificNxConfiguration = this.packagesWithScript.some((p) => !!p.get("nx")); + const hasCustomizedNxConfiguration = + (nxJsonExists && targetDependenciesAreDefined) || hasProjectSpecificNxConfiguration; + const mimicLernaDefaultBehavior = !hasCustomizedNxConfiguration; const targetDependencies = this.toposort && !this.options.parallel && mimicLernaDefaultBehavior @@ -276,36 +280,36 @@ class RunCommand extends Command { __overrides__: this.args.map((t) => t.toString()), }; - if (!mimicLernaDefaultBehavior) { + if (hasCustomizedNxConfiguration) { this.logger.verbose( this.name, - "nx.json with targetDefaults was found. Task dependencies will be automatically included." + "Nx target configuration was found. Task dependencies will be automatically included." ); if (this.options.parallel || this.options.sort !== undefined) { this.logger.warn( this.name, - `"parallel", "sort", and "no-sort" are ignored when nx.json has targetDefaults defined. See https://lerna.js.org/docs/lerna6-obsolete-options for details.` + `"parallel", "sort", and "no-sort" are ignored when Nx targets are configured. See https://lerna.js.org/docs/lerna6-obsolete-options for details.` ); } if (this.options.includeDependencies) { this.logger.info( this.name, - `Using the "include-dependencies" option when nx.json has targetDefaults defined will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/lerna6-obsolete-options#--include-dependencies for details.` + `Using the "include-dependencies" option when Nx targets are configured will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/lerna6-obsolete-options#--include-dependencies for details.` ); } if (this.options.ignore) { this.logger.info( this.name, - `Using the "ignore" option when nx.json has targetDefaults defined will exclude only tasks that are not determined to be required by Nx. See https://lerna.js.org/docs/lerna6-obsolete-options#--ignore for details.` + `Using the "ignore" option when Nx targets are configured will exclude only tasks that are not determined to be required by Nx. See https://lerna.js.org/docs/lerna6-obsolete-options#--ignore for details.` ); } } else { this.logger.verbose( this.name, - "nx.json was not found or is missing targetDefaults. Task dependencies will not be automatically included." + "Nx target configuration was not found. Task dependencies will not be automatically included." ); } diff --git a/e2e/tests/lerna-run/lerna-run-nx-include-dependencies.spec.ts b/e2e/tests/lerna-run/lerna-run-nx-include-dependencies.spec.ts index d1023ca9489..0c3c61c0180 100644 --- a/e2e/tests/lerna-run/lerna-run-nx-include-dependencies.spec.ts +++ b/e2e/tests/lerna-run/lerna-run-nx-include-dependencies.spec.ts @@ -107,7 +107,7 @@ describe("lerna-run-nx-include-dependencies", () => { lerna verb rootPath /tmp/lerna-e2e/lerna-run-nx-include-dependencies/lerna-workspace lerna notice filter including "package-X" lerna info filter [ 'package-X' ] - lerna verb run nx.json was not found or is missing targetDefaults. Task dependencies will not be automatically included. + lerna verb run Nx target configuration was not found. Task dependencies will not be automatically included. `); }); @@ -136,13 +136,13 @@ describe("lerna-run-nx-include-dependencies", () => { lerna verb rootPath /tmp/lerna-e2e/lerna-run-nx-include-dependencies/lerna-workspace lerna notice filter including "package-X" lerna info filter [ 'package-X' ] - lerna verb run nx.json was not found or is missing targetDefaults. Task dependencies will not be automatically included. + lerna verb run Nx target configuration was not found. Task dependencies will not be automatically included. `); }); }); - describe("with nx enabled and with nx.json with targetDefaults", () => { + describe("with nx enabled and with Nx target configuration", () => { it("should include package dependencies by default", async () => { await fixture.addNxJsonToWorkspace(); await fixture.updateJson("nx.json", (json) => ({ @@ -192,7 +192,7 @@ describe("lerna-run-nx-include-dependencies", () => { lerna verb rootPath /tmp/lerna-e2e/lerna-run-nx-include-dependencies/lerna-workspace lerna notice filter including "package-X" lerna info filter [ 'package-X' ] - lerna verb run nx.json with targetDefaults was found. Task dependencies will be automatically included. + lerna verb run Nx target configuration was found. Task dependencies will be automatically included. `); }); @@ -254,8 +254,8 @@ describe("lerna-run-nx-include-dependencies", () => { lerna notice filter including "package-X" lerna notice filter including dependencies lerna info filter [ 'package-X' ] - lerna verb run nx.json with targetDefaults was found. Task dependencies will be automatically included. - lerna info run Using the "include-dependencies" option when nx.json has targetDefaults defined will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/lerna6-obsolete-options#--include-dependencies for details. + lerna verb run Nx target configuration was found. Task dependencies will be automatically included. + lerna info run Using the "include-dependencies" option when Nx targets are configured will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/lerna6-obsolete-options#--include-dependencies for details. `); }); @@ -311,8 +311,65 @@ describe("lerna-run-nx-include-dependencies", () => { lerna notice filter including "package-X" lerna notice filter excluding "package-X" lerna info filter [ 'package-X', '!package-X' ] - lerna verb run nx.json with targetDefaults was found. Task dependencies will be automatically included. - lerna info run Using the "ignore" option when nx.json has targetDefaults defined will exclude only tasks that are not determined to be required by Nx. See https://lerna.js.org/docs/lerna6-obsolete-options#--ignore for details. + lerna verb run Nx target configuration was found. Task dependencies will be automatically included. + lerna info run Using the "ignore" option when Nx targets are configured will exclude only tasks that are not determined to be required by Nx. See https://lerna.js.org/docs/lerna6-obsolete-options#--ignore for details. + + `); + }); + }); + + describe("with nx enabled and with targets in a library's package.json", () => { + it("should include dependencies by default", async () => { + await fixture.addNxJsonToWorkspace(); + await fixture.updateJson("packages/package-3/package.json", (json) => ({ + ...json, + nx: { + targets: { + "print-name": { + dependsOn: ["^print-name"], + }, + }, + }, + })); + const output = await fixture.lerna("run print-name --scope package-3"); + expect(output.combinedOutput).toMatchInlineSnapshot(` + + > Lerna (powered by Nx) Running target print-name for project package-X and 2 task(s) it depends on + + + + > package-X:print-name + + + > package-X@0.0.0 print-name + > echo test-package-X + + test-package-X + + > package-X:print-name + + + > package-X@0.0.0 print-name + > echo test-package-X + + test-package-X + + > package-X:print-name + + > package-X@0.0.0 print-name + > echo test-package-X + test-package-X + + + + > Lerna (powered by Nx) Successfully ran target print-name for project package-X + + + lerna notice cli v999.9.9-e2e.0 + lerna verb rootPath /tmp/lerna-e2e/lerna-run-nx-include-dependencies/lerna-workspace + lerna notice filter including "package-X" + lerna info filter [ 'package-X' ] + lerna verb run Nx target configuration was found. Task dependencies will be automatically included. `); }); diff --git a/e2e/tests/lerna-run/lerna-run-nx-incompatible-options.spec.ts b/e2e/tests/lerna-run/lerna-run-nx-incompatible-options.spec.ts index 2ea07cb28be..21134e2b944 100644 --- a/e2e/tests/lerna-run/lerna-run-nx-incompatible-options.spec.ts +++ b/e2e/tests/lerna-run/lerna-run-nx-incompatible-options.spec.ts @@ -153,7 +153,7 @@ describe("lerna-run-nx-incompatible-options", () => { lerna notice cli v999.9.9-e2e.0 - lerna WARN run "parallel", "sort", and "no-sort" are ignored when nx.json has targetDefaults defined. See https://lerna.js.org/docs/lerna6-obsolete-options for details. + lerna WARN run "parallel", "sort", and "no-sort" are ignored when Nx targets are configured. See https://lerna.js.org/docs/lerna6-obsolete-options for details. `); }); @@ -201,7 +201,7 @@ describe("lerna-run-nx-incompatible-options", () => { lerna notice cli v999.9.9-e2e.0 - lerna WARN run "parallel", "sort", and "no-sort" are ignored when nx.json has targetDefaults defined. See https://lerna.js.org/docs/lerna6-obsolete-options for details. + lerna WARN run "parallel", "sort", and "no-sort" are ignored when Nx targets are configured. See https://lerna.js.org/docs/lerna6-obsolete-options for details. `); }); @@ -249,7 +249,7 @@ describe("lerna-run-nx-incompatible-options", () => { lerna notice cli v999.9.9-e2e.0 - lerna WARN run "parallel", "sort", and "no-sort" are ignored when nx.json has targetDefaults defined. See https://lerna.js.org/docs/lerna6-obsolete-options for details. + lerna WARN run "parallel", "sort", and "no-sort" are ignored when Nx targets are configured. See https://lerna.js.org/docs/lerna6-obsolete-options for details. `); }); @@ -298,7 +298,7 @@ describe("lerna-run-nx-incompatible-options", () => { lerna notice cli v999.9.9-e2e.0 lerna notice filter including dependencies - lerna info run Using the "include-dependencies" option when nx.json has targetDefaults defined will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/lerna6-obsolete-options#--include-dependencies for details. + lerna info run Using the "include-dependencies" option when Nx targets are configured will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/lerna6-obsolete-options#--include-dependencies for details. `); }); diff --git a/website/docs/lerna-and-nx.md b/website/docs/lerna-and-nx.md index 3f6645201f4..04a8825d56c 100644 --- a/website/docs/lerna-and-nx.md +++ b/website/docs/lerna-and-nx.md @@ -48,7 +48,7 @@ Free and open source - Continue using Lerna as usual :::note -When Lerna is set to use Nx and detects `nx.json` with `targetDefaults` in the workspace, it will defer to Nx to detect task dependencies. Some options for `lerna run` will behave differently than older versions of Lerna. See [Using Lerna (Powered by Nx) to Run Tasks](docs/lerna6-obsolete-options.md) for more details. +When Lerna is running tasks with Nx and detects Nx target configuration, it will defer to Nx to detect task dependencies. Some options for `lerna run` will behave differently than older versions of Lerna. See [Using Lerna (Powered by Nx) to Run Tasks](docs/lerna6-obsolete-options.md) for more details. ::: --- diff --git a/website/docs/lerna6-obsolete-options.md b/website/docs/lerna6-obsolete-options.md index 3a9c1c5d760..a04164010e9 100644 --- a/website/docs/lerna6-obsolete-options.md +++ b/website/docs/lerna6-obsolete-options.md @@ -2,8 +2,8 @@ Nx and Lerna work together seamlessly in the same workspace. -When `nx.json` is detected in the current workspace, Lerna will respect the `nx.json` configuration during `lerna run` -and delegate to the Nx task runner. +When Lerna is running tasks with Nx and detects Nx target configuration, Lerna will respect this configuration during `lerna run` +and delegate dependency detection to the Nx task runner. Nx will run tasks in an order and with a concurrency that it determines appropriate based on the task graph that it creates. For more information, @@ -17,7 +17,7 @@ for `lerna run` become obsolete. ### `--sort` and `--no-sort` -When `nx.json` is present, Lerna will always run tasks in the order it deems is correct based on its knowledge of +When Nx targets are configured, Lerna will always run tasks in the order it deems is correct based on its knowledge of project and task dependencies, so `--sort` and `--no-sort` have no effect. ### `--parallel` @@ -44,7 +44,12 @@ required [task graph](https://nx.dev/concepts/mental-model#the-task-graph). :::tip -The effects on the options above will only apply if `nx.json` exists in the root with the `targetDefaults` property -defined. Otherwise, they will behave just as they would with Lerna's base task runner (if `useNx` is `false`). +The effects on the options above will only apply if: + +1. `nx.json` exists in the root with the `targetDefaults` property + defined. +2. The `"nx"` property is found in the package.json of a target package. + +Otherwise, they will behave just as they would with Lerna's legacy task runner (if `useNx` is `false`). ::: diff --git a/website/package.json b/website/package.json index 06f07bb1851..cdc0283557b 100644 --- a/website/package.json +++ b/website/package.json @@ -42,5 +42,10 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "volta": { + "node": "16.15.0", + "npm": "8.12.1", + "yarn": "1.22.18" } }