diff --git a/docs/generated/devkit/NxJsonConfiguration.md b/docs/generated/devkit/NxJsonConfiguration.md index 9db108e67346a..12e04783ca72b 100644 --- a/docs/generated/devkit/NxJsonConfiguration.md +++ b/docs/generated/devkit/NxJsonConfiguration.md @@ -28,6 +28,7 @@ Nx.json configuration - [implicitDependencies](../../devkit/documents/NxJsonConfiguration#implicitdependencies): ImplicitDependencyEntry - [installation](../../devkit/documents/NxJsonConfiguration#installation): NxInstallationConfiguration - [namedInputs](../../devkit/documents/NxJsonConfiguration#namedinputs): Object +- [neverConnectToCloud](../../devkit/documents/NxJsonConfiguration#neverconnecttocloud): boolean - [nxCloudAccessToken](../../devkit/documents/NxJsonConfiguration#nxcloudaccesstoken): string - [nxCloudEncryptionKey](../../devkit/documents/NxJsonConfiguration#nxcloudencryptionkey): string - [nxCloudUrl](../../devkit/documents/NxJsonConfiguration#nxcloudurl): string @@ -163,6 +164,14 @@ Named inputs targets can refer to reduce duplication --- +### neverConnectToCloud + +• `Optional` **neverConnectToCloud**: `boolean` + +Set this to false to disable connection to Nx Cloud + +--- + ### nxCloudAccessToken • `Optional` **nxCloudAccessToken**: `string` diff --git a/docs/generated/devkit/Workspace.md b/docs/generated/devkit/Workspace.md index 05c15bc3a935e..a7dd997b95d57 100644 --- a/docs/generated/devkit/Workspace.md +++ b/docs/generated/devkit/Workspace.md @@ -26,6 +26,7 @@ use ProjectsConfigurations or NxJsonConfiguration - [implicitDependencies](../../devkit/documents/Workspace#implicitdependencies): ImplicitDependencyEntry - [installation](../../devkit/documents/Workspace#installation): NxInstallationConfiguration - [namedInputs](../../devkit/documents/Workspace#namedinputs): Object +- [neverConnectToCloud](../../devkit/documents/Workspace#neverconnecttocloud): boolean - [nxCloudAccessToken](../../devkit/documents/Workspace#nxcloudaccesstoken): string - [nxCloudEncryptionKey](../../devkit/documents/Workspace#nxcloudencryptionkey): string - [nxCloudUrl](../../devkit/documents/Workspace#nxcloudurl): string @@ -203,6 +204,18 @@ Named inputs targets can refer to reduce duplication --- +### neverConnectToCloud + +• `Optional` **neverConnectToCloud**: `boolean` + +Set this to false to disable connection to Nx Cloud + +#### Inherited from + +[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[neverConnectToCloud](../../devkit/documents/NxJsonConfiguration#neverconnecttocloud) + +--- + ### nxCloudAccessToken • `Optional` **nxCloudAccessToken**: `string` diff --git a/packages/create-nx-workspace/src/create-workspace.ts b/packages/create-nx-workspace/src/create-workspace.ts index c1bc203daddd3..3d6cbf1d48192 100644 --- a/packages/create-nx-workspace/src/create-workspace.ts +++ b/packages/create-nx-workspace/src/create-workspace.ts @@ -1,6 +1,6 @@ import { CreateWorkspaceOptions } from './create-workspace-options'; import { output } from './utils/output'; -import { getOnboardingInfo, setupNxCloud } from './utils/nx/nx-cloud'; +import { getOnboardingInfo, readNxCloudToken } from './utils/nx/nx-cloud'; import { createSandbox } from './create-sandbox'; import { createEmptyWorkspace } from './create-empty-workspace'; import { createPreset } from './create-preset'; @@ -54,7 +54,7 @@ export async function createWorkspace( let connectUrl: string | undefined; let nxCloudInfo: string | undefined; if (nxCloud !== 'skip') { - const token = await setupNxCloud(directory, nxCloud, useGitHub); + const token = readNxCloudToken(directory) as string; if (nxCloud !== 'yes') { await setupCI(directory, nxCloud, packageManager); diff --git a/packages/create-nx-workspace/src/utils/nx/nx-cloud.ts b/packages/create-nx-workspace/src/utils/nx/nx-cloud.ts index 0f6703c6128ff..9018a3539952d 100644 --- a/packages/create-nx-workspace/src/utils/nx/nx-cloud.ts +++ b/packages/create-nx-workspace/src/utils/nx/nx-cloud.ts @@ -1,53 +1,23 @@ -import * as ora from 'ora'; -import { CLIOutput, output } from '../output'; -import { mapErrorToBodyLines } from '../error-utils'; +import { CLIOutput } from '../output'; import { getMessageFactory } from './messages'; +import * as ora from 'ora'; export type NxCloud = 'yes' | 'github' | 'circleci' | 'skip'; -export async function setupNxCloud( - directory: string, - nxCloud: NxCloud, - useGitHub?: boolean -) { - const nxCloudSpinner = ora(`Setting up Nx Cloud`).start(); - try { - // nx-ignore-next-line - const { connectWorkspaceToCloud } = require(require.resolve( - 'nx/src/command-line/connect/connect-to-nx-cloud', - { - paths: [directory], - } - // nx-ignore-next-line - )) as typeof import('nx/src/command-line/connect/connect-to-nx-cloud'); - - const accessToken = await connectWorkspaceToCloud( - { - installationSource: 'create-nx-workspace', - directory, - github: useGitHub, - }, - directory - ); - - nxCloudSpinner.succeed('Nx Cloud has been set up successfully'); - return accessToken; - } catch (e) { - nxCloudSpinner.fail(); - - if (e instanceof Error) { - output.error({ - title: `Failed to setup Nx Cloud`, - bodyLines: mapErrorToBodyLines(e), - }); - } else { - console.error(e); +export function readNxCloudToken(directory: string) { + const nxCloudSpinner = ora(`Checking Nx Cloud setup`).start(); + // nx-ignore-next-line + const { getCloudOptions } = require(require.resolve( + 'nx/src/nx-cloud/utilities/get-cloud-options', + { + paths: [directory], } + // nx-ignore-next-line + )) as typeof import('nx/src/nx-cloud/utilities/get-cloud-options'); - process.exit(1); - } finally { - nxCloudSpinner.stop(); - } + const { accessToken } = getCloudOptions(directory); + nxCloudSpinner.succeed('Nx Cloud has been set up successfully'); + return accessToken; } export async function getOnboardingInfo( diff --git a/packages/nx/src/adapter/compat.ts b/packages/nx/src/adapter/compat.ts index d13d3c02fddce..279fc6e47a0e4 100644 --- a/packages/nx/src/adapter/compat.ts +++ b/packages/nx/src/adapter/compat.ts @@ -77,6 +77,7 @@ export const allowedWorkspaceExtensions = [ 'cacheDirectory', 'useDaemonProcess', 'useInferencePlugins', + 'neverConnectToCloud', ] as const; if (!patched) { diff --git a/packages/nx/src/config/nx-json.ts b/packages/nx/src/config/nx-json.ts index e6980f9395847..82f8b3ff2fe36 100644 --- a/packages/nx/src/config/nx-json.ts +++ b/packages/nx/src/config/nx-json.ts @@ -445,6 +445,11 @@ export interface NxJsonConfiguration { * Set this to false to disable adding inference plugins when generating new projects */ useInferencePlugins?: boolean; + + /** + * Set this to false to disable connection to Nx Cloud + */ + neverConnectToCloud?: boolean; } export type PluginConfiguration = string | ExpandedPluginConfiguration; diff --git a/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.ts b/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.ts index 92e79918f211c..a7c9fd1876957 100644 --- a/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.ts +++ b/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.ts @@ -1,15 +1,16 @@ import { execSync } from 'child_process'; import { output } from '../../../utils/output'; import { Tree } from '../../../generators/tree'; -import { readJson } from '../../../generators/utils/json'; +import { readJson, updateJson } from '../../../generators/utils/json'; import { NxJsonConfiguration } from '../../../config/nx-json'; -import { readNxJson, updateNxJson } from '../../../generators/utils/nx-json'; +import { readNxJson } from '../../../generators/utils/nx-json'; import { formatChangedFilesWithPrettierIfAvailable } from '../../../generators/internal-utils/format-changed-files-with-prettier-if-available'; import { repoUsesGithub, createNxCloudOnboardingURL, } from '../../utilities/url-shorten'; import { getCloudUrl } from '../../utilities/get-cloud-options'; +import { join } from 'path'; function printCloudConnectionDisabledMessage() { output.error({ @@ -103,30 +104,34 @@ export interface ConnectToNxCloudOptions { function addNxCloudOptionsToNxJson( tree: Tree, - nxJson: NxJsonConfiguration, - token: string + token: string, + directory: string = tree.root ) { - nxJson ??= { - extends: 'nx/presets/npm.json', - }; - nxJson.nxCloudAccessToken = token; - const overrideUrl = process.env.NX_CLOUD_API || process.env.NRWL_API; - if (overrideUrl) { - (nxJson as any).nxCloudUrl = overrideUrl; + const nxJsonPath = join(directory, 'nx.json'); + if (tree.exists(nxJsonPath)) { + updateJson( + tree, + join(directory, 'nx.json'), + (nxJson) => { + const overrideUrl = process.env.NX_CLOUD_API || process.env.NRWL_API; + if (overrideUrl) { + nxJson.nxCloudUrl = overrideUrl; + } + nxJson.nxCloudAccessToken = token; + + return nxJson; + } + ); } - updateNxJson(tree, nxJson); } export async function connectToNxCloud( tree: Tree, - schema: ConnectToNxCloudOptions + schema: ConnectToNxCloudOptions, + nxJson = readNxJson(tree) ): Promise { schema.installationSource ??= 'user'; - const nxJson = readNxJson(tree) as - | null - | (NxJsonConfiguration & { neverConnectToCloud: boolean }); - if (nxJson?.neverConnectToCloud) { printCloudConnectionDisabledMessage(); return null; @@ -150,8 +155,8 @@ export async function connectToNxCloud( addNxCloudOptionsToNxJson( tree, - nxJson, - responseFromCreateNxCloudWorkspace?.token + responseFromCreateNxCloudWorkspace?.token, + schema.directory ); await formatChangedFilesWithPrettierIfAvailable(tree, { diff --git a/packages/nx/src/nx-cloud/utilities/get-cloud-options.ts b/packages/nx/src/nx-cloud/utilities/get-cloud-options.ts index 6bca82e6af38e..3847c2a324e67 100644 --- a/packages/nx/src/nx-cloud/utilities/get-cloud-options.ts +++ b/packages/nx/src/nx-cloud/utilities/get-cloud-options.ts @@ -1,9 +1,12 @@ import { CloudTaskRunnerOptions } from '../nx-cloud-tasks-runner-shell'; import { readNxJson } from '../../config/nx-json'; import { getRunnerOptions } from '../../tasks-runner/run-command'; +import { workspaceRoot } from '../../utils/workspace-root'; -export function getCloudOptions(): CloudTaskRunnerOptions { - const nxJson = readNxJson(); +export function getCloudOptions( + directory = workspaceRoot +): CloudTaskRunnerOptions { + const nxJson = readNxJson(directory); // TODO: The default is not always cloud? But it's not handled at the moment return getRunnerOptions('default', nxJson, {}, true); diff --git a/packages/workspace/src/generators/new/generate-workspace-files.ts b/packages/workspace/src/generators/new/generate-workspace-files.ts index 566fa4a7d471b..e3ef6de778751 100644 --- a/packages/workspace/src/generators/new/generate-workspace-files.ts +++ b/packages/workspace/src/generators/new/generate-workspace-files.ts @@ -1,5 +1,4 @@ import { - formatFiles, generateFiles, getPackageManagerVersion, names, @@ -14,6 +13,7 @@ import { join } from 'path'; import { Preset } from '../utils/presets'; import { deduceDefaultBase } from '../../utilities/default-base'; import { NormalizedSchema } from './new'; +import { connectToNxCloud } from 'nx/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud'; export async function generateWorkspaceFiles( tree: Tree, @@ -31,7 +31,20 @@ export async function generateWorkspaceFiles( options = normalizeOptions(options); createReadme(tree, options); createFiles(tree, options); - createNxJson(tree, options); + const nxJson = createNxJson(tree, options); + + const token = + options.nxCloud !== 'skip' + ? await connectToNxCloud( + tree, + { + installationSource: 'create-nx-workspace', + directory: options.directory, + github: options.useGitHub, + }, + nxJson + ) + : null; const [packageMajor] = packageManagerVersion.split('.'); if (options.packageManager === 'pnpm' && +packageMajor >= 7) { @@ -47,7 +60,7 @@ export async function generateWorkspaceFiles( addNpmScripts(tree, options); setUpWorkspacesInPackageJson(tree, options); - await formatFiles(tree); + return token; } function setPresetProperty(tree: Tree, options: NormalizedSchema) { @@ -96,6 +109,8 @@ function createNxJson( } writeJson(tree, join(directory, 'nx.json'), nxJson); + + return nxJson; } function createFiles(tree: Tree, options: NormalizedSchema) { @@ -217,6 +232,7 @@ function normalizeOptions(options: NormalizedSchema) { name, ...options, defaultBase, + nxCloud: options.nxCloud ?? 'skip', }; } diff --git a/packages/workspace/src/generators/new/new.ts b/packages/workspace/src/generators/new/new.ts index 9200d4a965248..51b722625a74b 100644 --- a/packages/workspace/src/generators/new/new.ts +++ b/packages/workspace/src/generators/new/new.ts @@ -1,4 +1,5 @@ import { + formatFiles, getPackageManagerCommand, installPackagesTask, joinPathFragments, @@ -34,6 +35,8 @@ interface Schema { e2eTestRunner?: 'cypress' | 'playwright' | 'detox' | 'jest' | 'none'; ssr?: boolean; prefix?: string; + useGitHub?: boolean; + nxCloud?: 'yes' | 'skip' | 'circleci' | 'github'; } export interface NormalizedSchema extends Schema { @@ -49,6 +52,8 @@ export async function newGenerator(tree: Tree, opts: Schema) { addPresetDependencies(tree, options); + await formatFiles(tree); + return async () => { if (!options.skipInstall) { const pmc = getPackageManagerCommand(options.packageManager);