From cd79e4e4500929517da7e41c0e34b670fa90e004 Mon Sep 17 00:00:00 2001 From: AgentEnder Date: Tue, 19 Sep 2023 16:34:39 -0400 Subject: [PATCH 1/2] feat(core): accept various task runner options from root of nx.json --- docs/generated/devkit/NxJsonConfiguration.md | 37 +++++++ docs/generated/devkit/TargetConfiguration.md | 10 ++ docs/generated/devkit/Task.md | 9 ++ docs/generated/devkit/Workspace.md | 53 ++++++++++ packages/nx/src/config/nx-json.ts | 21 ++++ packages/nx/src/config/task-graph.ts | 5 + .../src/config/workspace-json-project-json.ts | 6 ++ packages/nx/src/daemon/client/client.ts | 1 + .../nx/src/generators/utils/deprecated.ts | 8 ++ .../nx/src/tasks-runner/create-task-graph.ts | 1 + .../nx/src/tasks-runner/run-command.spec.ts | 51 ++++++++++ packages/nx/src/tasks-runner/run-command.ts | 99 ++++++++++++++----- .../nx/src/tasks-runner/task-orchestrator.ts | 6 +- packages/nx/src/tasks-runner/utils.ts | 13 ++- packages/nx/src/utils/cache-directory.ts | 5 +- packages/nx/src/utils/nx-cloud-utils.ts | 24 +++-- 16 files changed, 305 insertions(+), 44 deletions(-) diff --git a/docs/generated/devkit/NxJsonConfiguration.md b/docs/generated/devkit/NxJsonConfiguration.md index 18c5c9ddc2f2f..9f6ead99b2256 100644 --- a/docs/generated/devkit/NxJsonConfiguration.md +++ b/docs/generated/devkit/NxJsonConfiguration.md @@ -18,7 +18,9 @@ Nx.json configuration ### Properties +- [accessToken](../../devkit/documents/NxJsonConfiguration#accesstoken): string - [affected](../../devkit/documents/NxJsonConfiguration#affected): NxAffectedConfig +- [cacheDirectory](../../devkit/documents/NxJsonConfiguration#cachedirectory): string - [cli](../../devkit/documents/NxJsonConfiguration#cli): Object - [defaultProject](../../devkit/documents/NxJsonConfiguration#defaultproject): string - [extends](../../devkit/documents/NxJsonConfiguration#extends): string @@ -27,15 +29,26 @@ Nx.json configuration - [installation](../../devkit/documents/NxJsonConfiguration#installation): NxInstallationConfiguration - [namedInputs](../../devkit/documents/NxJsonConfiguration#namedinputs): Object - [npmScope](../../devkit/documents/NxJsonConfiguration#npmscope): string +- [parallel](../../devkit/documents/NxJsonConfiguration#parallel): number - [plugins](../../devkit/documents/NxJsonConfiguration#plugins): string[] - [pluginsConfig](../../devkit/documents/NxJsonConfiguration#pluginsconfig): Record<string, unknown> - [release](../../devkit/documents/NxJsonConfiguration#release): NxReleaseConfiguration - [targetDefaults](../../devkit/documents/NxJsonConfiguration#targetdefaults): TargetDefaults - [tasksRunnerOptions](../../devkit/documents/NxJsonConfiguration#tasksrunneroptions): Object +- [useDaemonProcess](../../devkit/documents/NxJsonConfiguration#usedaemonprocess): boolean - [workspaceLayout](../../devkit/documents/NxJsonConfiguration#workspacelayout): Object ## Properties +### accessToken + +• `Optional` **accessToken**: `string` + +If specified Nx will use nx-cloud by default with the given token. +To use a different runner that accepts an access token, define it in [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions) + +--- + ### affected • `Optional` **affected**: [`NxAffectedConfig`](../../devkit/documents/NxAffectedConfig) @@ -44,6 +57,14 @@ Default options for `nx affected` --- +### cacheDirectory + +• `Optional` **cacheDirectory**: `string` + +Changes the default location of the cache directory. + +--- + ### cli • `Optional` **cli**: `Object` @@ -148,6 +169,14 @@ NPM Scope that the workspace uses --- +### parallel + +• `Optional` **parallel**: `number` + +Specifies how many tasks are ran in parallel by Nx for the default tasks runner. + +--- + ### plugins • `Optional` **plugins**: `string`[] @@ -192,6 +221,14 @@ Available Task Runners --- +### useDaemonProcess + +• `Optional` **useDaemonProcess**: `boolean` + +Allows turning the daemon off if set to false explicitly. + +--- + ### workspaceLayout • `Optional` **workspaceLayout**: `Object` diff --git a/docs/generated/devkit/TargetConfiguration.md b/docs/generated/devkit/TargetConfiguration.md index 251878c7850c0..ae0a478bdf522 100644 --- a/docs/generated/devkit/TargetConfiguration.md +++ b/docs/generated/devkit/TargetConfiguration.md @@ -12,6 +12,7 @@ Target's configuration ### Properties +- [cache](../../devkit/documents/TargetConfiguration#cache): boolean - [command](../../devkit/documents/TargetConfiguration#command): string - [configurations](../../devkit/documents/TargetConfiguration#configurations): Object - [defaultConfiguration](../../devkit/documents/TargetConfiguration#defaultconfiguration): string @@ -23,6 +24,15 @@ Target's configuration ## Properties +### cache + +• `Optional` **cache**: `boolean` + +Determines if Nx is able to cache a given target. +Currently only supported in `targetDefaults`. + +--- + ### command • `Optional` **command**: `string` diff --git a/docs/generated/devkit/Task.md b/docs/generated/devkit/Task.md index 389893a3f5998..bd068534e58e4 100644 --- a/docs/generated/devkit/Task.md +++ b/docs/generated/devkit/Task.md @@ -6,6 +6,7 @@ A representation of the invocation of an Executor ### Properties +- [cache](../../devkit/documents/Task#cache): boolean - [endTime](../../devkit/documents/Task#endtime): number - [hash](../../devkit/documents/Task#hash): string - [hashDetails](../../devkit/documents/Task#hashdetails): Object @@ -17,6 +18,14 @@ A representation of the invocation of an Executor ## Properties +### cache + +• `Optional` **cache**: `boolean` + +Determines if a given task should be cacheable. + +--- + ### endTime • `Optional` **endTime**: `number` diff --git a/docs/generated/devkit/Workspace.md b/docs/generated/devkit/Workspace.md index 7f2f09e29a107..07a89a9855165 100644 --- a/docs/generated/devkit/Workspace.md +++ b/docs/generated/devkit/Workspace.md @@ -16,7 +16,9 @@ use ProjectsConfigurations or NxJsonConfiguration ### Properties +- [accessToken](../../devkit/documents/Workspace#accesstoken): string - [affected](../../devkit/documents/Workspace#affected): NxAffectedConfig +- [cacheDirectory](../../devkit/documents/Workspace#cachedirectory): string - [cli](../../devkit/documents/Workspace#cli): Object - [defaultProject](../../devkit/documents/Workspace#defaultproject): string - [extends](../../devkit/documents/Workspace#extends): string @@ -25,17 +27,32 @@ use ProjectsConfigurations or NxJsonConfiguration - [installation](../../devkit/documents/Workspace#installation): NxInstallationConfiguration - [namedInputs](../../devkit/documents/Workspace#namedinputs): Object - [npmScope](../../devkit/documents/Workspace#npmscope): string +- [parallel](../../devkit/documents/Workspace#parallel): number - [plugins](../../devkit/documents/Workspace#plugins): string[] - [pluginsConfig](../../devkit/documents/Workspace#pluginsconfig): Record<string, unknown> - [projects](../../devkit/documents/Workspace#projects): Record<string, ProjectConfiguration> - [release](../../devkit/documents/Workspace#release): NxReleaseConfiguration - [targetDefaults](../../devkit/documents/Workspace#targetdefaults): TargetDefaults - [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions): Object +- [useDaemonProcess](../../devkit/documents/Workspace#usedaemonprocess): boolean - [version](../../devkit/documents/Workspace#version): number - [workspaceLayout](../../devkit/documents/Workspace#workspacelayout): Object ## Properties +### accessToken + +• `Optional` **accessToken**: `string` + +If specified Nx will use nx-cloud by default with the given token. +To use a different runner that accepts an access token, define it in [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions) + +#### Inherited from + +[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[accessToken](../../devkit/documents/NxJsonConfiguration#accesstoken) + +--- + ### affected • `Optional` **affected**: [`NxAffectedConfig`](../../devkit/documents/NxAffectedConfig) @@ -48,6 +65,18 @@ Default options for `nx affected` --- +### cacheDirectory + +• `Optional` **cacheDirectory**: `string` + +Changes the default location of the cache directory. + +#### Inherited from + +[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[cacheDirectory](../../devkit/documents/NxJsonConfiguration#cachedirectory) + +--- + ### cli • `Optional` **cli**: `Object` @@ -184,6 +213,18 @@ NPM Scope that the workspace uses --- +### parallel + +• `Optional` **parallel**: `number` + +Specifies how many tasks are ran in parallel by Nx for the default tasks runner. + +#### Inherited from + +[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[parallel](../../devkit/documents/NxJsonConfiguration#parallel) + +--- + ### plugins • `Optional` **plugins**: `string`[] @@ -260,6 +301,18 @@ Available Task Runners --- +### useDaemonProcess + +• `Optional` **useDaemonProcess**: `boolean` + +Allows turning the daemon off if set to false explicitly. + +#### Inherited from + +[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[useDaemonProcess](../../devkit/documents/NxJsonConfiguration#usedaemonprocess) + +--- + ### version • **version**: `number` diff --git a/packages/nx/src/config/nx-json.ts b/packages/nx/src/config/nx-json.ts index 0823f002395fa..0b8d9aec3754a 100644 --- a/packages/nx/src/config/nx-json.ts +++ b/packages/nx/src/config/nx-json.ts @@ -191,6 +191,27 @@ export interface NxJsonConfiguration { * **ALPHA**: Configuration for `nx release` (versioning and publishing of applications and libraries) */ release?: NxReleaseConfiguration; + + /** + * If specified Nx will use nx-cloud by default with the given token. + * To use a different runner that accepts an access token, define it in {@link tasksRunnerOptions} + */ + accessToken?: string; + + /** + * Specifies how many tasks are ran in parallel by Nx for the default tasks runner. + */ + parallel?: number; + + /** + * Changes the default location of the cache directory. + */ + cacheDirectory?: string; + + /** + * Allows turning the daemon off if set to false explicitly. + */ + useDaemonProcess?: boolean; } export function readNxJson(root: string = workspaceRoot): NxJsonConfiguration { diff --git a/packages/nx/src/config/task-graph.ts b/packages/nx/src/config/task-graph.ts index 96fb672b1176d..00ec80f94ec28 100644 --- a/packages/nx/src/config/task-graph.ts +++ b/packages/nx/src/config/task-graph.ts @@ -66,6 +66,11 @@ export interface Task { * Unix timestamp of when a Batch Task ends **/ endTime?: number; + + /** + * Determines if a given task should be cacheable. + */ + cache?: boolean; } /** diff --git a/packages/nx/src/config/workspace-json-project-json.ts b/packages/nx/src/config/workspace-json-project-json.ts index 86a2904908a1f..1466774b76993 100644 --- a/packages/nx/src/config/workspace-json-project-json.ts +++ b/packages/nx/src/config/workspace-json-project-json.ts @@ -181,4 +181,10 @@ export interface TargetConfiguration { * A default named configuration to use when a target configuration is not provided. */ defaultConfiguration?: string; + + /** + * Determines if Nx is able to cache a given target. + * Currently only supported in `targetDefaults`. + */ + cache?: boolean; } diff --git a/packages/nx/src/daemon/client/client.ts b/packages/nx/src/daemon/client/client.ts index 925d7d507f922..778df66051a13 100644 --- a/packages/nx/src/daemon/client/client.ts +++ b/packages/nx/src/daemon/client/client.ts @@ -65,6 +65,7 @@ export class DaemonClient { enabled() { if (this._enabled === undefined) { const useDaemonProcessOption = + this.nxJson.useDaemonProcess ?? this.nxJson.tasksRunnerOptions?.['default']?.options?.useDaemonProcess; const env = process.env.NX_DAEMON; diff --git a/packages/nx/src/generators/utils/deprecated.ts b/packages/nx/src/generators/utils/deprecated.ts index a49cd05057ed5..eb363c1704bd1 100644 --- a/packages/nx/src/generators/utils/deprecated.ts +++ b/packages/nx/src/generators/utils/deprecated.ts @@ -40,6 +40,10 @@ export function updateWorkspaceConfiguration( extends: ext, installation, release, + accessToken, + cacheDirectory, + parallel, + useDaemonProcess, } = workspaceConfig; const nxJson: Required = { @@ -58,6 +62,10 @@ export function updateWorkspaceConfiguration( extends: ext, installation, release, + accessToken, + cacheDirectory, + parallel, + useDaemonProcess, }; updateNxJson(tree, nxJson); diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 97572012dd4f8..4676730bc45dd 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -334,6 +334,7 @@ export class ProcessTasks { target: qualifiedTarget, projectRoot: project.data.root, overrides: interpolateOverrides(overrides, project.name, project.data), + cache: project.data.targets[target].cache, }; } diff --git a/packages/nx/src/tasks-runner/run-command.spec.ts b/packages/nx/src/tasks-runner/run-command.spec.ts index b835cd3ea0298..086d61a7bae6b 100644 --- a/packages/nx/src/tasks-runner/run-command.spec.ts +++ b/packages/nx/src/tasks-runner/run-command.spec.ts @@ -1,6 +1,7 @@ import { TasksRunner } from './tasks-runner'; import { getRunner } from './run-command'; import { NxJsonConfiguration } from '../config/nx-json'; +import { join } from 'path'; describe('getRunner', () => { let nxJson: NxJsonConfiguration; @@ -73,4 +74,54 @@ describe('getRunner', () => { expect(tasksRunner).toEqual(mockRunner); }); + + it('uses default runner when no tasksRunnerOptions are present', () => { + jest.mock(join(__dirname, './default-tasks-runner.ts'), () => mockRunner); + + const { tasksRunner } = getRunner({}, {}); + + expect(tasksRunner).toEqual(mockRunner); + }); + + it('uses nx-cloud when no tasksRunnerOptions are present and accessToken is specified', () => { + jest.mock('nx-cloud', () => mockRunner); + + const { tasksRunner } = getRunner( + {}, + { + accessToken: 'XXXX-XXX-XXXX', + } + ); + + expect(tasksRunner).toEqual(mockRunner); + }); + + it('reads options from base properties if no runner options provided', () => { + jest.mock(join(__dirname, './default-tasks-runner.ts'), () => mockRunner); + + const { runnerOptions } = getRunner( + {}, + { + cacheDirectory: '.nx/cache', + parallel: 3, + useDaemonProcess: false, + targetDefaults: { + build: { + cache: true, + }, + }, + } + ); + + expect(runnerOptions).toMatchInlineSnapshot(` + { + "cacheDirectory": ".nx/cache", + "cacheableOperations": [ + "build", + ], + "parallel": 3, + "useDaemonProcess": false, + } + `); + }); }); diff --git a/packages/nx/src/tasks-runner/run-command.ts b/packages/nx/src/tasks-runner/run-command.ts index b651dc6a75490..1fbc629363bca 100644 --- a/packages/nx/src/tasks-runner/run-command.ts +++ b/packages/nx/src/tasks-runner/run-command.ts @@ -390,7 +390,7 @@ function shouldUseDynamicLifeCycle( if (isCI()) return false; if (outputStyle === 'static' || outputStyle === 'stream') return false; - return !tasks.find((t) => shouldStreamOutput(t, null, options)); + return !tasks.find((t) => shouldStreamOutput(t, null)); } export function getRunner( @@ -402,35 +402,82 @@ export function getRunner( } { let runner = nxArgs.runner; runner = runner || 'default'; - if (!nxJson.tasksRunnerOptions) { - throw new Error(`Could not find any runner configurations in nx.json`); + + if (runner !== 'default' && !nxJson.tasksRunnerOptions[runner]) { + throw new Error(`Could not find runner configuration for ${runner}`); } - if (nxJson.tasksRunnerOptions[runner]) { - let modulePath: string = nxJson.tasksRunnerOptions[runner].runner; - let tasksRunner; - if (modulePath) { - if (isRelativePath(modulePath)) { - modulePath = join(workspaceRoot, modulePath); - } + const modulePath: string = getTasksRunnerPath(runner, nxJson); - tasksRunner = require(modulePath); - // to support both babel and ts formats - if (tasksRunner.default) { - tasksRunner = tasksRunner.default; - } - } else { - tasksRunner = require('./default-tasks-runner').defaultTasksRunner; + let tasksRunner = require(modulePath); + // to support both babel and ts formats + if (tasksRunner.default) { + tasksRunner = tasksRunner.default; + } + + return { + tasksRunner, + runnerOptions: getRunnerOptions(runner, nxJson, nxArgs), + }; +} +function getTasksRunnerPath( + runner: string, + nxJson: NxJsonConfiguration +) { + let modulePath: string = nxJson.tasksRunnerOptions?.[runner]?.runner; + + if (modulePath) { + if (isRelativePath(modulePath)) { + return join(workspaceRoot, modulePath); } + return modulePath; + } - return { - tasksRunner, - runnerOptions: { - ...nxJson.tasksRunnerOptions[runner].options, - ...nxArgs, - }, - }; - } else { - throw new Error(`Could not find runner configuration for ${runner}`); + // No runner prop in tasks runner options, check if access token is set. + const isCloudRunner = + nxJson.accessToken || + nxJson.tasksRunnerOptions?.[runner]?.options?.accessToken; + + return isCloudRunner ? 'nx-cloud' : require.resolve('./default-tasks-runner'); +} + +function getRunnerOptions( + runner: string, + nxJson: NxJsonConfiguration, + nxArgs: NxArgs +): any { + const defaultCacheableOperations = []; + + for (const key in nxJson.targetDefaults) { + if (nxJson.targetDefaults[key].cache) { + defaultCacheableOperations.push(key); + } + } + + const result = { + ...nxJson.tasksRunnerOptions?.[runner]?.options, + ...nxArgs, + }; + + if (nxJson.accessToken) { + result.accessToken ??= nxJson.accessToken; + } + + if (nxJson.parallel) { + result.parallel ??= nxJson.parallel; + } + + if (nxJson.cacheDirectory) { + result.cacheDirectory ??= nxJson.cacheDirectory; + } + + if (defaultCacheableOperations.length) { + result.cacheableOperations ??= defaultCacheableOperations; + } + + if (nxJson.useDaemonProcess !== undefined) { + result.useDaemonProcess ??= nxJson.useDaemonProcess; } + + return result; } diff --git a/packages/nx/src/tasks-runner/task-orchestrator.ts b/packages/nx/src/tasks-runner/task-orchestrator.ts index 6b1c3c757576b..9aa2539ccddc5 100644 --- a/packages/nx/src/tasks-runner/task-orchestrator.ts +++ b/packages/nx/src/tasks-runner/task-orchestrator.ts @@ -282,11 +282,7 @@ export class TaskOrchestrator { try { // obtain metadata const temporaryOutputPath = this.cache.temporaryOutputPath(task); - const streamOutput = shouldStreamOutput( - task, - this.initiatingProject, - this.options - ); + const streamOutput = shouldStreamOutput(task, this.initiatingProject); const pipeOutput = await this.pipeOutputCapture(task); diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index 9ffd006f9cef2..722d9f3c8f048 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -328,11 +328,7 @@ export function getSerializedArgsForTask(task: Task, isVerbose: boolean) { export function shouldStreamOutput( task: Task, - initiatingProject: string | null, - options: { - cacheableOperations?: string[] | null; - cacheableTargets?: string[] | null; - } + initiatingProject: string | null ): boolean { if (process.env.NX_STREAM_OUTPUT === 'true') return true; if (longRunningTask(task)) return true; @@ -347,6 +343,13 @@ export function isCacheableTask( cacheableTargets?: string[] | null; } ): boolean { + if ( + task.cache !== undefined && + process.env.NX_ALLOW_PROJECT_LEVEL_CACHE === 'true' + ) { + return task.cache; + } + const cacheable = options.cacheableOperations || options.cacheableTargets; return ( cacheable && diff --git a/packages/nx/src/utils/cache-directory.ts b/packages/nx/src/utils/cache-directory.ts index a8780b8fb879a..2c9b04cb1ad00 100644 --- a/packages/nx/src/utils/cache-directory.ts +++ b/packages/nx/src/utils/cache-directory.ts @@ -7,7 +7,10 @@ import { workspaceRoot } from './workspace-root'; function readCacheDirectoryProperty(root: string): string | undefined { try { const nxJson = readJsonFile(join(root, 'nx.json')); - return nxJson.tasksRunnerOptions.default.options.cacheDirectory; + return ( + nxJson.cacheDirectory ?? + nxJson.tasksRunnerOptions.default.options.cacheDirectory + ); } catch { return undefined; } diff --git a/packages/nx/src/utils/nx-cloud-utils.ts b/packages/nx/src/utils/nx-cloud-utils.ts index 3cb4545feb90d..ded0d079992e5 100644 --- a/packages/nx/src/utils/nx-cloud-utils.ts +++ b/packages/nx/src/utils/nx-cloud-utils.ts @@ -1,19 +1,29 @@ import { readNxJson } from '../config/configuration'; -export function isNxCloudUsed() { - const nxJson = readNxJson(); - return Object.values(nxJson.tasksRunnerOptions).find( - (r) => r.runner == '@nrwl/nx-cloud' || r.runner == 'nx-cloud' +export function isNxCloudUsed(nxJson = readNxJson()) { + return ( + !!nxJson.accessToken || + Object.values(nxJson.tasksRunnerOptions ?? {}).find( + (r) => r.runner == '@nrwl/nx-cloud' || r.runner == 'nx-cloud' + ) ); } export function getNxCloudUrl(): string { const taskRunner = isNxCloudUsed(); if (!taskRunner) throw new Error('nx-cloud runner not find in nx.json'); - return taskRunner.options.url || 'https://nx.app'; + return ( + (typeof taskRunner === 'object' ? taskRunner.options.url : null) ?? + 'https://nx.app' + ); } export function getNxCloudToken(): string { - const taskRunner = isNxCloudUsed(); + const nxJson = readNxJson(); + const taskRunner = isNxCloudUsed(nxJson); + if (!taskRunner) throw new Error('nx-cloud runner not find in nx.json'); - return taskRunner.options.accessToken; + + return typeof taskRunner === 'object' + ? taskRunner.options.accessToken + : nxJson.accessToken; } From 9704f7b256741439ef4753eb3f312cbc157cbf11 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Wed, 27 Sep 2023 10:06:19 -0400 Subject: [PATCH 2/2] chore(core): misc cleanup --- docs/generated/devkit/NxJsonConfiguration.md | 28 +++++++-------- docs/generated/devkit/README.md | 1 + docs/generated/devkit/TargetConfiguration.md | 10 ------ docs/generated/devkit/TargetDefaults.md | 3 ++ docs/generated/devkit/Workspace.md | 36 +++++++++---------- .../packages/devkit/documents/nx_devkit.md | 1 + packages/nx/schemas/nx-schema.json | 16 +++++++++ .../connect/connect-to-nx-cloud.ts | 2 +- .../nx/src/command-line/connect/view-logs.ts | 3 +- .../nx/src/command-line/migrate/migrate.ts | 9 ++--- packages/nx/src/config/nx-json.ts | 19 +++++++--- .../src/config/workspace-json-project-json.ts | 6 ---- packages/nx/src/daemon/client/client.ts | 1 + packages/nx/src/devkit-exports.ts | 1 + .../nx/src/generators/utils/deprecated.ts | 4 +-- .../nx/src/tasks-runner/create-task-graph.ts | 3 +- .../life-cycles/view-logs-utils.ts | 3 +- .../nx/src/tasks-runner/run-command.spec.ts | 2 +- packages/nx/src/tasks-runner/run-command.ts | 21 +++++++---- packages/nx/src/tasks-runner/utils.ts | 3 +- packages/nx/src/utils/nx-cloud-utils.ts | 10 +++--- 21 files changed, 105 insertions(+), 77 deletions(-) create mode 100644 docs/generated/devkit/TargetDefaults.md diff --git a/docs/generated/devkit/NxJsonConfiguration.md b/docs/generated/devkit/NxJsonConfiguration.md index 9f6ead99b2256..1eb7add2993ab 100644 --- a/docs/generated/devkit/NxJsonConfiguration.md +++ b/docs/generated/devkit/NxJsonConfiguration.md @@ -18,7 +18,6 @@ Nx.json configuration ### Properties -- [accessToken](../../devkit/documents/NxJsonConfiguration#accesstoken): string - [affected](../../devkit/documents/NxJsonConfiguration#affected): NxAffectedConfig - [cacheDirectory](../../devkit/documents/NxJsonConfiguration#cachedirectory): string - [cli](../../devkit/documents/NxJsonConfiguration#cli): Object @@ -29,6 +28,7 @@ Nx.json configuration - [installation](../../devkit/documents/NxJsonConfiguration#installation): NxInstallationConfiguration - [namedInputs](../../devkit/documents/NxJsonConfiguration#namedinputs): Object - [npmScope](../../devkit/documents/NxJsonConfiguration#npmscope): string +- [nxCloudAccessToken](../../devkit/documents/NxJsonConfiguration#nxcloudaccesstoken): string - [parallel](../../devkit/documents/NxJsonConfiguration#parallel): number - [plugins](../../devkit/documents/NxJsonConfiguration#plugins): string[] - [pluginsConfig](../../devkit/documents/NxJsonConfiguration#pluginsconfig): Record<string, unknown> @@ -40,15 +40,6 @@ Nx.json configuration ## Properties -### accessToken - -• `Optional` **accessToken**: `string` - -If specified Nx will use nx-cloud by default with the given token. -To use a different runner that accepts an access token, define it in [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions) - ---- - ### affected • `Optional` **affected**: [`NxAffectedConfig`](../../devkit/documents/NxAffectedConfig) @@ -61,7 +52,7 @@ Default options for `nx affected` • `Optional` **cacheDirectory**: `string` -Changes the default location of the cache directory. +Changes the directory used by Nx to store its cache. --- @@ -169,11 +160,20 @@ NPM Scope that the workspace uses --- +### nxCloudAccessToken + +• `Optional` **nxCloudAccessToken**: `string` + +If specified Nx will use nx-cloud by default with the given token. +To use a different runner that accepts an access token, define it in [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions) + +--- + ### parallel • `Optional` **parallel**: `number` -Specifies how many tasks are ran in parallel by Nx for the default tasks runner. +Specifies how many tasks can be run in parallel. --- @@ -203,7 +203,7 @@ Configuration for Nx Plugins ### targetDefaults -• `Optional` **targetDefaults**: `TargetDefaults` +• `Optional` **targetDefaults**: [`TargetDefaults`](../../devkit/documents/TargetDefaults) Dependencies between different target names across all projects @@ -225,7 +225,7 @@ Available Task Runners • `Optional` **useDaemonProcess**: `boolean` -Allows turning the daemon off if set to false explicitly. +Set this to false to disable the daemon. --- diff --git a/docs/generated/devkit/README.md b/docs/generated/devkit/README.md index 5b189866c4e7c..9ff7a125e01a0 100644 --- a/docs/generated/devkit/README.md +++ b/docs/generated/devkit/README.md @@ -83,6 +83,7 @@ It only uses language primitives and immutable objects - [RawProjectGraphDependency](../../devkit/documents/RawProjectGraphDependency) - [StaticDependency](../../devkit/documents/StaticDependency) - [StringChange](../../devkit/documents/StringChange) +- [TargetDefaults](../../devkit/documents/TargetDefaults) - [TaskGraphExecutor](../../devkit/documents/TaskGraphExecutor) - [WorkspaceConfiguration](../../devkit/documents/WorkspaceConfiguration) - [WorkspaceJsonConfiguration](../../devkit/documents/WorkspaceJsonConfiguration) diff --git a/docs/generated/devkit/TargetConfiguration.md b/docs/generated/devkit/TargetConfiguration.md index ae0a478bdf522..251878c7850c0 100644 --- a/docs/generated/devkit/TargetConfiguration.md +++ b/docs/generated/devkit/TargetConfiguration.md @@ -12,7 +12,6 @@ Target's configuration ### Properties -- [cache](../../devkit/documents/TargetConfiguration#cache): boolean - [command](../../devkit/documents/TargetConfiguration#command): string - [configurations](../../devkit/documents/TargetConfiguration#configurations): Object - [defaultConfiguration](../../devkit/documents/TargetConfiguration#defaultconfiguration): string @@ -24,15 +23,6 @@ Target's configuration ## Properties -### cache - -• `Optional` **cache**: `boolean` - -Determines if Nx is able to cache a given target. -Currently only supported in `targetDefaults`. - ---- - ### command • `Optional` **command**: `string` diff --git a/docs/generated/devkit/TargetDefaults.md b/docs/generated/devkit/TargetDefaults.md new file mode 100644 index 0000000000000..6bb0ccfefcdc0 --- /dev/null +++ b/docs/generated/devkit/TargetDefaults.md @@ -0,0 +1,3 @@ +# Type alias: TargetDefaults + +Ƭ **TargetDefaults**: `Record`<`string`, `Partial`<[`TargetConfiguration`](../../devkit/documents/TargetConfiguration)\> & { `cache?`: `boolean` }\> diff --git a/docs/generated/devkit/Workspace.md b/docs/generated/devkit/Workspace.md index 07a89a9855165..9e8d8639c28ce 100644 --- a/docs/generated/devkit/Workspace.md +++ b/docs/generated/devkit/Workspace.md @@ -16,7 +16,6 @@ use ProjectsConfigurations or NxJsonConfiguration ### Properties -- [accessToken](../../devkit/documents/Workspace#accesstoken): string - [affected](../../devkit/documents/Workspace#affected): NxAffectedConfig - [cacheDirectory](../../devkit/documents/Workspace#cachedirectory): string - [cli](../../devkit/documents/Workspace#cli): Object @@ -27,6 +26,7 @@ use ProjectsConfigurations or NxJsonConfiguration - [installation](../../devkit/documents/Workspace#installation): NxInstallationConfiguration - [namedInputs](../../devkit/documents/Workspace#namedinputs): Object - [npmScope](../../devkit/documents/Workspace#npmscope): string +- [nxCloudAccessToken](../../devkit/documents/Workspace#nxcloudaccesstoken): string - [parallel](../../devkit/documents/Workspace#parallel): number - [plugins](../../devkit/documents/Workspace#plugins): string[] - [pluginsConfig](../../devkit/documents/Workspace#pluginsconfig): Record<string, unknown> @@ -40,19 +40,6 @@ use ProjectsConfigurations or NxJsonConfiguration ## Properties -### accessToken - -• `Optional` **accessToken**: `string` - -If specified Nx will use nx-cloud by default with the given token. -To use a different runner that accepts an access token, define it in [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions) - -#### Inherited from - -[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[accessToken](../../devkit/documents/NxJsonConfiguration#accesstoken) - ---- - ### affected • `Optional` **affected**: [`NxAffectedConfig`](../../devkit/documents/NxAffectedConfig) @@ -69,7 +56,7 @@ Default options for `nx affected` • `Optional` **cacheDirectory**: `string` -Changes the default location of the cache directory. +Changes the directory used by Nx to store its cache. #### Inherited from @@ -213,11 +200,24 @@ NPM Scope that the workspace uses --- +### nxCloudAccessToken + +• `Optional` **nxCloudAccessToken**: `string` + +If specified Nx will use nx-cloud by default with the given token. +To use a different runner that accepts an access token, define it in [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions) + +#### Inherited from + +[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[nxCloudAccessToken](../../devkit/documents/NxJsonConfiguration#nxcloudaccesstoken) + +--- + ### parallel • `Optional` **parallel**: `number` -Specifies how many tasks are ran in parallel by Nx for the default tasks runner. +Specifies how many tasks can be run in parallel. #### Inherited from @@ -275,7 +275,7 @@ Projects' projects ### targetDefaults -• `Optional` **targetDefaults**: `TargetDefaults` +• `Optional` **targetDefaults**: [`TargetDefaults`](../../devkit/documents/TargetDefaults) Dependencies between different target names across all projects @@ -305,7 +305,7 @@ Available Task Runners • `Optional` **useDaemonProcess**: `boolean` -Allows turning the daemon off if set to false explicitly. +Set this to false to disable the daemon. #### Inherited from diff --git a/docs/generated/packages/devkit/documents/nx_devkit.md b/docs/generated/packages/devkit/documents/nx_devkit.md index 5b189866c4e7c..9ff7a125e01a0 100644 --- a/docs/generated/packages/devkit/documents/nx_devkit.md +++ b/docs/generated/packages/devkit/documents/nx_devkit.md @@ -83,6 +83,7 @@ It only uses language primitives and immutable objects - [RawProjectGraphDependency](../../devkit/documents/RawProjectGraphDependency) - [StaticDependency](../../devkit/documents/StaticDependency) - [StringChange](../../devkit/documents/StringChange) +- [TargetDefaults](../../devkit/documents/TargetDefaults) - [TaskGraphExecutor](../../devkit/documents/TaskGraphExecutor) - [WorkspaceConfiguration](../../devkit/documents/WorkspaceConfiguration) - [WorkspaceJsonConfiguration](../../devkit/documents/WorkspaceJsonConfiguration) diff --git a/packages/nx/schemas/nx-schema.json b/packages/nx/schemas/nx-schema.json index 091b7d0169510..4a7cb7e3383cd 100644 --- a/packages/nx/schemas/nx-schema.json +++ b/packages/nx/schemas/nx-schema.json @@ -81,6 +81,22 @@ "defaultProject": { "type": "string", "description": "Default project. When project isn't provided, the default project will be used." + }, + "accessToken": { + "type": "string", + "description": "The access token to use for nx-cloud. If set, the default tasks runner will be nx-cloud." + }, + "parallel": { + "type": "number", + "description": "Specifies how many tasks are ran in parallel by Nx for the default tasks runner." + }, + "cacheDirectory": { + "type": "string", + "description": "Specifies the default location of the cache directory." + }, + "useDaemonProcess": { + "type": "boolean", + "description": "Specifies whether the daemon should be used for the default tasks runner." } }, "definitions": { diff --git a/packages/nx/src/command-line/connect/connect-to-nx-cloud.ts b/packages/nx/src/command-line/connect/connect-to-nx-cloud.ts index 578dd5704ad34..afb0329cbea9f 100644 --- a/packages/nx/src/command-line/connect/connect-to-nx-cloud.ts +++ b/packages/nx/src/command-line/connect/connect-to-nx-cloud.ts @@ -35,7 +35,7 @@ export async function connectToNxCloudIfExplicitlyAsked(opts: { export async function connectToNxCloudCommand( promptOverride?: string ): Promise { - if (isNxCloudUsed()) { + if (isNxCloudUsed(readNxJson())) { output.log({ title: '✅ This workspace is already connected to Nx Cloud.', bodyLines: [ diff --git a/packages/nx/src/command-line/connect/view-logs.ts b/packages/nx/src/command-line/connect/view-logs.ts index f4eda36ca691c..3fc3df8d08da9 100644 --- a/packages/nx/src/command-line/connect/view-logs.ts +++ b/packages/nx/src/command-line/connect/view-logs.ts @@ -3,9 +3,10 @@ import { execSync } from 'child_process'; import { isNxCloudUsed } from '../../utils/nx-cloud-utils'; import { output } from '../../utils/output'; import { runNxSync } from '../../utils/child-process'; +import { readNxJson } from '../../config/nx-json'; export async function viewLogs(): Promise { - const cloudUsed = isNxCloudUsed(); + const cloudUsed = isNxCloudUsed(readNxJson()); if (cloudUsed) { output.error({ title: 'Your workspace is already connected to Nx Cloud', diff --git a/packages/nx/src/command-line/migrate/migrate.ts b/packages/nx/src/command-line/migrate/migrate.ts index 57889a93ac56d..7e94a001760aa 100644 --- a/packages/nx/src/command-line/migrate/migrate.ts +++ b/packages/nx/src/command-line/migrate/migrate.ts @@ -1203,16 +1203,17 @@ async function generateMigrationsJsonAndUpdatePackageJson( let originalPackageJson = existsSync(rootPkgJsonPath) ? readJsonFile(rootPkgJsonPath) : null; - const originalNxInstallation = readNxJson().installation; + const originalNxJson = readNxJson(); const from = - originalNxInstallation?.version ?? readNxVersion(originalPackageJson); + originalNxJson.installation?.version ?? + readNxVersion(originalPackageJson); try { if ( ['nx', '@nrwl/workspace'].includes(opts.targetPackage) && (await isMigratingToNewMajor(from, opts.targetVersion)) && !isCI() && - !isNxCloudUsed() + !isNxCloudUsed(originalNxJson) ) { const useCloud = await connectToNxCloudCommand( messages.getPromptMessage('nxCloudMigration') @@ -1237,7 +1238,7 @@ async function generateMigrationsJsonAndUpdatePackageJson( const migrator = new Migrator({ packageJson: originalPackageJson, - nxInstallation: originalNxInstallation, + nxInstallation: originalNxJson.installation, getInstalledPackageVersion: createInstalledPackageVersionsResolver(root), fetch: createFetcher(), from: opts.from, diff --git a/packages/nx/src/config/nx-json.ts b/packages/nx/src/config/nx-json.ts index 0b8d9aec3754a..8df96cad87a17 100644 --- a/packages/nx/src/config/nx-json.ts +++ b/packages/nx/src/config/nx-json.ts @@ -25,7 +25,16 @@ export interface NxAffectedConfig { defaultBase?: string; } -export type TargetDefaults = Record>; +export type TargetDefaults = Record< + string, + Partial & { + /** + * Determines if Nx is able to cache a given target. + * Currently only supported in `targetDefaults`. + */ + cache?: boolean; + } +>; export type TargetDependencies = Record< string, @@ -196,20 +205,20 @@ export interface NxJsonConfiguration { * If specified Nx will use nx-cloud by default with the given token. * To use a different runner that accepts an access token, define it in {@link tasksRunnerOptions} */ - accessToken?: string; + nxCloudAccessToken?: string; /** - * Specifies how many tasks are ran in parallel by Nx for the default tasks runner. + * Specifies how many tasks can be run in parallel. */ parallel?: number; /** - * Changes the default location of the cache directory. + * Changes the directory used by Nx to store its cache. */ cacheDirectory?: string; /** - * Allows turning the daemon off if set to false explicitly. + * Set this to false to disable the daemon. */ useDaemonProcess?: boolean; } diff --git a/packages/nx/src/config/workspace-json-project-json.ts b/packages/nx/src/config/workspace-json-project-json.ts index 1466774b76993..86a2904908a1f 100644 --- a/packages/nx/src/config/workspace-json-project-json.ts +++ b/packages/nx/src/config/workspace-json-project-json.ts @@ -181,10 +181,4 @@ export interface TargetConfiguration { * A default named configuration to use when a target configuration is not provided. */ defaultConfiguration?: string; - - /** - * Determines if Nx is able to cache a given target. - * Currently only supported in `targetDefaults`. - */ - cache?: boolean; } diff --git a/packages/nx/src/daemon/client/client.ts b/packages/nx/src/daemon/client/client.ts index 778df66051a13..17d173c683a00 100644 --- a/packages/nx/src/daemon/client/client.ts +++ b/packages/nx/src/daemon/client/client.ts @@ -64,6 +64,7 @@ export class DaemonClient { enabled() { if (this._enabled === undefined) { + // TODO(v18): Add migration to move it out of existing configs and remove the ?? here. const useDaemonProcessOption = this.nxJson.useDaemonProcess ?? this.nxJson.tasksRunnerOptions?.['default']?.options?.useDaemonProcess; diff --git a/packages/nx/src/devkit-exports.ts b/packages/nx/src/devkit-exports.ts index df9b7829115a2..a14192dbc115f 100644 --- a/packages/nx/src/devkit-exports.ts +++ b/packages/nx/src/devkit-exports.ts @@ -69,6 +69,7 @@ export type { ImplicitDependencyEntry, ImplicitJsonSubsetDependency, NxJsonConfiguration, + TargetDefaults, NxAffectedConfig, } from './config/nx-json'; diff --git a/packages/nx/src/generators/utils/deprecated.ts b/packages/nx/src/generators/utils/deprecated.ts index eb363c1704bd1..0f57cbc5d1ca2 100644 --- a/packages/nx/src/generators/utils/deprecated.ts +++ b/packages/nx/src/generators/utils/deprecated.ts @@ -40,7 +40,7 @@ export function updateWorkspaceConfiguration( extends: ext, installation, release, - accessToken, + nxCloudAccessToken, cacheDirectory, parallel, useDaemonProcess, @@ -62,7 +62,7 @@ export function updateWorkspaceConfiguration( extends: ext, installation, release, - accessToken, + nxCloudAccessToken, cacheDirectory, parallel, useDaemonProcess, diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 4676730bc45dd..412bc2329f62c 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -334,7 +334,8 @@ export class ProcessTasks { target: qualifiedTarget, projectRoot: project.data.root, overrides: interpolateOverrides(overrides, project.name, project.data), - cache: project.data.targets[target].cache, + // TODO(v18): Remove cast here after typing is moved back onto TargetConfiguration + cache: (project.data.targets[target] as any).cache, }; } diff --git a/packages/nx/src/tasks-runner/life-cycles/view-logs-utils.ts b/packages/nx/src/tasks-runner/life-cycles/view-logs-utils.ts index 5c5ef847d8e6b..5ac0c5a0ef0ab 100644 --- a/packages/nx/src/tasks-runner/life-cycles/view-logs-utils.ts +++ b/packages/nx/src/tasks-runner/life-cycles/view-logs-utils.ts @@ -1,10 +1,11 @@ +import { readNxJson } from '../../config/nx-json'; import { isNxCloudUsed } from '../../utils/nx-cloud-utils'; import { output } from '../../utils/output'; const VIEW_LOGS_MESSAGE = `Hint: Try "nx view-logs" to get structured, searchable errors logs in your browser.`; export function viewLogsFooterRows(failedTasks: number) { - if (failedTasks >= 2 && !isNxCloudUsed()) { + if (failedTasks >= 2 && !isNxCloudUsed(readNxJson())) { return [``, output.dim(`${output.X_PADDING} ${VIEW_LOGS_MESSAGE}`)]; } else { return []; diff --git a/packages/nx/src/tasks-runner/run-command.spec.ts b/packages/nx/src/tasks-runner/run-command.spec.ts index 086d61a7bae6b..4ad8f025029b8 100644 --- a/packages/nx/src/tasks-runner/run-command.spec.ts +++ b/packages/nx/src/tasks-runner/run-command.spec.ts @@ -89,7 +89,7 @@ describe('getRunner', () => { const { tasksRunner } = getRunner( {}, { - accessToken: 'XXXX-XXX-XXXX', + nxCloudAccessToken: 'XXXX-XXX-XXXX', } ); diff --git a/packages/nx/src/tasks-runner/run-command.ts b/packages/nx/src/tasks-runner/run-command.ts index 1fbc629363bca..c68467fae9058 100644 --- a/packages/nx/src/tasks-runner/run-command.ts +++ b/packages/nx/src/tasks-runner/run-command.ts @@ -403,7 +403,7 @@ export function getRunner( let runner = nxArgs.runner; runner = runner || 'default'; - if (runner !== 'default' && !nxJson.tasksRunnerOptions[runner]) { + if (runner !== 'default' && !nxJson.tasksRunnerOptions?.[runner]) { throw new Error(`Could not find runner configuration for ${runner}`); } @@ -417,7 +417,12 @@ export function getRunner( return { tasksRunner, - runnerOptions: getRunnerOptions(runner, nxJson, nxArgs), + runnerOptions: getRunnerOptions( + runner, + nxJson, + nxArgs, + modulePath === 'nx-cloud' + ), }; } function getTasksRunnerPath( @@ -433,9 +438,10 @@ function getTasksRunnerPath( return modulePath; } - // No runner prop in tasks runner options, check if access token is set. const isCloudRunner = - nxJson.accessToken || + // No tasksRunnerOptions for given --runner + nxJson.nxCloudAccessToken || + // No runner prop in tasks runner options, check if access token is set. nxJson.tasksRunnerOptions?.[runner]?.options?.accessToken; return isCloudRunner ? 'nx-cloud' : require.resolve('./default-tasks-runner'); @@ -444,7 +450,8 @@ function getTasksRunnerPath( function getRunnerOptions( runner: string, nxJson: NxJsonConfiguration, - nxArgs: NxArgs + nxArgs: NxArgs, + isCloudDefault: boolean ): any { const defaultCacheableOperations = []; @@ -459,8 +466,8 @@ function getRunnerOptions( ...nxArgs, }; - if (nxJson.accessToken) { - result.accessToken ??= nxJson.accessToken; + if (nxJson.nxCloudAccessToken && isCloudDefault) { + result.accessToken ??= nxJson.nxCloudAccessToken; } if (nxJson.parallel) { diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index 722d9f3c8f048..0be79f270f7c8 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -345,7 +345,8 @@ export function isCacheableTask( ): boolean { if ( task.cache !== undefined && - process.env.NX_ALLOW_PROJECT_LEVEL_CACHE === 'true' + process.env.NX_ALLOW_PROJECT_LEVEL_CACHE === 'true' && + !longRunningTask(task) ) { return task.cache; } diff --git a/packages/nx/src/utils/nx-cloud-utils.ts b/packages/nx/src/utils/nx-cloud-utils.ts index ded0d079992e5..572a6b1eb0ce2 100644 --- a/packages/nx/src/utils/nx-cloud-utils.ts +++ b/packages/nx/src/utils/nx-cloud-utils.ts @@ -1,8 +1,8 @@ -import { readNxJson } from '../config/configuration'; +import { NxJsonConfiguration, readNxJson } from '../config/nx-json'; -export function isNxCloudUsed(nxJson = readNxJson()) { +export function isNxCloudUsed(nxJson: NxJsonConfiguration) { return ( - !!nxJson.accessToken || + !!nxJson.nxCloudAccessToken || Object.values(nxJson.tasksRunnerOptions ?? {}).find( (r) => r.runner == '@nrwl/nx-cloud' || r.runner == 'nx-cloud' ) @@ -10,7 +10,7 @@ export function isNxCloudUsed(nxJson = readNxJson()) { } export function getNxCloudUrl(): string { - const taskRunner = isNxCloudUsed(); + const taskRunner = isNxCloudUsed(readNxJson()); if (!taskRunner) throw new Error('nx-cloud runner not find in nx.json'); return ( (typeof taskRunner === 'object' ? taskRunner.options.url : null) ?? @@ -25,5 +25,5 @@ export function getNxCloudToken(): string { return typeof taskRunner === 'object' ? taskRunner.options.accessToken - : nxJson.accessToken; + : nxJson.nxCloudAccessToken; }