feat(misc): add onboarding a/b testing (#27217)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> The onboarding message during `create-nx-workspace` is not ideal. ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> We are A/b testing some options for the `create-nx-workspace` onboarding message. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
66a8c75f87
commit
341f2951a8
@ -20,7 +20,6 @@ import { output } from 'create-nx-workspace/src/utils/output';
|
||||
import { NxCloud } from 'create-nx-workspace/src/utils/nx/nx-cloud';
|
||||
import type { PackageManager } from 'create-nx-workspace/src/utils/package-manager';
|
||||
import { showNxWarning } from 'create-nx-workspace/src/utils/nx/show-nx-warning';
|
||||
import { printNxCloudSuccessMessage } from 'create-nx-workspace/src/utils/nx/nx-cloud';
|
||||
import {
|
||||
messages,
|
||||
recordStat,
|
||||
@ -164,7 +163,7 @@ async function main(parsedArgs: yargs.Arguments<CreateNxPluginArguments>) {
|
||||
});
|
||||
|
||||
if (parsedArgs.nxCloud && workspaceInfo.nxCloudInfo) {
|
||||
printNxCloudSuccessMessage(workspaceInfo.nxCloudInfo);
|
||||
console.log(workspaceInfo.nxCloudInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,6 @@ import {
|
||||
withPackageManager,
|
||||
} from '../src/internal-utils/yargs-options';
|
||||
import { showNxWarning } from '../src/utils/nx/show-nx-warning';
|
||||
import { printNxCloudSuccessMessage } from '../src/utils/nx/nx-cloud';
|
||||
import { messages, recordStat } from '../src/utils/nx/ab-testing';
|
||||
import { mapErrorToBodyLines } from '../src/utils/error-utils';
|
||||
import { existsSync } from 'fs';
|
||||
@ -233,7 +232,7 @@ async function main(parsedArgs: yargs.Arguments<Arguments>) {
|
||||
});
|
||||
|
||||
if (parsedArgs.nxCloud && workspaceInfo.nxCloudInfo) {
|
||||
printNxCloudSuccessMessage(workspaceInfo.nxCloudInfo);
|
||||
console.log(workspaceInfo.nxCloudInfo);
|
||||
}
|
||||
|
||||
if (isKnownPreset(parsedArgs.preset)) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { CreateWorkspaceOptions } from './create-workspace-options';
|
||||
import { output } from './utils/output';
|
||||
import { setupNxCloud } from './utils/nx/nx-cloud';
|
||||
import { getOnboardingInfo, setupNxCloud } from './utils/nx/nx-cloud';
|
||||
import { createSandbox } from './create-sandbox';
|
||||
import { createEmptyWorkspace } from './create-empty-workspace';
|
||||
import { createPreset } from './create-preset';
|
||||
@ -51,31 +51,27 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
|
||||
);
|
||||
}
|
||||
|
||||
let nxCloudInstallRes;
|
||||
let connectUrl: string | undefined;
|
||||
let nxCloudInfo: string | undefined;
|
||||
if (nxCloud !== 'skip') {
|
||||
nxCloudInstallRes = await setupNxCloud(
|
||||
directory,
|
||||
packageManager,
|
||||
nxCloud,
|
||||
useGitHub
|
||||
);
|
||||
const token = await setupNxCloud(directory, nxCloud, useGitHub);
|
||||
|
||||
if (nxCloud !== 'yes') {
|
||||
await setupCI(
|
||||
directory,
|
||||
nxCloud,
|
||||
packageManager,
|
||||
nxCloudInstallRes?.code === 0
|
||||
);
|
||||
await setupCI(directory, nxCloud, packageManager);
|
||||
}
|
||||
|
||||
const { connectCloudUrl, output } = await getOnboardingInfo(
|
||||
nxCloud,
|
||||
token,
|
||||
directory,
|
||||
useGitHub
|
||||
);
|
||||
connectUrl = connectCloudUrl;
|
||||
nxCloudInfo = output;
|
||||
}
|
||||
|
||||
if (!skipGit) {
|
||||
try {
|
||||
let connectUrl;
|
||||
if (nxCloudInstallRes?.code === 0) {
|
||||
connectUrl = extractConnectUrl(nxCloudInstallRes?.stdout);
|
||||
}
|
||||
await initializeGitRepo(directory, { defaultBase, commit, connectUrl });
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
@ -90,7 +86,7 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
|
||||
}
|
||||
|
||||
return {
|
||||
nxCloudInfo: nxCloudInstallRes?.stdout,
|
||||
nxCloudInfo,
|
||||
directory,
|
||||
};
|
||||
}
|
||||
|
||||
@ -8,18 +8,8 @@ import { getPackageManagerCommand, PackageManager } from '../package-manager';
|
||||
export async function setupCI(
|
||||
directory: string,
|
||||
ci: string,
|
||||
packageManager: PackageManager,
|
||||
nxCloudSuccessfullyInstalled: boolean
|
||||
packageManager: PackageManager
|
||||
) {
|
||||
if (!nxCloudSuccessfullyInstalled) {
|
||||
output.error({
|
||||
title: `CI workflow generation skipped`,
|
||||
bodyLines: [
|
||||
`Nx Cloud was not installed`,
|
||||
`The autogenerated CI workflow requires Nx Cloud to be set-up.`,
|
||||
],
|
||||
});
|
||||
}
|
||||
const ciSpinner = ora(`Generating CI workflow`).start();
|
||||
try {
|
||||
const pmc = getPackageManagerCommand(packageManager);
|
||||
|
||||
185
packages/create-nx-workspace/src/utils/nx/messages.ts
Normal file
185
packages/create-nx-workspace/src/utils/nx/messages.ts
Normal file
@ -0,0 +1,185 @@
|
||||
const outputMessages = {
|
||||
'create-nx-workspace-success-ci-setup': [
|
||||
{
|
||||
code: 'nx-cloud-workspace-push-goto',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your Nx Cloud workspace is ready.`,
|
||||
type: 'success',
|
||||
bodyLines: [
|
||||
`To claim it, connect it to your Nx Cloud account:`,
|
||||
`- Push your repository to your git hosting provider.`,
|
||||
`- Go to the following URL to connect your workspace to Nx Cloud:`,
|
||||
'',
|
||||
`${url}`,
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-powered-ci-setup-visit',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup powered by Nx Cloud is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-powered-ci-setup-connect',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup powered by Nx Cloud is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'ci-setup-visit',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'ci-setup-connect',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-powered-ci-setup-visit-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup powered by Nx Cloud is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-powered-ci-setup-connect-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup powered by Nx Cloud is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'ci-setup-visit-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'ci-setup-connect-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your CI setup is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
],
|
||||
'create-nx-workspace-success-cache-setup': [
|
||||
{
|
||||
code: 'nx-cloud-workspace-push-goto',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your Nx Cloud workspace is ready.`,
|
||||
type: 'success',
|
||||
bodyLines: [
|
||||
`To claim it, connect it to your Nx Cloud account:`,
|
||||
`- Push your repository to your git hosting provider.`,
|
||||
`- Go to the following URL to connect your workspace to Nx Cloud:`,
|
||||
'',
|
||||
`${url}`,
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-remote-cache-setup-finish',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your Nx Cloud remote cache setup is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-remote-cache-setup-connect',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your Nx Cloud remote cache setup is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'remote-cache-visit',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your remote cache setup is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'remote-cache-connect',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your remote cache setup is almost complete.`,
|
||||
type: 'success',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-remote-cache-setup-visit-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your Nx Cloud remote cache setup is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'nx-cloud-remote-cache-setup-connect-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your Nx Cloud remote cache setup is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'remote-cache-visit-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your remote cache setup is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Finish it by visiting: ${url}`],
|
||||
}),
|
||||
},
|
||||
{
|
||||
code: 'remote-cache-connect-warn',
|
||||
createMessage: (url: string) => ({
|
||||
title: `Your remote cache setup is almost complete.`,
|
||||
type: 'warning',
|
||||
bodyLines: [`Connect your repository: ${url}`],
|
||||
}),
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
type OutputMessageKey = keyof typeof outputMessages;
|
||||
|
||||
class ABTestingMessages {
|
||||
private selectedMessages: Record<string, number> = {};
|
||||
getMessageFactory(key: OutputMessageKey) {
|
||||
if (this.selectedMessages[key] === undefined) {
|
||||
if (process.env.NX_GENERATE_DOCS_PROCESS === 'true') {
|
||||
this.selectedMessages[key] = 0;
|
||||
} else {
|
||||
this.selectedMessages[key] = Math.floor(
|
||||
Math.random() * outputMessages[key].length
|
||||
);
|
||||
}
|
||||
}
|
||||
return outputMessages[key][this.selectedMessages[key]!];
|
||||
}
|
||||
}
|
||||
|
||||
const messages = new ABTestingMessages();
|
||||
|
||||
export function getMessageFactory(key: OutputMessageKey) {
|
||||
return messages.getMessageFactory(key);
|
||||
}
|
||||
@ -1,37 +1,34 @@
|
||||
import * as ora from 'ora';
|
||||
import { execAndWait } from '../child-process-utils';
|
||||
import { output } from '../output';
|
||||
import { getPackageManagerCommand, PackageManager } from '../package-manager';
|
||||
import { CLIOutput, output } from '../output';
|
||||
import { mapErrorToBodyLines } from '../error-utils';
|
||||
import { getMessageFactory } from './messages';
|
||||
|
||||
export type NxCloud = 'yes' | 'github' | 'circleci' | 'skip';
|
||||
|
||||
export async function setupNxCloud(
|
||||
directory: string,
|
||||
packageManager: PackageManager,
|
||||
nxCloud: NxCloud,
|
||||
useGitHub?: boolean
|
||||
) {
|
||||
const nxCloudSpinner = ora(`Setting up Nx Cloud`).start();
|
||||
try {
|
||||
const pmc = getPackageManagerCommand(packageManager);
|
||||
const res = await execAndWait(
|
||||
`${
|
||||
pmc.exec
|
||||
} nx g nx:connect-to-nx-cloud --installationSource=create-nx-workspace --directory=${directory} ${
|
||||
useGitHub ? '--github' : ''
|
||||
} --no-interactive`,
|
||||
directory
|
||||
);
|
||||
// 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');
|
||||
|
||||
if (nxCloud !== 'yes') {
|
||||
nxCloudSpinner.succeed(
|
||||
'CI workflow with Nx Cloud has been generated successfully'
|
||||
);
|
||||
} else {
|
||||
nxCloudSpinner.succeed('Nx Cloud has been set up successfully');
|
||||
}
|
||||
return res;
|
||||
const accessToken = await connectWorkspaceToCloud({
|
||||
installationSource: 'create-nx-workspace',
|
||||
directory,
|
||||
github: useGitHub,
|
||||
});
|
||||
|
||||
nxCloudSpinner.succeed('Nx Cloud has been set up successfully');
|
||||
return accessToken;
|
||||
} catch (e) {
|
||||
nxCloudSpinner.fail();
|
||||
|
||||
@ -50,19 +47,39 @@ export async function setupNxCloud(
|
||||
}
|
||||
}
|
||||
|
||||
export function printNxCloudSuccessMessage(nxCloudOut: string) {
|
||||
// remove leading Nx carret and any new lines
|
||||
const logContent = nxCloudOut.split('NX ')[1];
|
||||
const indexOfTitleEnd = logContent.indexOf('\n');
|
||||
const title = logContent.slice(0, logContent.indexOf('\n')).trim();
|
||||
const bodyLines = logContent
|
||||
.slice(indexOfTitleEnd)
|
||||
.replace(/^\n*/, '') // remove leading new lines
|
||||
.replace(/\n*$/, '') // remove trailing new lines
|
||||
.split('\n')
|
||||
.map((r) => r.trim());
|
||||
output.warn({
|
||||
title,
|
||||
bodyLines,
|
||||
});
|
||||
export async function getOnboardingInfo(
|
||||
nxCloud: NxCloud,
|
||||
token: string,
|
||||
directory: string,
|
||||
useGithub?: boolean
|
||||
) {
|
||||
// nx-ignore-next-line
|
||||
const { createNxCloudOnboardingURL } = require(require.resolve(
|
||||
'nx/src/nx-cloud/utilities/url-shorten',
|
||||
{
|
||||
paths: [directory],
|
||||
}
|
||||
// nx-ignore-next-line
|
||||
)) as typeof import('nx/src/nx-cloud/utilities/url-shorten');
|
||||
|
||||
const source =
|
||||
nxCloud === 'yes'
|
||||
? 'create-nx-workspace-success-cache-setup'
|
||||
: 'create-nx-workspace-success-ci-setup';
|
||||
const { code, createMessage } = getMessageFactory(source);
|
||||
const connectCloudUrl = await createNxCloudOnboardingURL(
|
||||
source,
|
||||
token,
|
||||
useGithub ??
|
||||
(nxCloud === 'yes' || nxCloud === 'github' || nxCloud === 'circleci'),
|
||||
code
|
||||
);
|
||||
const out = new CLIOutput(false);
|
||||
const message = createMessage(connectCloudUrl);
|
||||
if (message.type === 'success') {
|
||||
out.success(message);
|
||||
} else {
|
||||
out.warn(message);
|
||||
}
|
||||
return { output: out.getOutput(), connectCloudUrl };
|
||||
}
|
||||
|
||||
@ -34,7 +34,9 @@ if (isCI()) {
|
||||
(chalk as any).level = 0;
|
||||
}
|
||||
|
||||
class CLIOutput {
|
||||
export class CLIOutput {
|
||||
private outstream = this.real ? process.stdout : new FakeStdout();
|
||||
constructor(private real = true) {}
|
||||
/**
|
||||
* Longer dash character which forms more of a continuous line when place side to side
|
||||
* with itself, unlike the standard dash character
|
||||
@ -64,7 +66,7 @@ class CLIOutput {
|
||||
dim = chalk.dim;
|
||||
|
||||
private writeToStdOut(str: string) {
|
||||
process.stdout.write(str);
|
||||
this.outstream.write(str);
|
||||
}
|
||||
|
||||
private writeOutputTitle({
|
||||
@ -192,6 +194,21 @@ class CLIOutput {
|
||||
|
||||
this.addNewline();
|
||||
}
|
||||
|
||||
getOutput() {
|
||||
return this.outstream.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export const output = new CLIOutput();
|
||||
|
||||
class FakeStdout {
|
||||
private content = '';
|
||||
write(str: string) {
|
||||
this.content += str;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.content;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import { output } from '../../utils/output';
|
||||
import { readNxJson } from '../../config/configuration';
|
||||
import { FsTree, flushChanges } from '../../generators/tree';
|
||||
import { connectToNxCloud } from '../../nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud';
|
||||
import { shortenedCloudUrl } from '../../nx-cloud/utilities/url-shorten';
|
||||
import {
|
||||
connectToNxCloud,
|
||||
ConnectToNxCloudOptions,
|
||||
} from '../../nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud';
|
||||
import { createNxCloudOnboardingURL } from '../../nx-cloud/utilities/url-shorten';
|
||||
import { isNxCloudUsed } from '../../utils/nx-cloud-utils';
|
||||
import { runNxSync } from '../../utils/child-process';
|
||||
import { NxJsonConfiguration } from '../../config/nx-json';
|
||||
@ -16,6 +19,8 @@ import {
|
||||
import { nxVersion } from '../../utils/versions';
|
||||
import { workspaceRoot } from '../../utils/workspace-root';
|
||||
import chalk = require('chalk');
|
||||
import * as ora from 'ora';
|
||||
import * as open from 'open';
|
||||
|
||||
export function onlyDefaultRunnerIsUsed(nxJson: NxJsonConfiguration) {
|
||||
const defaultRunner = nxJson.tasksRunnerOptions?.default?.runner;
|
||||
@ -50,6 +55,16 @@ export async function connectToNxCloudIfExplicitlyAsked(
|
||||
}
|
||||
}
|
||||
|
||||
export async function connectWorkspaceToCloud(
|
||||
options: ConnectToNxCloudOptions
|
||||
) {
|
||||
const tree = new FsTree(workspaceRoot, false, 'connect-to-nx-cloud');
|
||||
const accessToken = await connectToNxCloud(tree, options);
|
||||
tree.lock();
|
||||
flushChanges(workspaceRoot, tree.listChanges());
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
export async function connectToNxCloudCommand(
|
||||
command?: string
|
||||
): Promise<boolean> {
|
||||
@ -63,7 +78,10 @@ export async function connectToNxCloudCommand(
|
||||
`Unable to authenticate. Either define accessToken in nx.json or set the NX_CLOUD_ACCESS_TOKEN env variable.`
|
||||
);
|
||||
}
|
||||
const connectCloudUrl = await shortenedCloudUrl('nx-connect', token);
|
||||
const connectCloudUrl = await createNxCloudOnboardingURL(
|
||||
'nx-connect',
|
||||
token
|
||||
);
|
||||
output.log({
|
||||
title: '✔ This workspace already has Nx Cloud set up',
|
||||
bodyLines: [
|
||||
@ -76,18 +94,37 @@ export async function connectToNxCloudCommand(
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const tree = new FsTree(workspaceRoot, false, 'connect-to-nx-cloud');
|
||||
const callback = await connectToNxCloud(tree, {
|
||||
const token = await connectWorkspaceToCloud({
|
||||
installationSource: command ?? 'nx-connect',
|
||||
});
|
||||
tree.lock();
|
||||
flushChanges(workspaceRoot, tree.listChanges());
|
||||
await callback();
|
||||
|
||||
const connectCloudUrl = await createNxCloudOnboardingURL('nx-connect', token);
|
||||
try {
|
||||
const cloudConnectSpinner = ora(
|
||||
`Opening Nx Cloud ${connectCloudUrl} in your browser to connect your workspace.`
|
||||
).start();
|
||||
await sleep(2000);
|
||||
await open(connectCloudUrl);
|
||||
cloudConnectSpinner.succeed();
|
||||
} catch (e) {
|
||||
output.note({
|
||||
title: `Your Nx Cloud workspace is ready.`,
|
||||
bodyLines: [
|
||||
`To claim it, connect it to your Nx Cloud account:`,
|
||||
`- Go to the following URL to connect your workspace to Nx Cloud:`,
|
||||
'',
|
||||
`${connectCloudUrl}`,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export async function connectExistingRepoToNxCloudPrompt(
|
||||
command = 'init',
|
||||
key: MessageKey = 'setupNxCloud'
|
||||
|
||||
@ -2,9 +2,13 @@ import { getPackageManagerCommand } from '../../utils/package-manager';
|
||||
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';
|
||||
import { connectExistingRepoToNxCloudPrompt } from './connect-to-nx-cloud';
|
||||
import {
|
||||
connectExistingRepoToNxCloudPrompt,
|
||||
connectWorkspaceToCloud,
|
||||
} from './connect-to-nx-cloud';
|
||||
import { printSuccessMessage } from '../../nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud';
|
||||
import { repoUsesGithub } from '../../nx-cloud/utilities/url-shorten';
|
||||
|
||||
export async function viewLogs(): Promise<number> {
|
||||
const cloudUsed = isNxCloudUsed(readNxJson());
|
||||
@ -30,12 +34,11 @@ export async function viewLogs(): Promise<number> {
|
||||
output.log({
|
||||
title: 'Connecting to Nx Cloud',
|
||||
});
|
||||
runNxSync(
|
||||
`g nx:connect-to-nx-cloud --installation-source=view-logs --quiet --no-interactive`,
|
||||
{
|
||||
stdio: 'ignore',
|
||||
}
|
||||
);
|
||||
const token = await connectWorkspaceToCloud({
|
||||
installationSource: 'view-logs',
|
||||
});
|
||||
|
||||
await printSuccessMessage(token, 'view-logs', await repoUsesGithub());
|
||||
} catch (e) {
|
||||
output.log({
|
||||
title: 'Failed to connect to Nx Cloud',
|
||||
|
||||
@ -108,7 +108,7 @@ export async function addNxToMonorepo(options: Options) {
|
||||
|
||||
if (useNxCloud) {
|
||||
output.log({ title: '🛠️ Setting up Nx Cloud' });
|
||||
initCloud(repoRoot, 'nx-init-monorepo');
|
||||
await initCloud('nx-init-monorepo');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -140,7 +140,7 @@ export async function addNxToNest(options: Options, packageJson: PackageJson) {
|
||||
|
||||
if (useNxCloud) {
|
||||
output.log({ title: '🛠️ Setting up Nx Cloud' });
|
||||
initCloud(repoRoot, 'nx-init-nest');
|
||||
await initCloud('nx-init-nest');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -97,6 +97,6 @@ export async function addNxToNpmRepo(options: Options) {
|
||||
|
||||
if (useNxCloud) {
|
||||
output.log({ title: '🛠️ Setting up Nx Cloud' });
|
||||
initCloud(repoRoot, 'nx-init-npm-repo');
|
||||
await initCloud('nx-init-npm-repo');
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ export async function addNxToAngularCliRepo(options: Options) {
|
||||
|
||||
if (useNxCloud) {
|
||||
output.log({ title: '🛠️ Setting up Nx Cloud' });
|
||||
initCloud(repoRoot, 'nx-init-angular');
|
||||
await initCloud('nx-init-angular');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -110,7 +110,7 @@ export async function getLegacyMigrationFunctionIfApplicable(
|
||||
|
||||
if (useNxCloud) {
|
||||
output.log({ title: '🛠️ Setting up Nx Cloud' });
|
||||
initCloud(repoRoot, 'nx-init-angular');
|
||||
await initCloud('nx-init-angular');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import { execSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
|
||||
import { NxJsonConfiguration } from '../../../config/nx-json';
|
||||
import { runNxSync } from '../../../utils/child-process';
|
||||
import {
|
||||
fileExists,
|
||||
readJsonFile,
|
||||
@ -17,6 +16,9 @@ import {
|
||||
import { joinPathFragments } from '../../../utils/path';
|
||||
import { nxVersion } from '../../../utils/versions';
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||
import { printSuccessMessage } from '../../../nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud';
|
||||
import { repoUsesGithub } from '../../../nx-cloud/utilities/url-shorten';
|
||||
import { connectWorkspaceToCloud } from '../../connect/connect-to-nx-cloud';
|
||||
|
||||
export function createNxJsonFile(
|
||||
repoRoot: string,
|
||||
@ -141,22 +143,19 @@ export function runInstall(
|
||||
execSync(pmc.install, { stdio: [0, 1, 2], cwd: repoRoot });
|
||||
}
|
||||
|
||||
export function initCloud(
|
||||
repoRoot: string,
|
||||
export async function initCloud(
|
||||
installationSource:
|
||||
| 'nx-init'
|
||||
| 'nx-init-angular'
|
||||
| 'nx-init-cra'
|
||||
| 'nx-init-monorepo'
|
||||
| 'nx-init-nest'
|
||||
| 'nx-init-npm-repo'
|
||||
) {
|
||||
runNxSync(
|
||||
`g nx:connect-to-nx-cloud --installationSource=${installationSource} --quiet --no-interactive`,
|
||||
{
|
||||
stdio: [0, 1, 2],
|
||||
cwd: repoRoot,
|
||||
}
|
||||
);
|
||||
const token = await connectWorkspaceToCloud({
|
||||
installationSource,
|
||||
});
|
||||
await printSuccessMessage(token, installationSource, await repoUsesGithub());
|
||||
}
|
||||
|
||||
export function addVsCodeRecommendedExtensions(
|
||||
|
||||
@ -10,6 +10,7 @@ import { nxVersion } from '../../utils/versions';
|
||||
import {
|
||||
addDepsToPackageJson,
|
||||
createNxJsonFile,
|
||||
initCloud,
|
||||
isMonorepo,
|
||||
printFinalMessage,
|
||||
runInstall,
|
||||
@ -126,13 +127,7 @@ export async function initHandler(options: InitArgs): Promise<void> {
|
||||
|
||||
if (useNxCloud) {
|
||||
output.log({ title: '🛠️ Setting up Nx Cloud' });
|
||||
execSync(
|
||||
`${pmc.exec} nx g nx:connect-to-nx-cloud --installationSource=nx-init --quiet --hideFormatLogs --no-interactive`,
|
||||
{
|
||||
stdio: [0, 1, 2],
|
||||
cwd: repoRoot,
|
||||
}
|
||||
);
|
||||
await initCloud('nx-init');
|
||||
}
|
||||
|
||||
printFinalMessage({
|
||||
|
||||
@ -5,10 +5,11 @@ import { readJson } from '../../../generators/utils/json';
|
||||
import { NxJsonConfiguration } from '../../../config/nx-json';
|
||||
import { readNxJson, updateNxJson } from '../../../generators/utils/nx-json';
|
||||
import { formatChangedFilesWithPrettierIfAvailable } from '../../../generators/internal-utils/format-changed-files-with-prettier-if-available';
|
||||
import { repoUsesGithub, shortenedCloudUrl } from '../../utilities/url-shorten';
|
||||
import {
|
||||
repoUsesGithub,
|
||||
createNxCloudOnboardingURL,
|
||||
} from '../../utilities/url-shorten';
|
||||
import { getCloudUrl } from '../../utilities/get-cloud-options';
|
||||
import * as ora from 'ora';
|
||||
import * as open from 'open';
|
||||
|
||||
function printCloudConnectionDisabledMessage() {
|
||||
output.error({
|
||||
@ -68,65 +69,31 @@ async function createNxCloudWorkspace(
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function printSuccessMessage(
|
||||
export async function printSuccessMessage(
|
||||
token: string | undefined,
|
||||
installationSource: string,
|
||||
usesGithub: boolean
|
||||
) {
|
||||
const connectCloudUrl = await shortenedCloudUrl(
|
||||
const connectCloudUrl = await createNxCloudOnboardingURL(
|
||||
installationSource,
|
||||
token,
|
||||
usesGithub
|
||||
);
|
||||
|
||||
if (installationSource === 'nx-connect' && usesGithub) {
|
||||
try {
|
||||
const cloudConnectSpinner = ora(
|
||||
`Opening Nx Cloud ${connectCloudUrl} in your browser to connect your workspace.`
|
||||
).start();
|
||||
await sleep(2000);
|
||||
open(connectCloudUrl);
|
||||
cloudConnectSpinner.succeed();
|
||||
} catch (e) {
|
||||
output.note({
|
||||
title: `Your Nx Cloud workspace is ready.`,
|
||||
bodyLines: [
|
||||
`To claim it, connect it to your Nx Cloud account:`,
|
||||
`- Go to the following URL to connect your workspace to Nx Cloud:`,
|
||||
'',
|
||||
`${connectCloudUrl}`,
|
||||
],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (installationSource === 'create-nx-workspace') {
|
||||
output.note({
|
||||
title: `Your Nx Cloud workspace is ready.`,
|
||||
bodyLines: [
|
||||
`To claim it, connect it to your Nx Cloud account:`,
|
||||
`- Push your repository to your git hosting provider.`,
|
||||
`- Go to the following URL to connect your workspace to Nx Cloud:`,
|
||||
'',
|
||||
`${connectCloudUrl}`,
|
||||
],
|
||||
});
|
||||
} else {
|
||||
output.note({
|
||||
title: `Your Nx Cloud workspace is ready.`,
|
||||
bodyLines: [
|
||||
`To claim it, connect it to your Nx Cloud account:`,
|
||||
`- Commit and push your changes.`,
|
||||
`- Create a pull request for the changes.`,
|
||||
`- Go to the following URL to connect your workspace to Nx Cloud:`,
|
||||
'',
|
||||
`${connectCloudUrl}`,
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
output.note({
|
||||
title: `Your Nx Cloud workspace is ready.`,
|
||||
bodyLines: [
|
||||
`To claim it, connect it to your Nx Cloud account:`,
|
||||
`- Commit and push your changes.`,
|
||||
`- Create a pull request for the changes.`,
|
||||
`- Go to the following URL to connect your workspace to Nx Cloud:`,
|
||||
'',
|
||||
`${connectCloudUrl}`,
|
||||
],
|
||||
});
|
||||
return connectCloudUrl;
|
||||
}
|
||||
|
||||
interface ConnectToNxCloudOptions {
|
||||
export interface ConnectToNxCloudOptions {
|
||||
analytics?: boolean;
|
||||
installationSource?: string;
|
||||
hideFormatLogs?: boolean;
|
||||
@ -153,7 +120,7 @@ function addNxCloudOptionsToNxJson(
|
||||
export async function connectToNxCloud(
|
||||
tree: Tree,
|
||||
schema: ConnectToNxCloudOptions
|
||||
) {
|
||||
): Promise<string> {
|
||||
schema.installationSource ??= 'user';
|
||||
|
||||
const nxJson = readNxJson(tree) as
|
||||
@ -161,16 +128,14 @@ export async function connectToNxCloud(
|
||||
| (NxJsonConfiguration & { neverConnectToCloud: boolean });
|
||||
|
||||
if (nxJson?.neverConnectToCloud) {
|
||||
return () => {
|
||||
printCloudConnectionDisabledMessage();
|
||||
};
|
||||
printCloudConnectionDisabledMessage();
|
||||
return null;
|
||||
} else {
|
||||
const usesGithub = await repoUsesGithub(schema.github);
|
||||
const usesGithub = schema.github ?? (await repoUsesGithub(schema.github));
|
||||
|
||||
let responseFromCreateNxCloudWorkspace:
|
||||
| {
|
||||
token: string;
|
||||
url: string;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
@ -192,18 +157,9 @@ export async function connectToNxCloud(
|
||||
await formatChangedFilesWithPrettierIfAvailable(tree, {
|
||||
silent: schema.hideFormatLogs,
|
||||
});
|
||||
return responseFromCreateNxCloudWorkspace.token;
|
||||
}
|
||||
return async () =>
|
||||
await printSuccessMessage(
|
||||
responseFromCreateNxCloudWorkspace?.token,
|
||||
schema.installationSource,
|
||||
usesGithub
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export default connectToNxCloud;
|
||||
|
||||
@ -2,10 +2,11 @@ import { logger } from '../../devkit-exports';
|
||||
import { getGithubSlugOrNull } from '../../utils/git-utils';
|
||||
import { getCloudUrl } from './get-cloud-options';
|
||||
|
||||
export async function shortenedCloudUrl(
|
||||
installationSource: string,
|
||||
export async function createNxCloudOnboardingURL(
|
||||
onboardingSource: string,
|
||||
accessToken?: string,
|
||||
usesGithub?: boolean
|
||||
usesGithub?: boolean,
|
||||
meta?: string
|
||||
) {
|
||||
const githubSlug = getGithubSlugOrNull();
|
||||
|
||||
@ -29,7 +30,7 @@ export async function shortenedCloudUrl(
|
||||
return apiUrl;
|
||||
}
|
||||
|
||||
const source = getSource(installationSource);
|
||||
const source = getSource(onboardingSource);
|
||||
|
||||
try {
|
||||
const response = await require('axios').post(
|
||||
@ -39,6 +40,7 @@ export async function shortenedCloudUrl(
|
||||
source,
|
||||
accessToken: usesGithub ? null : accessToken,
|
||||
selectedRepositoryName: githubSlug === 'github' ? null : githubSlug,
|
||||
meta,
|
||||
}
|
||||
);
|
||||
|
||||
@ -87,15 +89,13 @@ export async function repoUsesGithub(
|
||||
|
||||
function getSource(
|
||||
installationSource: string
|
||||
): 'nx-init' | 'nx-connect' | 'create-nx-workspace' | 'other' {
|
||||
): 'nx-init' | 'nx-connect' | string {
|
||||
if (installationSource.includes('nx-init')) {
|
||||
return 'nx-init';
|
||||
} else if (installationSource.includes('nx-connect')) {
|
||||
return 'nx-connect';
|
||||
} else if (installationSource.includes('create-nx-workspace')) {
|
||||
return 'create-nx-workspace';
|
||||
} else {
|
||||
return 'other';
|
||||
return installationSource;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user