Skip to content

Commit

Permalink
fix(run): detect target configuration in package.json files (lerna#3432)
Browse files Browse the repository at this point in the history
  • Loading branch information
fahslaj authored and Ross Rhodes committed Jan 3, 2023
1 parent 816e9f0 commit 6c40a95
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 28 deletions.
24 changes: 14 additions & 10 deletions commands/run/index.js
Expand Up @@ -188,7 +188,7 @@ class RunCommand extends Command {
}
}

runScriptsUsingNx() {
async runScriptsUsingNx() {
if (this.options.ci) {
process.env.CI = "true";
}
Expand All @@ -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");
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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."
);
}

Expand Down
73 changes: 65 additions & 8 deletions e2e/tests/lerna-run/lerna-run-nx-include-dependencies.spec.ts
Expand Up @@ -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.
`);
});
Expand Down Expand Up @@ -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) => ({
Expand Down Expand Up @@ -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.
`);
});
Expand Down Expand Up @@ -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.
`);
});
Expand Down Expand Up @@ -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.
`);
});
Expand Down
8 changes: 4 additions & 4 deletions e2e/tests/lerna-run/lerna-run-nx-incompatible-options.spec.ts
Expand Up @@ -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.
`);
});
Expand Down Expand Up @@ -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.
`);
});
Expand Down Expand Up @@ -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.
`);
});
Expand Down Expand Up @@ -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.
`);
});
Expand Down
2 changes: 1 addition & 1 deletion website/docs/lerna-and-nx.md
Expand Up @@ -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.
:::

---
Expand Down
15 changes: 10 additions & 5 deletions website/docs/lerna6-obsolete-options.md
Expand Up @@ -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,
Expand All @@ -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`
Expand All @@ -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`).

:::
5 changes: 5 additions & 0 deletions website/package.json
Expand Up @@ -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"
}
}

0 comments on commit 6c40a95

Please sign in to comment.