Skip to content

Commit

Permalink
fix(run): fully defer to Nx for dep detection when nx.json exists
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Oct 2, 2022
1 parent 7bdefbd commit 0657aa4
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 11 deletions.
8 changes: 7 additions & 1 deletion packages/run/README.md
Expand Up @@ -182,6 +182,8 @@ Nx will run tasks in an order and with a concurrency that it determines appropri

**This behavior allows Nx to run tasks in the most efficient way possible, but it also means that some existing options for `lerna run` become obsolete as explained below.**

> **Note** when Lerna is set to use Nx and detects `nx.json` in the workspace, it will defer to Nx to detect task dependencies. Some options for `lerna run` will behave differently. See [Using Lerna (Powered by Nx) to Run Tasks](./recipes/using-lerna-powered-by-nx-to-run-tasks) for more details.
#### Obsolete Options when `useNx` is enabled

##### `--sort` and `--no-sort`
Expand All @@ -199,6 +201,10 @@ Nx will use the task graph to determine which tasks can be run in parallel and d

Lerna by itself does not have knowledge of which tasks depend on others, so it defaults to excluding tasks on dependent projects when using [filter options](https://github.com/lerna/lerna/tree/6cb8ab2d4af7ce25c812e8fb05cd04650105705f/core/filter-options#lernafilter-options) and relies on `--include-dependencies` to manually specify that dependent projects' tasks should be included.

This is no longer a problem when Lerna uses Nx to run tasks. Nx, utilizing its [task graph](https://nx.dev/concepts/mental-model#the-task-graph), will automatically run dependent tasks first when necessary, so `--include-dependencies` is obsolete.
This is no longer a problem when Lerna uses Nx to run tasks. Nx, utilizing its [task graph](https://nx.dev/concepts/mental-model#the-task-graph), will automatically run dependent tasks first when necessary, so `--include-dependencies` is obsolete. However, it can still be used to include project dependencies that Lerna detects but Nx does not deem necessary and would otherwise exclude.

### `--ignore`

When used with Nx, `--ignore` will never cause `lerna run` to exclude any tasks that are deemed to be required by the Nx [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. If `nx.json` does not exist and `useNx` is `true`, then they will behave just as they would with Lerna's base task runner (if `useNx` is `false`).
20 changes: 19 additions & 1 deletion packages/run/src/__tests__/run-command.spec.ts
Expand Up @@ -404,8 +404,14 @@ describe('RunCommand', () => {
it('does not run a script in ignored packages', async () => {
collectedOutput = '';
await lernaRun(testDir)('my-script', '--ignore', 'package-@(2|3|4)');

expect(collectedOutput).toContain('package-1');
expect(collectedOutput).not.toContain('package-3');

const logMessages = loggingOutput('info');
expect(logMessages).toContain(
'Using the "ignore" option when nx.json exists will exclude only tasks that are not determined to be required by Nx. See https://lerna.js.org/docs/recipes/using-lerna-powered-by-nx-to-run-tasks#--ignore for details.'
);
});

it('runs a script in packages with --stream', async () => {
Expand Down Expand Up @@ -439,7 +445,19 @@ describe('RunCommand', () => {

const [logMessage] = loggingOutput('warn');
expect(logMessage).toContain(
'"parallel", "sort", "no-sort", and "include-dependencies" are ignored when nx.json exists.'
'"parallel", "sort", and "no-sort" are ignored when nx.json exists. See https://lerna.js.org/docs/recipes/using-lerna-powered-by-nx-to-run-tasks for details.'
);
expect(collectedOutput).toContain('package-1');
});

it('should log some infos when using "includeDependencies" options with useNx', async () => {
collectedOutput = '';

await lernaRun(testDir)('my-script', '--include-dependencies');

const logMessages = loggingOutput('info');
expect(logMessages).toContain(
'Using the "include-dependencies" option when nx.json exists will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/recipes/using-lerna-powered-by-nx-to-run-tasks#--include-dependencies for details.'
);
expect(collectedOutput).toContain('package-1');
});
Expand Down
27 changes: 18 additions & 9 deletions packages/run/src/run-command.ts
Expand Up @@ -251,15 +251,10 @@ export class RunCommand extends Command<RunCommandOption & FilterOptions> {
}

async prepNxOptions() {
const { readNxJson } = await import('nx/src/config/configuration');
const nxJson = readNxJson();
const nxJsonExists = existsSync(path.join(this.project.rootPath, 'nx.json'));
const useParallel = this.options.parallel && !nxJsonExists;
const targetDependenciesAreDefined =
Object.keys(nxJson.targetDependencies || nxJson.targetDefaults || {}).length > 0;
const targetDependencies =
// prettier-ignore
this.toposort && !useParallel && !targetDependenciesAreDefined
this.toposort && !this.options.parallel && !nxJsonExists
? {
[this.script]: [
{
Expand All @@ -283,7 +278,7 @@ export class RunCommand extends Command<RunCommandOption & FilterOptions> {
* To match lerna's own behavior (via pMap's default concurrency), we set parallel to a very large number if
* the flag has been set (we can't use Infinity because that would cause issues with the task runner).
*/
parallel: useParallel ? 999 : this.concurrency,
parallel: this.options.parallel && !nxJsonExists ? 999 : this.concurrency,
nxBail: this.bail,
nxIgnoreCycles: !this.options.rejectCycles,
skipNxCache: this.options.skipNxCache,
Expand All @@ -294,10 +289,24 @@ export class RunCommand extends Command<RunCommandOption & FilterOptions> {
if (nxJsonExists) {
this.logger.verbose(this.name, 'nx.json was found. Task dependencies will be automatically included.');

if (this.options.parallel || this.options.sort !== undefined || this.options.includeDependencies) {
if (this.options.parallel || this.options.sort !== undefined) {
this.logger.warn(
this.name,
`"parallel", "sort", "no-sort", and "include-dependencies" are ignored when nx.json exists. See https://lerna.js.org/docs/recipes/using-lerna-powered-by-nx-to-run-tasks for details.`
`"parallel", "sort", and "no-sort" are ignored when nx.json exists. See https://lerna.js.org/docs/recipes/using-lerna-powered-by-nx-to-run-tasks for details.`
);
}

if (this.options.includeDependencies) {
this.logger.info(
this.name,
`Using the "include-dependencies" option when nx.json exists will include both task dependencies detected by Nx and project dependencies detected by Lerna. See https://lerna.js.org/docs/recipes/using-lerna-powered-by-nx-to-run-tasks#--include-dependencies for details.`
);
}

if (this.options.ignore) {
this.logger.info(
this.name,
`Using the "ignore" option when nx.json exists will exclude only tasks that are not determined to be required by Nx. See https://lerna.js.org/docs/recipes/using-lerna-powered-by-nx-to-run-tasks#--ignore for details.`
);
}
}
Expand Down

0 comments on commit 0657aa4

Please sign in to comment.