From c9370964878827d617ceec3339876081189d4a8c Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Tue, 20 Apr 2021 12:14:39 -0300 Subject: [PATCH 1/9] create check functions --- src/modules/abtest/finish.ts | 4 ++-- src/modules/abtest/start.ts | 37 ++++++++++-------------------------- src/modules/abtest/status.ts | 4 ++-- src/modules/abtest/utils.ts | 23 +++++++++++++++++++--- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/modules/abtest/finish.ts b/src/modules/abtest/finish.ts index e6bb384..2f0d1b6 100644 --- a/src/modules/abtest/finish.ts +++ b/src/modules/abtest/finish.ts @@ -5,7 +5,7 @@ import { map, prop, filter } from 'ramda' import { logger, promptConfirm, SessionManager } from 'vtex' import { default as abTestStatus } from './status' -import { abtester, installedABTester } from './utils' +import { abtester, checkABTester } from './utils' const { account } = SessionManager.getSingleton() @@ -33,7 +33,7 @@ const promptWorkspaceToFinishABTest = () => .then(prop('workspace')) export default async () => { - await installedABTester() + await checkABTester() const workspace = await promptWorkspaceToFinishABTest() const promptAnswer = await promptContinue(workspace) diff --git a/src/modules/abtest/start.ts b/src/modules/abtest/start.ts index a008b2a..d858ace 100644 --- a/src/modules/abtest/start.ts +++ b/src/modules/abtest/start.ts @@ -1,13 +1,12 @@ import chalk from 'chalk' import enquirer from 'enquirer' import { compose, fromPairs, keys, map, mapObjIndexed, prop, values, zip } from 'ramda' -import semver from 'semver' import { logger, promptConfirm } from 'vtex' import { abtester, - installedABTester, + checkABTester, formatDays, promptConstraintDuration, promptProductionWorkspace, @@ -56,38 +55,22 @@ ${chalk.green('master')} and ${chalk.green(workspace)}. Proceed?`, } export default async () => { - const abTesterManifest = await installedABTester() + await checkABTester() const workspace = await promptProductionWorkspace('Choose production workspace to start A/B test:') try { - const [version] = abTesterManifest.version.split('-') - - if (semver.satisfies(version, '>=0.10.0')) { - logger.info(`Setting workspace ${chalk.green(workspace)} to A/B test`) - const promptAnswer = await promptContinue(workspace) - - if (!promptAnswer) return - const proportion = Number(await promptProportionTrafic()) - const timeLength = Number(await promptConstraintDuration()) - - await abtester.customStart(workspace, timeLength, proportion) - logger.info(`Workspace ${chalk.green(String(workspace))} in A/B test`) - logger.info(`You can stop the test using ${chalk.blue('vtex workspace abtest finish')}`) - - return - } - - const significanceLevel = await promptSignificanceLevel() - const promptAnswer = await promptContinue(workspace, significanceLevel) + logger.info(`Setting workspace ${chalk.green(workspace)} to A/B test`) + const promptAnswer = await promptContinue(workspace) if (!promptAnswer) return - const significanceLevelValue = SIGNIFICANCE_LEVELS[significanceLevel] + const proportion = Number(await promptProportionTrafic()) + const timeLength = Number(await promptConstraintDuration()) - logger.info(`Setting workspace ${chalk.green(workspace)} to A/B test with \ - ${significanceLevel} significance level`) - await abtester.startLegacy(workspace, significanceLevelValue) - logger.info(`Workspace ${chalk.green(workspace)} in A/B test`) + await abtester.customStart(workspace, timeLength, proportion) + logger.info(`Workspace ${chalk.green(String(workspace))} in A/B test`) logger.info(`You can stop the test using ${chalk.blue('vtex workspace abtest finish')}`) + + return } catch (err) { if (err.message === 'Workspace not found') { console.log(`Test not initialized due to workspace ${workspace} not found by ab-tester.`) diff --git a/src/modules/abtest/status.ts b/src/modules/abtest/status.ts index cb479b5..b4ce71f 100644 --- a/src/modules/abtest/status.ts +++ b/src/modules/abtest/status.ts @@ -4,7 +4,7 @@ import numbro from 'numbro' import R from 'ramda' import { SessionManager, logger, createTable } from 'vtex' -import { abtester, formatDuration, installedABTester } from './utils' +import { abtester, formatDuration, checkABTester } from './utils' interface ABTestStatus { ABTestBeginning: string @@ -119,7 +119,7 @@ const printResultsTable = (testInfo: ABTestStatus) => { export default async () => { const { account } = SessionManager.getSingleton() - await installedABTester() + await checkABTester() let abTestInfo = [] abTestInfo = await abtester.status() diff --git a/src/modules/abtest/utils.ts b/src/modules/abtest/utils.ts index fe19211..33cc00c 100644 --- a/src/modules/abtest/utils.ts +++ b/src/modules/abtest/utils.ts @@ -4,8 +4,11 @@ import enquirer from 'enquirer' import numbro from 'numbro' import { compose, filter, map, prop } from 'ramda' import * as env from 'vtex' -import { createFlowIssueError, createAppsClient, createWorkspacesClient, SessionManager } from 'vtex' +import { createFlowIssueError, createAppsClient, createWorkspacesClient, SessionManager, COLORS } from 'vtex' import { ABTester } from '../../clients/apps/ABTester' +import semver from 'semver' + +const VERSION_THRESHOLD = '0.12.0' const DEFAULT_TIMEOUT = 15000 @@ -41,7 +44,12 @@ export const formatDuration = (durationInMinutes: number) => { return `${days} days, ${hours} hours and ${minutes} minutes` } -export const installedABTester = async (): Promise => { +export const checkABTester = async () => { + const abTesterManifest = await installedABTester() + checkABTesterVersion(abTesterManifest.version) +} + +const installedABTester = async (): Promise => { try { return await apps.getApp('vtex.ab-tester@x') } catch (e) { @@ -51,11 +59,20 @@ not installed in account ${chalk.green(account)}, workspace \ ${chalk.blue('master')}. Please install it before attempting to use A/B \ testing functionality`) } - throw e } } +const checkABTesterVersion = (version: string) => { + const [versionNumber] = version.split('-') + + if (!semver.satisfies(versionNumber, `>${VERSION_THRESHOLD}`)) { + throw createFlowIssueError(`You are using ${chalk.yellow(`vtex.ab-tester@${version}`)}, \ +which is of an excessively old version. Please, use a version newer than ${chalk.green(VERSION_THRESHOLD)} \ +\nTo get the latest version, run ${chalk.hex(COLORS.PINK)('vtex install vtex.ab-tester')}`) + } +} + export const promptProductionWorkspace = async (promptMessage: string): Promise => { const workspaces = createWorkspacesClient() const productionWorkspaces = await workspaces.list(account).then( From 33b2b971b262a799e72a6032d5b754e54a416fdd Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Tue, 20 Apr 2021 12:22:58 -0300 Subject: [PATCH 2/9] remove unused code --- src/modules/abtest/start.ts | 29 ----------------------------- src/modules/abtest/utils.ts | 17 ----------------- 2 files changed, 46 deletions(-) diff --git a/src/modules/abtest/start.ts b/src/modules/abtest/start.ts index d858ace..db761e8 100644 --- a/src/modules/abtest/start.ts +++ b/src/modules/abtest/start.ts @@ -1,44 +1,15 @@ import chalk from 'chalk' -import enquirer from 'enquirer' -import { compose, fromPairs, keys, map, mapObjIndexed, prop, values, zip } from 'ramda' import { logger, promptConfirm } from 'vtex' import { abtester, checkABTester, - formatDays, promptConstraintDuration, promptProductionWorkspace, promptProportionTrafic, - SIGNIFICANCE_LEVELS, } from './utils' -const promptSignificanceLevel = async (): Promise => { - const significanceTimePreviews = await Promise.all( - compose>>( - map((value) => abtester.preview(value as number)), - values - )(SIGNIFICANCE_LEVELS) - ) - - const significanceTimePreviewMap = fromPairs(zip(keys(SIGNIFICANCE_LEVELS), significanceTimePreviews)) - - return enquirer - .prompt<{ level: string }>({ - name: 'level', - message: 'Choose the significance level:', - type: 'select', - choices: values( - mapObjIndexed((value, key) => ({ - message: `${key} (~ ${formatDays(value as number)})`, - value: key, - }))(significanceTimePreviewMap) - ) as any, - }) - .then(prop('level')) -} - const promptContinue = (workspace: string, significanceLevel?: string) => { return significanceLevel ? promptConfirm( diff --git a/src/modules/abtest/utils.ts b/src/modules/abtest/utils.ts index 33cc00c..d30d9e4 100644 --- a/src/modules/abtest/utils.ts +++ b/src/modules/abtest/utils.ts @@ -1,7 +1,6 @@ import { AppManifest } from '@vtex/api' import chalk from 'chalk' import enquirer from 'enquirer' -import numbro from 'numbro' import { compose, filter, map, prop } from 'ramda' import * as env from 'vtex' import { createFlowIssueError, createAppsClient, createWorkspacesClient, SessionManager, COLORS } from 'vtex' @@ -12,12 +11,6 @@ const VERSION_THRESHOLD = '0.12.0' const DEFAULT_TIMEOUT = 15000 -export const SIGNIFICANCE_LEVELS: Record = { - low: 0.5, - mid: 0.7, - high: 0.9, -} - const { account } = SessionManager.getSingleton() const options = { timeout: (env.envTimeout || DEFAULT_TIMEOUT) as number } @@ -26,16 +19,6 @@ const options = { timeout: (env.envTimeout || DEFAULT_TIMEOUT) as number } export const abtester = ABTester.createClient({ workspace: 'master' }, { ...options, retries: 3 }) export const apps = createAppsClient({ workspace: 'master' }) -export const formatDays = (days: number) => { - let suffix = 'days' - - if (days === 1) { - suffix = 'day' - } - - return `${numbro(days).format('0,0')} ${suffix}` -} - export const formatDuration = (durationInMinutes: number) => { const minutes = durationInMinutes % 60 const hours = Math.trunc(durationInMinutes / 60) % 24 From 8f5dd8c52fc08986cc15896ba6983eee406ca5b6 Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Tue, 20 Apr 2021 12:26:24 -0300 Subject: [PATCH 3/9] refactor modules/start --- src/modules/abtest/start.ts | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/modules/abtest/start.ts b/src/modules/abtest/start.ts index db761e8..49e50a5 100644 --- a/src/modules/abtest/start.ts +++ b/src/modules/abtest/start.ts @@ -28,23 +28,22 @@ ${chalk.green('master')} and ${chalk.green(workspace)}. Proceed?`, export default async () => { await checkABTester() const workspace = await promptProductionWorkspace('Choose production workspace to start A/B test:') + logger.info(`Setting workspace ${chalk.green(workspace)} to A/B test`) + const promptAnswer = await promptContinue(workspace) - try { - logger.info(`Setting workspace ${chalk.green(workspace)} to A/B test`) - const promptAnswer = await promptContinue(workspace) - - if (!promptAnswer) return - const proportion = Number(await promptProportionTrafic()) - const timeLength = Number(await promptConstraintDuration()) + if (!promptAnswer) return + const proportion = Number(await promptProportionTrafic()) + const timeLength = Number(await promptConstraintDuration()) + try { await abtester.customStart(workspace, timeLength, proportion) - logger.info(`Workspace ${chalk.green(String(workspace))} in A/B test`) - logger.info(`You can stop the test using ${chalk.blue('vtex workspace abtest finish')}`) - - return } catch (err) { if (err.message === 'Workspace not found') { console.log(`Test not initialized due to workspace ${workspace} not found by ab-tester.`) } - } + } + logger.info(`Workspace ${chalk.green(String(workspace))} in A/B test`) + logger.info(`You can stop the test using ${chalk.blue('vtex workspace abtest finish')}`) + + return } From 809c98084a82e550b0565e827f3f04f0809132b0 Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Tue, 20 Apr 2021 12:31:44 -0300 Subject: [PATCH 4/9] update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42e2906..e8000f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- [abtest] Prohibit the use of old versions of vtex.ab-tester + ## [0.1.3] - 2021-04-20 ### Fixed From db5a202c700e64dcce8145986c114cd3c27c3f8d Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Tue, 20 Apr 2021 13:26:11 -0300 Subject: [PATCH 5/9] run prettier on src/modules/abtest/start.ts --- src/modules/abtest/start.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/abtest/start.ts b/src/modules/abtest/start.ts index 49e50a5..6e37963 100644 --- a/src/modules/abtest/start.ts +++ b/src/modules/abtest/start.ts @@ -41,7 +41,7 @@ export default async () => { if (err.message === 'Workspace not found') { console.log(`Test not initialized due to workspace ${workspace} not found by ab-tester.`) } - } + } logger.info(`Workspace ${chalk.green(String(workspace))} in A/B test`) logger.info(`You can stop the test using ${chalk.blue('vtex workspace abtest finish')}`) From eefb2c7658e90240b6518c322e7fa7dc14ce639d Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Tue, 20 Apr 2021 13:29:31 -0300 Subject: [PATCH 6/9] lint --- src/modules/abtest/start.ts | 2 -- src/modules/abtest/utils.ts | 10 +++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/modules/abtest/start.ts b/src/modules/abtest/start.ts index 6e37963..9c21980 100644 --- a/src/modules/abtest/start.ts +++ b/src/modules/abtest/start.ts @@ -44,6 +44,4 @@ export default async () => { } logger.info(`Workspace ${chalk.green(String(workspace))} in A/B test`) logger.info(`You can stop the test using ${chalk.blue('vtex workspace abtest finish')}`) - - return } diff --git a/src/modules/abtest/utils.ts b/src/modules/abtest/utils.ts index d30d9e4..f4d492d 100644 --- a/src/modules/abtest/utils.ts +++ b/src/modules/abtest/utils.ts @@ -27,11 +27,6 @@ export const formatDuration = (durationInMinutes: number) => { return `${days} days, ${hours} hours and ${minutes} minutes` } -export const checkABTester = async () => { - const abTesterManifest = await installedABTester() - checkABTesterVersion(abTesterManifest.version) -} - const installedABTester = async (): Promise => { try { return await apps.getApp('vtex.ab-tester@x') @@ -56,6 +51,11 @@ which is of an excessively old version. Please, use a version newer than ${chalk } } +export const checkABTester = async () => { + const abTesterManifest = await installedABTester() + checkABTesterVersion(abTesterManifest.version) +} + export const promptProductionWorkspace = async (promptMessage: string): Promise => { const workspaces = createWorkspacesClient() const productionWorkspaces = await workspaces.list(account).then( From 8f3deb82f1403508df2b574353fc4be8b6f3ffde Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Wed, 5 May 2021 10:38:18 -0300 Subject: [PATCH 7/9] lint whole project --- src/modules/abtest/start.ts | 2 ++ src/modules/abtest/utils.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/modules/abtest/start.ts b/src/modules/abtest/start.ts index 9c21980..a94621e 100644 --- a/src/modules/abtest/start.ts +++ b/src/modules/abtest/start.ts @@ -28,6 +28,7 @@ ${chalk.green('master')} and ${chalk.green(workspace)}. Proceed?`, export default async () => { await checkABTester() const workspace = await promptProductionWorkspace('Choose production workspace to start A/B test:') + logger.info(`Setting workspace ${chalk.green(workspace)} to A/B test`) const promptAnswer = await promptContinue(workspace) @@ -42,6 +43,7 @@ export default async () => { console.log(`Test not initialized due to workspace ${workspace} not found by ab-tester.`) } } + logger.info(`Workspace ${chalk.green(String(workspace))} in A/B test`) logger.info(`You can stop the test using ${chalk.blue('vtex workspace abtest finish')}`) } diff --git a/src/modules/abtest/utils.ts b/src/modules/abtest/utils.ts index f4d492d..bbe456f 100644 --- a/src/modules/abtest/utils.ts +++ b/src/modules/abtest/utils.ts @@ -37,6 +37,7 @@ not installed in account ${chalk.green(account)}, workspace \ ${chalk.blue('master')}. Please install it before attempting to use A/B \ testing functionality`) } + throw e } } @@ -53,6 +54,7 @@ which is of an excessively old version. Please, use a version newer than ${chalk export const checkABTester = async () => { const abTesterManifest = await installedABTester() + checkABTesterVersion(abTesterManifest.version) } From ad5d2ea68e9fa795eab08cc8957b9c1976318269 Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Wed, 5 May 2021 10:55:10 -0300 Subject: [PATCH 8/9] release v0.1.4 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8000f3..ede376c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.1.4] - 2021-05-05 + ### Fixed - [abtest] Prohibit the use of old versions of vtex.ab-tester diff --git a/package.json b/package.json index e12b518..8d66e1c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@vtex/cli-plugin-abtest", "description": "vtex plugin abtest", - "version": "0.1.3", + "version": "0.1.4", "bugs": "https://github.com/vtex/cli-plugin-abtest/issues", "dependencies": { "@oclif/command": "^1", From 0c8b9940e3a088818322af3eadd36686c9c6b405 Mon Sep 17 00:00:00 2001 From: valentino-amadeus Date: Wed, 5 May 2021 13:56:26 +0000 Subject: [PATCH 9/9] Automatic update on Toolbelt plugin documentation --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 25c5e0a..14e8f6c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ $ npm install -g @vtex/cli-plugin-abtest $ oclif-example COMMAND running command... $ oclif-example (-v|--version|version) -@vtex/cli-plugin-abtest/0.1.3 linux-x64 node-v12.22.1 +@vtex/cli-plugin-abtest/0.1.4 linux-x64 node-v12.22.1 $ oclif-example --help [COMMAND] USAGE $ oclif-example COMMAND @@ -44,7 +44,7 @@ OPTIONS --trace Ensure all requests to VTEX IO are traced ``` -_See code: [build/commands/workspace/abtest/finish.ts](https://github.com/vtex/cli-plugin-abtest/blob/v0.1.3/build/commands/workspace/abtest/finish.ts)_ +_See code: [build/commands/workspace/abtest/finish.ts](https://github.com/vtex/cli-plugin-abtest/blob/v0.1.4/build/commands/workspace/abtest/finish.ts)_ ## `oclif-example workspace:abtest:start` @@ -60,7 +60,7 @@ OPTIONS --trace Ensure all requests to VTEX IO are traced ``` -_See code: [build/commands/workspace/abtest/start.ts](https://github.com/vtex/cli-plugin-abtest/blob/v0.1.3/build/commands/workspace/abtest/start.ts)_ +_See code: [build/commands/workspace/abtest/start.ts](https://github.com/vtex/cli-plugin-abtest/blob/v0.1.4/build/commands/workspace/abtest/start.ts)_ ## `oclif-example workspace:abtest:status` @@ -76,5 +76,5 @@ OPTIONS --trace Ensure all requests to VTEX IO are traced ``` -_See code: [build/commands/workspace/abtest/status.ts](https://github.com/vtex/cli-plugin-abtest/blob/v0.1.3/build/commands/workspace/abtest/status.ts)_ +_See code: [build/commands/workspace/abtest/status.ts](https://github.com/vtex/cli-plugin-abtest/blob/v0.1.4/build/commands/workspace/abtest/status.ts)_