Skip to content

Commit

Permalink
feat(core): allow using Nx Cloud without nx-cloud installed (#19553)
Browse files Browse the repository at this point in the history
  • Loading branch information
FrozenPandaz authored Oct 13, 2023
1 parent 6857155 commit d62acec
Show file tree
Hide file tree
Showing 39 changed files with 1,040 additions and 112 deletions.
8 changes: 8 additions & 0 deletions docs/generated/cli/connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ Type: `boolean`

Show help

### interactive

Type: `boolean`

Default: `true`

Prompt for confirmation

### version

Type: `boolean`
Expand Down
17 changes: 17 additions & 0 deletions docs/generated/manifests/menus.json
Original file line number Diff line number Diff line change
Expand Up @@ -7666,6 +7666,23 @@
],
"isExternal": false,
"disableCollapsible": false
},
{
"id": "generators",
"path": "/nx-api/nx/generators",
"name": "generators",
"children": [
{
"id": "connect-to-nx-cloud",
"path": "/nx-api/nx/generators/connect-to-nx-cloud",
"name": "connect-to-nx-cloud",
"children": [],
"isExternal": false,
"disableCollapsible": false
}
],
"isExternal": false,
"disableCollapsible": false
}
],
"isExternal": false,
Expand Down
12 changes: 11 additions & 1 deletion docs/generated/manifests/nx-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -1815,7 +1815,17 @@
"type": "executor"
}
},
"generators": {},
"generators": {
"/nx-api/nx/generators/connect-to-nx-cloud": {
"description": "Connect a workspace to Nx Cloud",
"file": "generated/packages/nx/generators/connect-to-nx-cloud.json",
"hidden": false,
"name": "connect-to-nx-cloud",
"originalFilePath": "/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/schema.json",
"path": "/nx-api/nx/generators/connect-to-nx-cloud",
"type": "generator"
}
},
"path": "/nx-api/nx"
},
"playwright": {
Expand Down
12 changes: 11 additions & 1 deletion docs/generated/packages-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,17 @@
"type": "executor"
}
],
"generators": [],
"generators": [
{
"description": "Connect a workspace to Nx Cloud",
"file": "generated/packages/nx/generators/connect-to-nx-cloud.json",
"hidden": false,
"name": "connect-to-nx-cloud",
"originalFilePath": "/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/schema.json",
"path": "nx/generators/connect-to-nx-cloud",
"type": "generator"
}
],
"githubRoot": "https://github.com/nrwl/nx/blob/master",
"name": "nx",
"packageName": "nx",
Expand Down
8 changes: 8 additions & 0 deletions docs/generated/packages/nx/documents/connect-to-nx-cloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ Type: `boolean`

Show help

### interactive

Type: `boolean`

Default: `true`

Prompt for confirmation

### version

