Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(misc): add onboarding a/b testing #27217

Merged
merged 1 commit into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/create-nx-plugin/bin/create-nx-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -164,7 +163,7 @@ async function main(parsedArgs: yargs.Arguments<CreateNxPluginArguments>) {
});

if (parsedArgs.nxCloud && workspaceInfo.nxCloudInfo) {
printNxCloudSuccessMessage(workspaceInfo.nxCloudInfo);
console.log(workspaceInfo.nxCloudInfo);
}
}

Expand Down
3 changes: 1 addition & 2 deletions packages/create-nx-workspace/bin/create-nx-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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)) {
Expand Down
34 changes: 15 additions & 19 deletions packages/create-nx-workspace/src/create-workspace.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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(
Copy link
Contributor

Choose a reason for hiding this comment

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

should we short-circuit this if the token is invalid?
Like for example not having an internet connection?

Copy link
Collaborator Author

@FrozenPandaz FrozenPandaz Jul 30, 2024

Choose a reason for hiding this comment

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

If there's an error getting the token because of internet issues, then the process will exit 1 without reaching this part. So that short circuits this logic.

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) {
Expand All @@ -90,7 +86,7 @@ export async function createWorkspace<T extends CreateWorkspaceOptions>(
}

return {
nxCloudInfo: nxCloudInstallRes?.stdout,
nxCloudInfo,
directory,
};
}
Expand Down
12 changes: 1 addition & 11 deletions packages/create-nx-workspace/src/utils/ci/setup-ci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
185 changes: 185 additions & 0 deletions packages/create-nx-workspace/src/utils/nx/messages.ts
Original file line number Diff line number Diff line change
@@ -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);
}
Loading