Skip to content

Commit

Permalink
feat(misc): add onboarding a/b testing (#27217)
Browse files Browse the repository at this point in the history
<!-- 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 #

(cherry picked from commit 341f295)
  • Loading branch information
FrozenPandaz committed Jul 30, 2024
1 parent 56bf5ff commit a329c2c
Show file tree
Hide file tree
Showing 18 changed files with 380 additions and 187 deletions.
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(
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

0 comments on commit a329c2c

Please sign in to comment.