From b41bb0571c4f6a6760bbb28b64a678a484cf5985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Thu, 26 Oct 2023 11:56:30 -0700 Subject: [PATCH 01/11] feat: add env ci support --- .changeset/metal-tomatoes-check.md | 5 +++++ packages/create-amplify/src/get_project_root.ts | 3 ++- packages/create-amplify/src/logger.ts | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 .changeset/metal-tomatoes-check.md diff --git a/.changeset/metal-tomatoes-check.md b/.changeset/metal-tomatoes-check.md new file mode 100644 index 0000000000..41a25346d7 --- /dev/null +++ b/.changeset/metal-tomatoes-check.md @@ -0,0 +1,5 @@ +--- +'create-amplify': patch +--- + +Create Amplify uses default options and log verbosely when it's CI env diff --git a/packages/create-amplify/src/get_project_root.ts b/packages/create-amplify/src/get_project_root.ts index bb9dc4f84b..c12f623a23 100644 --- a/packages/create-amplify/src/get_project_root.ts +++ b/packages/create-amplify/src/get_project_root.ts @@ -7,7 +7,8 @@ import { logger } from './logger.js'; * Returns the project root directory. */ export const getProjectRoot = async () => { - const useDefault = process.env.npm_config_yes === 'true'; + const useDefault = + process.env.npm_config_yes === 'true' || process.env.CI === 'true'; const defaultProjectRoot = '.'; let projectRoot: string = useDefault ? defaultProjectRoot diff --git a/packages/create-amplify/src/logger.ts b/packages/create-amplify/src/logger.ts index 53832e0404..f30880665d 100644 --- a/packages/create-amplify/src/logger.ts +++ b/packages/create-amplify/src/logger.ts @@ -77,7 +77,9 @@ export const argv = await yargs(process.argv.slice(2)).options({ }).argv; const minimumLogLevel = - argv.debug || argv.verbose ? LogLevel.DEBUG : LogLevel.INFO; + argv.debug || argv.verbose || process.env.CI === 'true' + ? LogLevel.DEBUG + : LogLevel.INFO; const logger = new Logger(global.console, minimumLogLevel); From e722f114ae4c340a0ff6b635e76fddae5b565541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Thu, 26 Oct 2023 12:18:08 -0700 Subject: [PATCH 02/11] test: update unit tests --- .../src/get_project_root.test.ts | 14 +++++++++++ packages/create-amplify/src/logger.test.ts | 25 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/packages/create-amplify/src/get_project_root.test.ts b/packages/create-amplify/src/get_project_root.test.ts index 333c997474..dce866b1f7 100644 --- a/packages/create-amplify/src/get_project_root.test.ts +++ b/packages/create-amplify/src/get_project_root.test.ts @@ -68,4 +68,18 @@ void describe('getProjectRoot', () => { ); assert.equal(projectRoot, path.resolve(userInput)); }); + + void it('use default options if in CI mode', async (ctx) => { + process.env.CI = 'true'; + const userInput = 'test'; + const fsMkDirSyncMock = ctx.mock.method(fsp, 'mkdir', () => undefined); + ctx.mock.method(fsp, 'stat', () => Promise.reject(new Error())); + ctx.mock.method(AmplifyPrompter, 'input', () => Promise.resolve(userInput)); + + const projectRoot = await getProjectRoot(); + + assert.equal(fsMkDirSyncMock.mock.callCount(), 1); + assert.equal(fsMkDirSyncMock.mock.calls[0].arguments[0], process.cwd()); + assert.equal(projectRoot, process.cwd()); + }); }); diff --git a/packages/create-amplify/src/logger.test.ts b/packages/create-amplify/src/logger.test.ts index 4e7f2132e0..40267c3f9a 100644 --- a/packages/create-amplify/src/logger.test.ts +++ b/packages/create-amplify/src/logger.test.ts @@ -59,4 +59,29 @@ void describe('Logger', () => { new RegExp(`\\[DEBUG\\].*: Test log message`) ); }); + + void it('logs a debug message in CI mode', async (ctx) => { + const mockConsole = { + log: ctx.mock.fn(() => undefined), + }; + + const mockArgs = { + debug: false, + verbose: false, + }; + + const mockProcessEnv = { CI: 'true' }; + + const mockMinimumLogLevel = + mockArgs.debug || mockArgs.verbose || mockProcessEnv.CI === 'true' + ? LogLevel.DEBUG + : LogLevel.INFO; + + const logger = new Logger(mockConsole as never, mockMinimumLogLevel); + await logger.debug('Test log message'); + assert.match( + [...mockConsole.log.mock.calls[0].arguments][0] ?? '', + new RegExp(`\\[DEBUG\\].*: Test log message`) + ); + }); }); From 7dca6dacdb451d327e66fa844c12d2b75e4f8aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Thu, 26 Oct 2023 13:22:47 -0700 Subject: [PATCH 03/11] feat: create amplify --yes option --- packages/create-amplify/src/get_project_root.test.ts | 8 +++++--- packages/create-amplify/src/get_project_root.ts | 11 +++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/create-amplify/src/get_project_root.test.ts b/packages/create-amplify/src/get_project_root.test.ts index dce866b1f7..616ef9b2e5 100644 --- a/packages/create-amplify/src/get_project_root.test.ts +++ b/packages/create-amplify/src/get_project_root.test.ts @@ -2,8 +2,9 @@ import { afterEach, describe, it } from 'node:test'; import assert from 'assert'; import fsp from 'fs/promises'; import path from 'path'; -import { getProjectRoot } from './get_project_root.js'; +import yargs from 'yargs'; import { AmplifyPrompter } from '@aws-amplify/cli-core'; +import { getProjectRoot } from './get_project_root.js'; const originalEnv = process.env; @@ -69,8 +70,9 @@ void describe('getProjectRoot', () => { assert.equal(projectRoot, path.resolve(userInput)); }); - void it('use default options if in CI mode', async (ctx) => { - process.env.CI = 'true'; + void it('use default options if `yes`', async (ctx) => { + process.env.npm_config_yes = 'false'; + process.argv = ['node', 'test.js', '--yes']; const userInput = 'test'; const fsMkDirSyncMock = ctx.mock.method(fsp, 'mkdir', () => undefined); ctx.mock.method(fsp, 'stat', () => Promise.reject(new Error())); diff --git a/packages/create-amplify/src/get_project_root.ts b/packages/create-amplify/src/get_project_root.ts index c12f623a23..f88469c5ad 100644 --- a/packages/create-amplify/src/get_project_root.ts +++ b/packages/create-amplify/src/get_project_root.ts @@ -1,5 +1,6 @@ import fsp from 'fs/promises'; import path from 'path'; +import yargs from 'yargs'; import { AmplifyPrompter } from '@aws-amplify/cli-core'; import { logger } from './logger.js'; @@ -7,8 +8,14 @@ import { logger } from './logger.js'; * Returns the project root directory. */ export const getProjectRoot = async () => { - const useDefault = - process.env.npm_config_yes === 'true' || process.env.CI === 'true'; + const argv = await yargs(process.argv.slice(2)).options({ + yes: { + type: 'boolean', + default: false, + }, + }).argv; + + const useDefault = process.env.npm_config_yes === 'true' || argv.yes === true; const defaultProjectRoot = '.'; let projectRoot: string = useDefault ? defaultProjectRoot From 70fad768a856da60a4f7dbe140ae6a888b845c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Thu, 26 Oct 2023 13:27:28 -0700 Subject: [PATCH 04/11] chore: remove un-used code --- packages/create-amplify/src/get_project_root.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/create-amplify/src/get_project_root.test.ts b/packages/create-amplify/src/get_project_root.test.ts index 616ef9b2e5..601cde9b71 100644 --- a/packages/create-amplify/src/get_project_root.test.ts +++ b/packages/create-amplify/src/get_project_root.test.ts @@ -2,7 +2,6 @@ import { afterEach, describe, it } from 'node:test'; import assert from 'assert'; import fsp from 'fs/promises'; import path from 'path'; -import yargs from 'yargs'; import { AmplifyPrompter } from '@aws-amplify/cli-core'; import { getProjectRoot } from './get_project_root.js'; From dc2df4bf80669e39d37ebb1a909d75686609e065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Thu, 26 Oct 2023 16:53:21 -0700 Subject: [PATCH 05/11] feat: support Panage Manager env var --- packages/create-amplify/src/get_project_root.ts | 1 - .../create-amplify/src/npm_package_manager_controller.ts | 8 +++++--- packages/create-amplify/src/tsconfig_initializer.ts | 9 +++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/create-amplify/src/get_project_root.ts b/packages/create-amplify/src/get_project_root.ts index f88469c5ad..cb693c3d25 100644 --- a/packages/create-amplify/src/get_project_root.ts +++ b/packages/create-amplify/src/get_project_root.ts @@ -14,7 +14,6 @@ export const getProjectRoot = async () => { default: false, }, }).argv; - const useDefault = process.env.npm_config_yes === 'true' || argv.yes === true; const defaultProjectRoot = '.'; let projectRoot: string = useDefault diff --git a/packages/create-amplify/src/npm_package_manager_controller.ts b/packages/create-amplify/src/npm_package_manager_controller.ts index 39e6ee4406..a4bfbf044e 100644 --- a/packages/create-amplify/src/npm_package_manager_controller.ts +++ b/packages/create-amplify/src/npm_package_manager_controller.ts @@ -15,7 +15,7 @@ export class NpmPackageManagerController implements PackageManagerController { private readonly projectRoot: string, private readonly execa = _execa ) {} - private readonly executableName = 'npm'; + private readonly executableName = process.env.PM || 'npm'; /** * Installs the given package names as devDependencies @@ -24,9 +24,11 @@ export class NpmPackageManagerController implements PackageManagerController { packageNames: string[], type: DependencyType ): Promise => { - const args = ['install'].concat(...packageNames); + const args = [this.executableName === 'yarn' ? 'add' : 'install'].concat( + ...packageNames + ); if (type === 'dev') { - args.push('--save-dev'); + args.push('-D'); } await this.execa(this.executableName, args, { stdio: 'inherit', diff --git a/packages/create-amplify/src/tsconfig_initializer.ts b/packages/create-amplify/src/tsconfig_initializer.ts index 114f1fdb03..2cecc99ed9 100644 --- a/packages/create-amplify/src/tsconfig_initializer.ts +++ b/packages/create-amplify/src/tsconfig_initializer.ts @@ -17,6 +17,7 @@ export class TsConfigInitializer { private readonly existsSync = _existsSync, private readonly execa = _execa ) {} + private readonly executableName = process.env.PM || 'npx'; /** * If tsconfig.json already exists, this is a noop. Otherwise, `npx tsc --init` is executed to create a tsconfig.json file @@ -27,7 +28,7 @@ export class TsConfigInitializer { return; } this.logger.log( - 'No tsconfig.json file found in the current directory. Running `npx tsc --init`...' + `No tsconfig.json file found in the current directory. Running \`${this.executableName} tsc --init\`...` ); const packageJson = await this.packageJsonReader.readPackageJson(); @@ -53,20 +54,20 @@ export class TsConfigInitializer { } try { - await this.execa('npx', tscArgs, { + await this.execa(this.executableName, tscArgs, { stdio: 'inherit', cwd: this.projectRoot, }); } catch { throw new Error( - '`npx tsc --init` did not exit successfully. Initialize a valid TypeScript configuration before continuing.' + `\`${this.executableName} tsc --init\` did not exit successfully. Initialize a valid TypeScript configuration before continuing.` ); } if (!this.tsConfigJsonExists()) { // this should only happen if the customer exits out of npx tsc --init before finishing throw new Error( - 'tsconfig.json does not exist after running `npx tsc --init`. Initialize a valid TypeScript configuration before continuing.' + `tsconfig.json does not exist after running \`${this.executableName} tsc --init\`. Initialize a valid TypeScript configuration before continuing.` ); } }; From c4231705486955a30fcdb25207622488773df30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Thu, 26 Oct 2023 21:49:03 -0700 Subject: [PATCH 06/11] chore: add comments --- packages/create-amplify/src/npm_package_manager_controller.ts | 2 +- packages/create-amplify/src/tsconfig_initializer.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-amplify/src/npm_package_manager_controller.ts b/packages/create-amplify/src/npm_package_manager_controller.ts index a4bfbf044e..e6e5b4b6b1 100644 --- a/packages/create-amplify/src/npm_package_manager_controller.ts +++ b/packages/create-amplify/src/npm_package_manager_controller.ts @@ -15,7 +15,7 @@ export class NpmPackageManagerController implements PackageManagerController { private readonly projectRoot: string, private readonly execa = _execa ) {} - private readonly executableName = process.env.PM || 'npm'; + private readonly executableName = process.env.PM || 'npm'; // TODO: replace `process.env.PM` with `getPackageManagerName()` once the test infra is ready. /** * Installs the given package names as devDependencies diff --git a/packages/create-amplify/src/tsconfig_initializer.ts b/packages/create-amplify/src/tsconfig_initializer.ts index 2cecc99ed9..1a471126c2 100644 --- a/packages/create-amplify/src/tsconfig_initializer.ts +++ b/packages/create-amplify/src/tsconfig_initializer.ts @@ -17,7 +17,7 @@ export class TsConfigInitializer { private readonly existsSync = _existsSync, private readonly execa = _execa ) {} - private readonly executableName = process.env.PM || 'npx'; + private readonly executableName = process.env.PM || 'npx'; // TODO: replace `process.env.PM` with `getPackageManagerName()` once the test infra is ready. /** * If tsconfig.json already exists, this is a noop. Otherwise, `npx tsc --init` is executed to create a tsconfig.json file From 7b887724a30c07a32d7f4eaef41e6568a6c9bea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Fri, 27 Oct 2023 13:35:31 -0700 Subject: [PATCH 07/11] chore: remove env.CI --- packages/create-amplify/src/logger.test.ts | 6 +----- packages/create-amplify/src/logger.ts | 4 +--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/create-amplify/src/logger.test.ts b/packages/create-amplify/src/logger.test.ts index 40267c3f9a..585dc0f736 100644 --- a/packages/create-amplify/src/logger.test.ts +++ b/packages/create-amplify/src/logger.test.ts @@ -70,12 +70,8 @@ void describe('Logger', () => { verbose: false, }; - const mockProcessEnv = { CI: 'true' }; - const mockMinimumLogLevel = - mockArgs.debug || mockArgs.verbose || mockProcessEnv.CI === 'true' - ? LogLevel.DEBUG - : LogLevel.INFO; + mockArgs.debug || mockArgs.verbose ? LogLevel.DEBUG : LogLevel.INFO; const logger = new Logger(mockConsole as never, mockMinimumLogLevel); await logger.debug('Test log message'); diff --git a/packages/create-amplify/src/logger.ts b/packages/create-amplify/src/logger.ts index f30880665d..53832e0404 100644 --- a/packages/create-amplify/src/logger.ts +++ b/packages/create-amplify/src/logger.ts @@ -77,9 +77,7 @@ export const argv = await yargs(process.argv.slice(2)).options({ }).argv; const minimumLogLevel = - argv.debug || argv.verbose || process.env.CI === 'true' - ? LogLevel.DEBUG - : LogLevel.INFO; + argv.debug || argv.verbose ? LogLevel.DEBUG : LogLevel.INFO; const logger = new Logger(global.console, minimumLogLevel); From a0851622e1135a8290d5dbf95971f085615a2b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Fri, 27 Oct 2023 13:38:34 -0700 Subject: [PATCH 08/11] chore: update changeset --- .changeset/metal-tomatoes-check.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.changeset/metal-tomatoes-check.md b/.changeset/metal-tomatoes-check.md index 41a25346d7..cb02e03b2b 100644 --- a/.changeset/metal-tomatoes-check.md +++ b/.changeset/metal-tomatoes-check.md @@ -2,4 +2,5 @@ 'create-amplify': patch --- -Create Amplify uses default options and log verbosely when it's CI env +1. Create Amplify (temporarily) uses environment variable for Package Manager +2. Create Amplify uses `yes` option to choose the default value for prompts From 988637ebb865c1239a32fd2ca09f3bd973ff6140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Fri, 27 Oct 2023 13:38:50 -0700 Subject: [PATCH 09/11] chore: rename PACKAGE_MANAGER_EXECUTABLE --- packages/create-amplify/src/npm_package_manager_controller.ts | 3 ++- packages/create-amplify/src/tsconfig_initializer.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/create-amplify/src/npm_package_manager_controller.ts b/packages/create-amplify/src/npm_package_manager_controller.ts index e6e5b4b6b1..65c98f0ab7 100644 --- a/packages/create-amplify/src/npm_package_manager_controller.ts +++ b/packages/create-amplify/src/npm_package_manager_controller.ts @@ -15,7 +15,8 @@ export class NpmPackageManagerController implements PackageManagerController { private readonly projectRoot: string, private readonly execa = _execa ) {} - private readonly executableName = process.env.PM || 'npm'; // TODO: replace `process.env.PM` with `getPackageManagerName()` once the test infra is ready. + private readonly executableName = + process.env.PACKAGE_MANAGER_EXECUTABLE || 'npm'; // TODO: replace `process.env.PACKAGE_MANAGER_EXECUTABLE` with `getPackageManagerName()` once the test infra is ready. /** * Installs the given package names as devDependencies diff --git a/packages/create-amplify/src/tsconfig_initializer.ts b/packages/create-amplify/src/tsconfig_initializer.ts index 1a471126c2..f17112e739 100644 --- a/packages/create-amplify/src/tsconfig_initializer.ts +++ b/packages/create-amplify/src/tsconfig_initializer.ts @@ -17,7 +17,8 @@ export class TsConfigInitializer { private readonly existsSync = _existsSync, private readonly execa = _execa ) {} - private readonly executableName = process.env.PM || 'npx'; // TODO: replace `process.env.PM` with `getPackageManagerName()` once the test infra is ready. + private readonly executableName = + process.env.PACKAGE_MANAGER_EXECUTABLE || 'npx'; // TODO: replace `process.env.PACKAGE_MANAGER_EXECUTABLE` with `getPackageManagerName()` once the test infra is ready. /** * If tsconfig.json already exists, this is a noop. Otherwise, `npx tsc --init` is executed to create a tsconfig.json file From be3a456c11c88c32551da0f42015425f037de99c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Fri, 27 Oct 2023 13:56:55 -0700 Subject: [PATCH 10/11] fix: tests --- packages/create-amplify/src/logger.test.ts | 21 ------------------- .../npm_package_manager_controller.test.ts | 2 +- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/packages/create-amplify/src/logger.test.ts b/packages/create-amplify/src/logger.test.ts index 585dc0f736..4e7f2132e0 100644 --- a/packages/create-amplify/src/logger.test.ts +++ b/packages/create-amplify/src/logger.test.ts @@ -59,25 +59,4 @@ void describe('Logger', () => { new RegExp(`\\[DEBUG\\].*: Test log message`) ); }); - - void it('logs a debug message in CI mode', async (ctx) => { - const mockConsole = { - log: ctx.mock.fn(() => undefined), - }; - - const mockArgs = { - debug: false, - verbose: false, - }; - - const mockMinimumLogLevel = - mockArgs.debug || mockArgs.verbose ? LogLevel.DEBUG : LogLevel.INFO; - - const logger = new Logger(mockConsole as never, mockMinimumLogLevel); - await logger.debug('Test log message'); - assert.match( - [...mockConsole.log.mock.calls[0].arguments][0] ?? '', - new RegExp(`\\[DEBUG\\].*: Test log message`) - ); - }); }); diff --git a/packages/create-amplify/src/npm_package_manager_controller.test.ts b/packages/create-amplify/src/npm_package_manager_controller.test.ts index 7504d2c348..f555d3ba80 100644 --- a/packages/create-amplify/src/npm_package_manager_controller.test.ts +++ b/packages/create-amplify/src/npm_package_manager_controller.test.ts @@ -12,7 +12,7 @@ void describe('NpmPackageManagerController', () => { await npmPackageManagerController.installDependencies(['testDep'], 'dev'); assert.deepStrictEqual(execaMock.mock.calls[0].arguments, [ 'npm', - ['install', 'testDep', '--save-dev'], + ['install', 'testDep', '-D'], { cwd: 'testPath', stdio: 'inherit' }, ]); }); From 01d879220d6e3de55ff1aec8ace403e4ac1ba03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MJ=E2=98=94?= Date: Fri, 27 Oct 2023 15:45:59 -0700 Subject: [PATCH 11/11] fix npm -> npx --- packages/create-amplify/src/tsconfig_initializer.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/create-amplify/src/tsconfig_initializer.ts b/packages/create-amplify/src/tsconfig_initializer.ts index f17112e739..5c88dc8198 100644 --- a/packages/create-amplify/src/tsconfig_initializer.ts +++ b/packages/create-amplify/src/tsconfig_initializer.ts @@ -29,7 +29,9 @@ export class TsConfigInitializer { return; } this.logger.log( - `No tsconfig.json file found in the current directory. Running \`${this.executableName} tsc --init\`...` + `No tsconfig.json file found in the current directory. Running \`${ + this.executableName === 'npm' ? 'npx' : this.executableName + } tsc --init\`...` ); const packageJson = await this.packageJsonReader.readPackageJson(); @@ -61,14 +63,18 @@ export class TsConfigInitializer { }); } catch { throw new Error( - `\`${this.executableName} tsc --init\` did not exit successfully. Initialize a valid TypeScript configuration before continuing.` + `\`${ + this.executableName === 'npm' ? 'npx' : this.executableName + } tsc --init\` did not exit successfully. Initialize a valid TypeScript configuration before continuing.` ); } if (!this.tsConfigJsonExists()) { // this should only happen if the customer exits out of npx tsc --init before finishing throw new Error( - `tsconfig.json does not exist after running \`${this.executableName} tsc --init\`. Initialize a valid TypeScript configuration before continuing.` + `tsconfig.json does not exist after running \`${ + this.executableName === 'npm' ? 'npx' : this.executableName + } tsc --init\`. Initialize a valid TypeScript configuration before continuing.` ); } };