diff --git a/docs/generated/cli/reset.md b/docs/generated/cli/reset.md index ad1bf3e90755e..fef274c023160 100644 --- a/docs/generated/cli/reset.md +++ b/docs/generated/cli/reset.md @@ -55,6 +55,12 @@ Type: `boolean` Clears the Nx cache directory. This will remove all local cache entries for tasks, but will not affect the remote cache. +### onlyCloud + +Type: `boolean` + +Resets the Nx Cloud client. NOTE: Does not clear the remote cache. + ### onlyDaemon Type: `boolean` diff --git a/docs/generated/packages/nx/documents/reset.md b/docs/generated/packages/nx/documents/reset.md index ad1bf3e90755e..fef274c023160 100644 --- a/docs/generated/packages/nx/documents/reset.md +++ b/docs/generated/packages/nx/documents/reset.md @@ -55,6 +55,12 @@ Type: `boolean` Clears the Nx cache directory. This will remove all local cache entries for tasks, but will not affect the remote cache. +### onlyCloud + +Type: `boolean` + +Resets the Nx Cloud client. NOTE: Does not clear the remote cache. + ### onlyDaemon Type: `boolean` diff --git a/packages/nx/bin/nx-cloud.ts b/packages/nx/bin/nx-cloud.ts index 85b6e5154364b..08b92362a28fb 100644 --- a/packages/nx/bin/nx-cloud.ts +++ b/packages/nx/bin/nx-cloud.ts @@ -1,14 +1,16 @@ #!/usr/bin/env node -import { findAncestorNodeModules } from '../src/nx-cloud/resolution-helpers'; import { getCloudOptions } from '../src/nx-cloud/utilities/get-cloud-options'; import { NxCloudClientUnavailableError, NxCloudEnterpriseOutdatedError, - verifyOrUpdateNxCloudClient, } from '../src/nx-cloud/update-manager'; import type { CloudTaskRunnerOptions } from '../src/nx-cloud/nx-cloud-tasks-runner-shell'; import { output } from '../src/utils/output'; +import { + UnknownCommandError, + getCloudClient, +} from '../src/nx-cloud/utilities/client'; const command = process.argv[2]; @@ -16,31 +18,23 @@ const options = getCloudOptions(); Promise.resolve().then(async () => invokeCommandWithNxCloudClient(options)); -async function invokeCommandWithNxCloudClient(options: CloudTaskRunnerOptions) { +export async function invokeCommandWithNxCloudClient( + options: CloudTaskRunnerOptions +) { try { - const { nxCloudClient } = await verifyOrUpdateNxCloudClient(options); - - const paths = findAncestorNodeModules(__dirname, []); - nxCloudClient.configureLightClientRequire()(paths); - - if (command in nxCloudClient.commands) { - nxCloudClient.commands[command]() - .then(() => process.exit(0)) - .catch((e) => { - console.error(e); - process.exit(1); - }); - } else { + const client = await getCloudClient(options); + client.invoke(command); + } catch (e: any) { + if (e instanceof UnknownCommandError) { output.error({ - title: `Unknown Command "${command}"`, + title: `Unknown Command "${e.command}"`, }); output.log({ title: 'Available Commands:', - bodyLines: Object.keys(nxCloudClient.commands).map((c) => `- ${c}`), + bodyLines: e.availableCommands.map((c) => `- ${c}`), }); process.exit(1); } - } catch (e: any) { const body = ['Cannot run commands from the `nx-cloud` CLI.']; if (e instanceof NxCloudEnterpriseOutdatedError) { diff --git a/packages/nx/src/command-line/reset/command-object.ts b/packages/nx/src/command-line/reset/command-object.ts index 17decc00dd4d0..04e2871eb4ec1 100644 --- a/packages/nx/src/command-line/reset/command-object.ts +++ b/packages/nx/src/command-line/reset/command-object.ts @@ -4,6 +4,7 @@ export type ResetCommandOptions = { onlyCache?: boolean; onlyDaemon?: boolean; onlyWorkspaceData?: boolean; + onlyCloud?: boolean; }; export const yargsResetCommand: CommandModule< @@ -26,6 +27,11 @@ export const yargsResetCommand: CommandModule< 'Stops the Nx Daemon, it will be restarted fresh when the next Nx command is run.', type: 'boolean', }) + .option('onlyCloud', { + description: + 'Resets the Nx Cloud client. NOTE: Does not clear the remote cache.', + type: 'boolean', + }) .option('onlyWorkspaceData', { description: 'Clears the workspace data directory. Used by Nx to store cached data about the current workspace (e.g. partial results, incremental data, etc)', diff --git a/packages/nx/src/command-line/reset/reset.ts b/packages/nx/src/command-line/reset/reset.ts index 61dc978ad7651..3d79c31ec07a5 100644 --- a/packages/nx/src/command-line/reset/reset.ts +++ b/packages/nx/src/command-line/reset/reset.ts @@ -5,6 +5,9 @@ import { output } from '../../utils/output'; import { getNativeFileCacheLocation } from '../../native/native-file-cache-location'; import { ResetCommandOptions } from './command-object'; +import { getCloudClient } from '../../nx-cloud/utilities/client'; +import { getCloudOptions } from '../../nx-cloud/utilities/get-cloud-options'; + // Wait at max 5 seconds before giving up on a failing operation. const INCREMENTAL_BACKOFF_MAX_DURATION = 5000; @@ -62,6 +65,9 @@ export async function resetHandler(args: ResetCommandOptions) { errors.push('Failed to clean up the workspace data directory.'); } } + if (all || args.onlyCloud) { + await resetCloudClient(); + } if (errors.length > 0) { output.error({ title: 'Failed to reset the Nx workspace.', @@ -79,6 +85,14 @@ function killDaemon() { return daemonClient.stop(); } +async function resetCloudClient() { + // Remove nx cloud marker files. This helps if the use happens to run `nx-cloud start-ci-run` or + // similar commands on their local machine. + try { + (await getCloudClient(getCloudOptions())).invoke('cleanup'); + } catch {} +} + function cleanupCacheEntries() { return incrementalBackoff( INCREMENTAL_BACKOFF_FIRST_DELAY, diff --git a/packages/nx/src/nx-cloud/utilities/client.ts b/packages/nx/src/nx-cloud/utilities/client.ts new file mode 100644 index 0000000000000..09b9b3ff1164c --- /dev/null +++ b/packages/nx/src/nx-cloud/utilities/client.ts @@ -0,0 +1,35 @@ +import { findAncestorNodeModules } from '../resolution-helpers'; +import { verifyOrUpdateNxCloudClient } from '../update-manager'; +import { CloudTaskRunnerOptions } from '../nx-cloud-tasks-runner-shell'; + +export class UnknownCommandError extends Error { + constructor(public command: string, public availableCommands: string[]) { + super(`Unknown Command "${command}"`); + } +} + +export async function getCloudClient(options: CloudTaskRunnerOptions) { + const { nxCloudClient } = await verifyOrUpdateNxCloudClient(options); + + const paths = findAncestorNodeModules(__dirname, []); + nxCloudClient.configureLightClientRequire()(paths); + + return { + invoke: (command: string) => { + if (command in nxCloudClient.commands) { + nxCloudClient.commands[command]() + .then(() => process.exit(0)) + .catch((e) => { + console.error(e); + process.exit(1); + }); + } else { + throw new UnknownCommandError( + command, + Object.keys(nxCloudClient.commands) + ); + } + }, + availableCommands: Object.keys(nxCloudClient.commands), + }; +}