feat(misc): a/b different messages during migration to next major

This commit is contained in:
Victor Savkin 2022-09-28 13:42:10 -04:00
parent 4678f3a83b
commit 77b57b78e8
6 changed files with 192 additions and 73 deletions

View File

@ -0,0 +1,83 @@
import axios from 'axios';
import { isCI } from './output';
export class PromptMessages {
private messages = {
nxCloudCreation: [
{
code: 'set-up-distributed-caching-ci',
message: `Enable distributed caching to make your CI faster`,
},
],
nxCloudMigration: [
{
code: 'we-noticed',
message: `We noticed you are migrating to a new major version, but are not taking advantage of Nx Cloud. Nx Cloud can make your CI up to 10 times faster. Learn more about it here: nx.app. Would you like to add it?`,
},
{
code: 'not-leveraging-caching',
message: `You're not leveraging distributed caching yet. Do you want to enable it and speed up your CI?`,
},
{
code: 'make-ci-faster',
message: `Enable distributed caching to make your CI faster?`,
},
],
};
private selectedMessages = {};
getPromptMessage(key: string): string {
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() * this.messages[key].length
);
}
}
return this.messages[key][this.selectedMessages[key]].message;
}
codeOfSelectedPromptMessage(key: string): string {
if (this.selectedMessages[key] === undefined) return null;
return this.messages[key][this.selectedMessages[key]].code;
}
}
export const messages = new PromptMessages();
/**
* We are incrementing a counter to track how often create-nx-workspace is used in CI
* vs dev environments. No personal information is collected.
*/
export async function recordStat(opts: {
command: string;
nxVersion: string;
useCloud: boolean;
meta: string;
}) {
try {
const major = Number(opts.nxVersion.split('.')[0]);
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.log(`Record stat. Major: ${major}`);
}
if (major < 10 || major > 14) return; // test version, skip it
await axios
.create({
baseURL: 'https://cloud.nx.app',
timeout: 400,
})
.post('/nx-cloud/stats', {
command: opts.command,
isCI: isCI(),
useCloud: opts.useCloud,
meta: opts.meta,
});
} catch (e) {
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.error(e);
}
}
}

View File