Type: `boolean`
Expand Down
34 changes: 34 additions & 0 deletions docs/generated/packages/nx/generators/connect-to-nx-cloud.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "connect-to-nx-cloud",
"factory": "./src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud",
"schema": {
"$schema": "http://json-schema.org/schema",
"id": "NxCloudInit",
"title": "Add Nx Cloud Configuration to the workspace",
"description": "Connect a workspace to Nx Cloud.",
"type": "object",
"cli": "nx",
"properties": {
"analytics": {
"type": "boolean",
"description": "Anonymously store hashed machine ID for task runs",
"default": false
},
"installationSource": {
"type": "string",
"description": "Name of Nx Cloud installation invoker (ex. user, add-nx-to-monorepo, create-nx-workspace, nx-upgrade",
"default": "user"
}
},
"additionalProperties": false,
"required": [],
"presets": []
},
"description": "Connect a workspace to Nx Cloud",
"x-hidden": true,
"implementation": "/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.ts",
"aliases": [],
"hidden": false,
"path": "/packages/nx/src/nx-cloud/generators/connect-to-nx-cloud/schema.json",
"type": "generator"
}
5 changes: 0 additions & 5 deletions docs/generated/packages/workspace/generators/new.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@
"type": "string"
},
"appName": { "type": "string", "description": "Application name." },
"nxCloud": {
"description": "Connect the workspace to the free tier of the distributed cache provided by Nx Cloud.",
"type": "boolean",
"default": false
},
"linter": {
"description": "The tool to use for running lint checks.",
"type": "string",
Expand Down
2 changes: 2 additions & 0 deletions docs/shared/reference/sitemap.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@
- [noop](/nx-api/nx/executors/noop)
- [run-commands](/nx-api/nx/executors/run-commands)
- [run-script](/nx-api/nx/executors/run-script)
- [generators](/nx-api/nx/generators)
- [connect-to-nx-cloud](/nx-api/nx/generators/connect-to-nx-cloud)
- [playwright](/nx-api/playwright)
- [documents](/nx-api/playwright/documents)
- [Overview](/nx-api/playwright/documents/overview)
Expand Down
37 changes: 37 additions & 0 deletions e2e/nx-run/src/nx-cloud.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { cleanupProject, newProject, runCLI } from '@nx/e2e/utils';

describe('Nx Cloud', () => {
beforeAll(() =>
newProject({
unsetProjectNameAndRootFormat: false,
})
);

const libName = 'test-lib';
beforeAll(() => {
runCLI('connect --no-interactive', {
env: {
...process.env,
NX_CLOUD_API: 'https://staging.nx.app',
},
});
runCLI(`generate @nx/js:lib ${libName} --no-interactive`);
});

afterAll(() => cleanupProject());

it('should cache tests', async () => {
// Should be able to view logs with Nx Cloud
expect(runCLI(`test ${libName}`)).toContain(
`View logs and investigate cache misses at https://staging.nx.app`
);

// Reset Local cache
runCLI(`reset`);

// Should be pull cache from Nx Cloud
expect(runCLI(`test ${libName}`)).toContain(
`Nx Cloud made it possible to reuse test-lib: https://staging.nx.app`
);
});
});
2 changes: 1 addition & 1 deletion packages/create-nx-workspace/src/utils/nx/nx-cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export async function setupNxCloud(
try {
const pmc = getPackageManagerCommand(packageManager);
const res = await execAndWait(
`${pmc.exec} nx g nx-cloud:init --no-analytics --installationSource=create-nx-workspace`,
`${pmc.exec} nx g nx:connect-to-nx-cloud --no-interactive --quiet`,
directory
);
nxCloudSpinner.succeed('NxCloud has been set up successfully');
Expand Down
65 changes: 65 additions & 0 deletions packages/nx/bin/nx-cloud.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/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';

const command = process.argv[2];

const options = getCloudOptions();

Promise.resolve().then(async () => invokeCommandWithNxCloudClient(options));

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 {
output.error({
title: `Unknown Command "${command}"`,
});
output.log({
title: 'Available Commands:',
bodyLines: Object.keys(nxCloudClient.commands).map((c) => `- ${c}`),
});
process.exit(1);
}
} catch (e: any) {
const body = ['Cannot run commands from the `nx-cloud` CLI.'];

if (e instanceof NxCloudEnterpriseOutdatedError) {
body.push(
'If you are an Nx Enterprise customer, please reach out to your assigned Developer Productivity Engineer.',
'If you are NOT an Nx Enterprise customer but are seeing this message, please reach out to [email protected].'
);
}

if (e instanceof NxCloudClientUnavailableError) {
body.unshift(
'You may be offline. Please try again when you are back online.'
);
}

output.error({
title: e.message,
bodyLines: body,
});
process.exit(1);
}
}
10 changes: 10 additions & 0 deletions packages/nx/generators.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"generators": {
"connect-to-nx-cloud": {
"factory": "./src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud",
"schema": "./src/nx-cloud/generators/connect-to-nx-cloud/schema.json",
"description": "Connect a workspace to Nx Cloud",
"x-hidden": true
}
}
}
2 changes: 1 addition & 1 deletion packages/nx/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
},
"17.0.0-use-minimal-config-for-tasks-runner-options": {
"cli": "nx",
"version": "17.0.0-beta.2",
"version": "17.0.0-beta.3",
"description": "Use minimal config for tasksRunnerOptions",
"implementation": "./src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options"
}
Expand Down
4 changes: 3 additions & 1 deletion packages/nx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"CLI"
],
"bin": {
"nx": "./bin/nx.js"
"nx": "./bin/nx.js",
"nx-cloud": "./bin/nx-cloud.js"
},
"author": "Victor Savkin",
"license": "MIT",
Expand Down Expand Up @@ -153,6 +154,7 @@
}
]
},
"generators": "./generators.json",
"executors": "./executors.json",
"builders": "./executors.json",
"publishConfig": {
Expand Down
19 changes: 15 additions & 4 deletions packages/nx/src/command-line/connect/command-object.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { CommandModule } from 'yargs';
import { linkToNxDevAndExamples } from '../yargs-utils/documentation';
import type { ConnectToNxCloudOptions } from './connect-to-nx-cloud';

export const yargsConnectCommand: CommandModule = {
export const yargsConnectCommand: CommandModule<{}, ConnectToNxCloudOptions> = {
command: 'connect',
aliases: ['connect-to-nx-cloud'],
describe: `Connect workspace to Nx Cloud`,
builder: (yargs) => linkToNxDevAndExamples(yargs, 'connect-to-nx-cloud'),
handler: async () => {
await (await import('./connect-to-nx-cloud')).connectToNxCloudCommand();
builder: (yargs) =>
linkToNxDevAndExamples(
yargs.option('interactive', {
type: 'boolean',
description: 'Prompt for confirmation',
default: true,
}),
'connect-to-nx-cloud'
),
handler: async (options) => {
await (
await import('./connect-to-nx-cloud')
).connectToNxCloudCommand(options);
process.exit(0);
},
};
Expand Down
30 changes: 11 additions & 19 deletions packages/nx/src/command-line/connect/connect-to-nx-cloud.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { output } from '../../utils/output';
import { getPackageManagerCommand } from '../../utils/package-manager';
import { execSync } from 'child_process';
import { readNxJson } from '../../config/configuration';
import {
getNxCloudToken,
Expand Down Expand Up @@ -48,9 +46,15 @@ export async function connectToNxCloudIfExplicitlyAsked(
}
}

export async function connectToNxCloudCommand(
promptOverride?: string
): Promise<boolean> {
export interface ConnectToNxCloudOptions {
interactive: boolean;
promptOverride?: string;
}

export async function connectToNxCloudCommand({
promptOverride,
interactive,
}: ConnectToNxCloudOptions): Promise<boolean> {
const nxJson = readNxJson();
if (isNxCloudUsed(nxJson)) {
output.log({
Expand All @@ -68,21 +72,9 @@ export async function connectToNxCloudCommand(
return false;
}

const res = await connectToNxCloudPrompt(promptOverride);
const res = interactive ? await connectToNxCloudPrompt(promptOverride) : true;
if (!res) return false;
const pmc = getPackageManagerCommand();
if (pmc) {
execSync(`${pmc.addDev} nx-cloud@latest`);
} else {
const nxJson = readNxJson();
if (nxJson.installation) {
nxJson.installation.plugins ??= {};
nxJson.installation.plugins['nx-cloud'] = execSync(
`npm view nx-cloud@latest version`
).toString();
}
}
runNxSync(`g nx-cloud:init`, {
runNxSync(`g nx:connect-to-nx-cloud --quiet --no-interactive`, {
stdio: [0, 1, 2],
});
return true;
Expand Down
Loading

1 comment on commit d62acec

@vercel
Copy link

@vercel vercel bot commented on d62acec Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-nrwl.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx.dev
nx-five.vercel.app

Please sign in to comment.