@ -5,7 +5,7 @@ import * as path from 'path';
import { dirSync } from 'tmp'; import { dirSync } from 'tmp';
import * as yargs from 'yargs'; import * as yargs from 'yargs';
import { showNxWarning, unparse } from './shared'; import { showNxWarning, unparse } from './shared';
import { isCI, output } from './output'; import { output } from './output';
import * as ora from 'ora'; import * as ora from 'ora';
import { import {
detectInvokedPackageManager, detectInvokedPackageManager,
@ -23,7 +23,7 @@ import chalk = require('chalk');
import { ciList } from './ci'; import { ciList } from './ci';
import { join } from 'path'; import { join } from 'path';
import { initializeGitRepo } from './git'; import { initializeGitRepo } from './git';
import axios from 'axios'; import { messages, recordStat } from './ab-testing';
type Arguments = { type Arguments = {
name: string; name: string;
@ -62,37 +62,6 @@ enum Preset {
Express = 'express', Express = 'express',
} }
class PromptMessages {
private messages = {
nxCloud: [
{
code: 'set-up-distributed-caching-ci',
message: `Enable distributed caching to make your CI faster`,
},
],
};
private selectedMessages = {};
getPromptMessage(key: string): string {
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() * this.messages[key].length
);
}
}
return this.messages[key][this.selectedMessages[key]].message;
}
codeOfSelectedPromptMessage(key: string): string {
if (this.selectedMessages[key] === undefined) return null;
return this.messages[key][this.selectedMessages[key]].code;
}
}
const presetOptions: { name: Preset; message: string }[] = [ const presetOptions: { name: Preset; message: string }[] = [
{ {
name: Preset.Apps, name: Preset.Apps,
@ -162,8 +131,6 @@ const nxVersion = require('../package.json').version;
const tsVersion = 'TYPESCRIPT_VERSION'; // This gets replaced with the typescript version in the root package.json during build const tsVersion = 'TYPESCRIPT_VERSION'; // This gets replaced with the typescript version in the root package.json during build
const prettierVersion = 'PRETTIER_VERSION'; // This gets replaced with the prettier version in the root package.json during build const prettierVersion = 'PRETTIER_VERSION'; // This gets replaced with the prettier version in the root package.json during build
const messages = new PromptMessages();
export const commandsObject: yargs.Argv<Arguments> = yargs export const commandsObject: yargs.Argv<Arguments> = yargs
.wrap(yargs.terminalWidth()) .wrap(yargs.terminalWidth())
.parserConfiguration({ .parserConfiguration({
@ -208,7 +175,7 @@ export const commandsObject: yargs.Argv<Arguments> = yargs
type: 'string', type: 'string',
}) })
.option('nxCloud', { .option('nxCloud', {
describe: chalk.dim(messages.getPromptMessage('nxCloud')), describe: chalk.dim(messages.getPromptMessage('nxCloudCreation')),
type: 'boolean', type: 'boolean',
}) })
.option('ci', { .option('ci', {
@ -346,7 +313,12 @@ async function main(parsedArgs: yargs.Arguments<Arguments>) {
printNxCloudSuccessMessage(nxCloudInstallRes.stdout); printNxCloudSuccessMessage(nxCloudInstallRes.stdout);
} }
await recordWorkspaceCreationStats(nxCloud); await recordStat({
nxVersion,
command: 'create-nx-workspace',
useCloud: nxCloud,
meta: messages.codeOfSelectedPromptMessage('nxCloudCreation'),
});
} }
async function getConfiguration( async function getConfiguration(
@ -718,7 +690,7 @@ async function determineNxCloud(
.prompt([ .prompt([
{ {
name: 'NxCloud', name: 'NxCloud',
message: messages.getPromptMessage('nxCloud'), message: messages.getPromptMessage('nxCloudCreation'),
type: 'autocomplete', type: 'autocomplete',
choices: [ choices: [
{ {
@ -1039,32 +1011,3 @@ function pointToTutorialAndCourse(preset: Preset) {
break; break;
} }
} }
/**
* We are incrementing a counter to track how often create-nx-workspace is used in CI
* vs dev environments. No personal information is collected.
*/
async function recordWorkspaceCreationStats(useCloud: boolean) {
try {
const major = Number(nxVersion.split('.')[0]);
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.log(`Record stat. Major: ${major}`);
}
if (major < 10 || major > 14) return; // test version, skip it
await axios
.create({
baseURL: 'https://cloud.nx.app',
timeout: 400,
})
.post('/nx-cloud/stats', {
command: 'create-nx-workspace',
isCI: isCI(),
useCloud,
meta: messages.codeOfSelectedPromptMessage('nxCloud'),
});
} catch (e) {
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.error(e);
}
}
}

View File

@ -63,7 +63,8 @@
"v8-compile-cache": "2.3.0", "v8-compile-cache": "2.3.0",
"yargs": "^17.4.0", "yargs": "^17.4.0",
"yargs-parser": "21.0.1", "yargs-parser": "21.0.1",
"js-yaml": "4.1.0" "js-yaml": "4.1.0",
"axios": "0.21.1"
}, },
"peerDependencies": { "peerDependencies": {
"@swc-node/register": "^1.4.2", "@swc-node/register": "^1.4.2",

View File

@ -29,7 +29,7 @@ export async function connectToNxCloudIfExplicitlyAsked(opts: {
export async function connectToNxCloudCommand( export async function connectToNxCloudCommand(
promptOverride?: string promptOverride?: string
): Promise<void> { ): Promise<boolean> {
const nxJson = readNxJson(); const nxJson = readNxJson();
const nxCloudUsed = Object.values(nxJson.tasksRunnerOptions).find( const nxCloudUsed = Object.values(nxJson.tasksRunnerOptions).find(
(r) => r.runner == '@nrwl/nx-cloud' (r) => r.runner == '@nrwl/nx-cloud'
@ -38,16 +38,17 @@ export async function connectToNxCloudCommand(
output.log({ output.log({
title: 'This workspace is already connected to Nx Cloud.', title: 'This workspace is already connected to Nx Cloud.',
}); });
return; return false;
} }
const res = await connectToNxCloudPrompt(promptOverride); const res = await connectToNxCloudPrompt(promptOverride);
if (!res) return; if (!res) return false;
const pmc = getPackageManagerCommand(); const pmc = getPackageManagerCommand();
execSync(`${pmc.addDev} @nrwl/nx-cloud@latest`); execSync(`${pmc.addDev} @nrwl/nx-cloud@latest`);
execSync(`${pmc.exec} nx g @nrwl/nx-cloud:init`, { execSync(`${pmc.exec} nx g @nrwl/nx-cloud:init`, {
stdio: [0, 1, 2], stdio: [0, 1, 2],
}); });
return true;
} }
async function connectToNxCloudPrompt(prompt?: string) { async function connectToNxCloudPrompt(prompt?: string) {

View File

@ -34,6 +34,8 @@ import {
import { handleErrors } from '../utils/params'; import { handleErrors } from '../utils/params';
import { connectToNxCloudCommand } from './connect-to-nx-cloud'; import { connectToNxCloudCommand } from './connect-to-nx-cloud';
import { output } from '../utils/output'; import { output } from '../utils/output';
import { messages, recordStat } from 'nx/src/utils/ab-testing';
import { nxVersion } from '../utils/versions';
export interface ResolvedMigrationConfiguration extends MigrationsJson { export interface ResolvedMigrationConfiguration extends MigrationsJson {
packageGroup?: NxMigrationsConfiguration['packageGroup']; packageGroup?: NxMigrationsConfiguration['packageGroup'];
@ -815,9 +817,15 @@ async function generateMigrationsJsonAndUpdatePackageJson(
opts.targetVersion opts.targetVersion
)) ))
) { ) {
await connectToNxCloudCommand( const useCloud = await connectToNxCloudCommand(
'We noticed you are migrating to a new major version, but are not taking advantage of Nx Cloud. Nx Cloud can make your CI up to 10 times faster. Learn more about it here: nx.app. Would you like to add it?' messages.getPromptMessage('nxCloudMigration')
); );
await recordStat({
command: 'migrate',
nxVersion,
useCloud,
meta: messages.codeOfSelectedPromptMessage('nxCloudMigration'),
});
originalPackageJson = readJsonFile<PackageJson>( originalPackageJson = readJsonFile<PackageJson>(
join(root, 'package.json') join(root, 'package.json')
); );

View File

@ -0,0 +1,83 @@
import axios from 'axios';
import { isCI } from './is-ci';
export class PromptMessages {
private messages = {
nxCloudCreation: [
{
code: 'set-up-distributed-caching-ci',
message: `Enable distributed caching to make your CI faster`,
},
],
nxCloudMigration: [
{
code: 'we-noticed',
message: `We noticed you are migrating to a new major version, but are not taking advantage of Nx Cloud. Nx Cloud can make your CI up to 10 times faster. Learn more about it here: nx.app. Would you like to add it?`,
},
{
code: 'not-leveraging-caching',
message: `You're not leveraging distributed caching yet. Do you want to enable it and speed up your CI?`,
},
{
code: 'make-ci-faster',
message: `Enable distributed caching to make your CI faster?`,
},
],
};
private selectedMessages = {};
getPromptMessage(key: string): string {
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() * this.messages[key].length
);
}
}
return this.messages[key][this.selectedMessages[key]].message;
}
codeOfSelectedPromptMessage(key: string): string {
if (this.selectedMessages[key] === undefined) return null;
return this.messages[key][this.selectedMessages[key]].code;
}
}
export const messages = new PromptMessages();
/**
* We are incrementing a counter to track how often create-nx-workspace is used in CI
* vs dev environments. No personal information is collected.
*/
export async function recordStat(opts: {
command: string;
nxVersion: string;
useCloud: boolean;
meta: string;
}) {
try {
const major = Number(opts.nxVersion.split('.')[0]);
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.log(`Record stat. Major: ${major}`);
}
if (major < 10 || major > 14) return; // test version, skip it
await axios
.create({
baseURL: 'https://cloud.nx.app',
timeout: 400,
})
.post('/nx-cloud/stats', {
command: opts.command,
isCI: isCI(),
useCloud: opts.useCloud,
meta: opts.meta,
});
} catch (e) {
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.error(e);
}
}
}