Skip to content

Commit 7ab8fae

Browse files
06180.618Amplifiyer
authored
feat: add init prompts for Gen2 (#13849)
* feat: add warning to init * feat: add prompt to init * feat: only prompt on new project * feat: add guide to Gen2 * refactor: change to use process exit * Update packages/amplify-cli/src/init-steps/preInitMigrationWarning.ts Co-authored-by: Amplifiyer <[email protected]> * refactor: rename to gen2Recommendation * refactor: combine gen2Recommendation to preInitSetup * feat: remove goodbye message * test: fix init.test * test: add unit test for preInitSetup * chore: rename to getPreInitSetup * feat: change verbiage * chore: update unit test * feat: add whyContinueWithGen1 to stack metadata * fix: verify verify_versions_match * fix: verify verify_versions_match * feat: bump versions * feat: bump versions * feat: bump versions * chore: rename to recommendGen2 * chore: rename to recommendGen2 in test * revert .sh format * chore: rename and not export preInitSetup * fix: export gen2Recommandation and preInitSetup for test * fix: set inital answer for pick * Revert "fix: set inital answer for pick" This reverts commit 7ecde5c. * Revert "Revert "fix: set inital answer for pick"" This reverts commit d8fa624. * fix: preInitSetup.test * fix: e2e test by adding isCI * chore: upgrade node-pty * Revert "fix: e2e test by adding isCI" This reverts commit 71b204c. * test: add prompt to e2e * fix: set default value for whyContinueWithGen1 * fix: projectConfig undefined and remove default choice * fix: preInitSetup.test.ts * fix: add default choice back * fix: remove prompts from migration test * test: move new prompt from v12 * test: move new prompt from initJSProjectWithProfile * Revert "test: move new prompt from initJSProjectWithProfile" This reverts commit eeb6f71. * test: move new prompts from initJSProjectWithProfile * chore: change recommendGen2 * test: fix preInitSetup unit test * test: add includeGen2RecommendationPrompt * test: add includeGen2RecommendationPrompt to migration-2 * test: remove prompts from initAndroidProjectWithProfileV12 --------- Co-authored-by: 0.618 <[email protected]> Co-authored-by: Amplifiyer <[email protected]>
1 parent a644a1f commit 7ab8fae

File tree

19 files changed

+223
-28
lines changed

19 files changed

+223
-28
lines changed

.circleci/local_publish_helpers_codebuild.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ function checkPackageVersionsInLocalNpmRegistry {
323323

324324
if [[ $cli_internal_version != $cli_version ]]; then
325325
echo "Versions did not match."
326-
echo "Manual fix: add a proper conventional commit that touches the amplify-cli-npm package to correct its version bump. For example https://github.com/aws-amplify/amplify-cli/commit/6f14792d1db424aa428ec4836fed7d6dd5cccfd0"
326+
echo "Manual fix: add a proper conventional commit that touches the amplify-cli-npm package to correct its version bump. For example https://github.com/aws-amplify/amplify-cli/pull/13759/commits/15dcd96feae925ff26ca51abfb4a0477890af745"
327327
exit 1
328328
else
329329
echo "Versions matched."

packages/amplify-cli-npm/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ export const install = async (): Promise<void> => {
1616
return binary.install();
1717
};
1818

19-
// force version bump to 12.12.0
19+
// force version bump to 12.13.0

packages/amplify-cli/src/__tests__/commands/init.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
import { execSync } from 'child_process';
1212
import { ensureDir, existsSync, readFileSync, readJSON, readdirSync } from 'fs-extra';
1313
import { sync } from 'which';
14-
import { preInitSetup } from '../../init-steps/preInitSetup';
14+
import { getPreInitSetup } from '../../init-steps/preInitSetup';
1515
import { analyzeProject } from '../../init-steps/s0-analyzeProject';
1616
import { initFrontend } from '../../init-steps/s1-initFrontend';
1717
import { scaffoldProjectHeadless } from '../../init-steps/s8-scaffoldHeadless';
@@ -137,7 +137,9 @@ describe('amplify init:', () => {
137137
},
138138
},
139139
};
140-
await preInitSetup(context as unknown as $TSContext);
140+
const recommendGen2 = true;
141+
const step = getPreInitSetup(!recommendGen2);
142+
await step(context as unknown as $TSContext);
141143
expect(execSync).toBeCalledWith(`git ls-remote ${appUrl}`, { stdio: 'ignore' });
142144
expect(execSync).toBeCalledWith(`git clone ${appUrl} .`, { stdio: 'inherit' });
143145
expect(execSync).toBeCalledWith('yarn install', { stdio: 'inherit' });
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { $TSContext } from '@aws-amplify/amplify-cli-core';
2+
import { printer, prompter } from '@aws-amplify/amplify-prompts';
3+
import { getPreInitSetup, preInitSetup, gen2Recommendation } from '../../init-steps/preInitSetup';
4+
import { isNewProject } from '../../init-steps/s0-analyzeProject';
5+
6+
// Mock dependencies
7+
jest.mock('@aws-amplify/amplify-cli-core', () => ({
8+
...(jest.requireActual('@aws-amplify/amplify-cli-core') as {}),
9+
FeatureFlags: {
10+
getBoolean: jest.fn(),
11+
getNumber: jest.fn(),
12+
isInitialized: jest.fn().mockReturnValue(true),
13+
ensureDefaultFeatureFlags: jest.fn(),
14+
},
15+
getPackageManager: jest.fn(),
16+
}));
17+
18+
jest.mock('@aws-amplify/amplify-prompts', () => ({
19+
printer: {
20+
warn: jest.fn(),
21+
},
22+
prompter: {
23+
confirmContinue: jest.fn(),
24+
pick: jest.fn(),
25+
},
26+
}));
27+
28+
jest.mock('../../init-steps/s0-analyzeProject', () => ({
29+
isNewProject: jest.fn(),
30+
}));
31+
32+
describe('preInitSetup', () => {
33+
it('should return preInitSetupBasic when isHeadless is true', () => {
34+
const result = getPreInitSetup(false);
35+
expect(result).toBe(preInitSetup);
36+
});
37+
38+
it('should return a function when isHeadless is false', () => {
39+
const result = getPreInitSetup(false);
40+
expect(typeof result).toBe('function');
41+
});
42+
});
43+
44+
describe('gen2Recommendation', () => {
45+
let context;
46+
47+
beforeEach(() => {
48+
context = { exeInfo: {} } as $TSContext;
49+
});
50+
51+
afterEach(() => {
52+
jest.clearAllMocks();
53+
});
54+
55+
it('should recommend using Gen 2 for new projects', async () => {
56+
const isNewProjectMock = jest.mocked(isNewProject);
57+
isNewProjectMock.mockReturnValue(true);
58+
59+
const confirmContinueMock = jest.mocked(prompter.confirmContinue);
60+
confirmContinueMock.mockResolvedValue(true);
61+
62+
const pickMock = jest.mocked(prompter.pick);
63+
pickMock.mockResolvedValue('I am a current Gen 1 user');
64+
65+
await gen2Recommendation(context);
66+
67+
expect(require('@aws-amplify/amplify-prompts').printer.warn).toHaveBeenCalledWith(
68+
'For new projects, we recommend starting with AWS Amplify Gen 2, our new code-first developer experience. Get started at https://docs.amplify.aws/react/start/quickstart/',
69+
);
70+
expect(confirmContinueMock).toHaveBeenCalledWith('Do you want to continue with Amplify Gen 1?');
71+
expect(pickMock).toHaveBeenCalledWith(
72+
'Why would you like to use Amplify Gen 1?',
73+
[
74+
'I am a current Gen 1 user',
75+
'Gen 2 is missing features I need from Gen 1',
76+
'I find the Gen 1 CLI easier to use',
77+
'Prefer not to answer',
78+
],
79+
{ initial: 3 },
80+
);
81+
expect(context.exeInfo.projectConfig).toEqual({ whyContinueWithGen1: 'I am a current Gen 1 user' });
82+
});
83+
84+
it('should return the context for existing projects', async () => {
85+
const isNewProjectMock = jest.mocked(isNewProject);
86+
isNewProjectMock.mockReturnValue(false);
87+
88+
const result = await gen2Recommendation(context);
89+
90+
expect(result).toEqual(context);
91+
expect(printer.warn).not.toHaveBeenCalled();
92+
expect(prompter.confirmContinue).not.toHaveBeenCalled();
93+
expect(prompter.pick).not.toHaveBeenCalled();
94+
});
95+
});

packages/amplify-cli/src/commands/init.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { constructInputParams } from '../amplify-service-helper';
33
import { Context } from '../domain/context';
44
import { raisePostEnvAddEvent } from '../execution-manager';
55
import { postInitSetup } from '../init-steps/postInitSetup';
6-
import { preInitSetup } from '../init-steps/preInitSetup';
6+
import { getPreInitSetup } from '../init-steps/preInitSetup';
77
import { analyzeProject, analyzeProjectHeadless } from '../init-steps/s0-analyzeProject';
88
import { initFrontend } from '../init-steps/s1-initFrontend';
99
import { initProviders } from '../init-steps/s2-initProviders';
@@ -18,11 +18,12 @@ const constructExeInfo = (context: $TSContext): void => {
1818
};
1919
};
2020

21+
const recommendGen2 = true;
2122
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
2223
const runStrategy = (quickstart: boolean) =>
2324
quickstart
24-
? [preInitSetup, analyzeProjectHeadless, scaffoldProjectHeadless, onHeadlessSuccess]
25-
: [preInitSetup, analyzeProject, initFrontend, initProviders, onSuccess, postInitSetup];
25+
? [getPreInitSetup(!recommendGen2), analyzeProjectHeadless, scaffoldProjectHeadless, onHeadlessSuccess]
26+
: [getPreInitSetup(recommendGen2), analyzeProject, initFrontend, initProviders, onSuccess, postInitSetup];
2627

2728
/**
2829
* entry point for the init command

packages/amplify-cli/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,5 +257,4 @@ export const executeAmplifyCommand = async (context: Context): Promise<void> =>
257257
}
258258
};
259259

260-
// bump version to 12.12.0
261-
//
260+
// bump version to 12.13.0

packages/amplify-cli/src/init-steps/preInitSetup.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ import { execSync } from 'child_process';
33
import * as fs from 'fs-extra';
44
import * as url from 'url';
55
import { generateLocalEnvInfoFile } from './s9-onSuccess';
6+
import { printer, prompter } from '@aws-amplify/amplify-prompts';
7+
import { isNewProject } from './s0-analyzeProject';
8+
9+
export const getPreInitSetup = (recommendGen2: boolean) => {
10+
if (recommendGen2) {
11+
return async (context) => {
12+
await gen2Recommendation(context);
13+
await preInitSetup(context);
14+
};
15+
} else {
16+
return preInitSetup;
17+
}
18+
};
619

720
/**
821
* Executes before init
@@ -22,6 +35,42 @@ export const preInitSetup = async (context: $TSContext): Promise<$TSContext> =>
2235
return context;
2336
};
2437

38+
/**
39+
* recommend using Gen 2 or continue with Gen 1.
40+
* ask for why they are using Gen 1 and store the answer in project-config
41+
*/
42+
export const gen2Recommendation = async (context: $TSContext): Promise<$TSContext> => {
43+
if (!isNewProject(context)) {
44+
return context;
45+
}
46+
printer.warn(
47+
'For new projects, we recommend starting with AWS Amplify Gen 2, our new code-first developer experience. Get started at https://docs.amplify.aws/react/start/quickstart/',
48+
);
49+
50+
const continueWithGen1 = await prompter.confirmContinue('Do you want to continue with Amplify Gen 1?');
51+
52+
if (!continueWithGen1) {
53+
process.exit(0);
54+
}
55+
56+
const whyContinueWithGen1 = await prompter.pick(
57+
'Why would you like to use Amplify Gen 1?',
58+
[
59+
'I am a current Gen 1 user',
60+
'Gen 2 is missing features I need from Gen 1',
61+
'I find the Gen 1 CLI easier to use',
62+
'Prefer not to answer',
63+
],
64+
{ initial: 3 },
65+
);
66+
67+
context.exeInfo.projectConfig = {
68+
whyContinueWithGen1,
69+
};
70+
71+
return context;
72+
};
73+
2574
/**
2675
* Checks whether a url is a valid remote github repository
2776
*

packages/amplify-cli/src/init-steps/s0-analyzeProject.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export const analyzeProject = async (context: $TSContext): Promise<$TSContext> =
152152
const setProjectConfig = (context: $TSContext, projectName: string): void => {
153153
context.exeInfo.isNewProject = isNewProject(context);
154154
context.exeInfo.projectConfig = {
155+
...context.exeInfo.projectConfig,
155156
projectName,
156157
version: amplifyCLIConstants.CURRENT_PROJECT_CONFIG_VERSION,
157158
};
@@ -325,7 +326,7 @@ const isNewEnv = (envName: string): boolean => {
325326
return !allEnvs.includes(envName);
326327
};
327328

328-
const isNewProject = (context: $TSContext): boolean => {
329+
export const isNewProject = (context: $TSContext): boolean => {
329330
let newProject = true;
330331
const projectPath = process.cwd();
331332
const projectConfigFilePath = context.amplify.pathManager.getProjectConfigFilePath(projectPath);

packages/amplify-e2e-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"jest-environment-node": "^26.6.2",
4040
"lodash": "^4.17.21",
4141
"node-fetch": "^2.6.7",
42-
"node-pty": "beta",
42+
"node-pty": "^1.0.0",
4343
"retimer": "2.0.0",
4444
"rimraf": "^3.0.0",
4545
"semver": "^7.5.4",

packages/amplify-e2e-core/src/init/initProjectHelper.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const defaultSettings = {
2727
providerConfig: undefined,
2828
permissionsBoundaryArn: undefined,
2929
includeUsageDataPrompt: true,
30+
includeGen2RecommendationPrompt: true,
3031
testingWithLatestCodebase: false,
3132
};
3233

@@ -59,7 +60,17 @@ export function initJSProjectWithProfile(cwd: string, settings?: Partial<typeof
5960
stripColors: true,
6061
env,
6162
disableCIDetection: s.disableCIDetection,
62-
})
63+
});
64+
65+
if (s.includeGen2RecommendationPrompt) {
66+
chain
67+
.wait('Do you want to continue with Amplify Gen 1?')
68+
.sendYes()
69+
.wait('Why would you like to use Amplify Gen 1?')
70+
.sendCarriageReturn();
71+
}
72+
73+
chain
6374
.wait('Enter a name for the project')
6475
.sendLine(s.name)
6576
.wait('Initialize the project with the above configuration?')
@@ -115,6 +126,10 @@ export function initAndroidProjectWithProfile(cwd: string, settings: Partial<typ
115126
stripColors: true,
116127
env,
117128
})
129+
.wait('Do you want to continue with Amplify Gen 1?')
130+
.sendYes()
131+
.wait('Why would you like to use Amplify Gen 1?')
132+
.sendCarriageReturn()
118133
.wait('Enter a name for the project')
119134
.sendLine(s.name)
120135
.wait('Initialize the project with the above configuration?')
@@ -171,6 +186,10 @@ export function initIosProjectWithProfile(cwd: string, settings: Record<string,
171186
stripColors: true,
172187
env,
173188
})
189+
.wait('Do you want to continue with Amplify Gen 1?')
190+
.sendYes()
191+
.wait('Why would you like to use Amplify Gen 1?')
192+
.sendCarriageReturn()
174193
.wait('Enter a name for the project')
175194
.sendLine(s.name)
176195
.wait('Initialize the project with the above configuration?')
@@ -205,6 +224,10 @@ export function initIosProjectWithXcode(cwd: string): Promise<void> {
205224
cwd,
206225
stripColors: true,
207226
})
227+
.wait('Do you want to continue with Amplify Gen 1?')
228+
.sendYes()
229+
.wait('Why would you like to use Amplify Gen 1?')
230+
.sendCarriageReturn()
208231
.wait('Enter a name for the project')
209232
.sendCarriageReturn()
210233
.wait('Initialize the project with the above configuration?')
@@ -237,6 +260,10 @@ export function initFlutterProjectWithProfile(cwd: string, settings: Record<stri
237260

238261
return new Promise((resolve, reject) => {
239262
const chain = spawn(getCLIPath(), ['init'], { cwd, stripColors: true })
263+
.wait('Do you want to continue with Amplify Gen 1?')
264+
.sendYes()
265+
.wait('Why would you like to use Amplify Gen 1?')
266+
.sendCarriageReturn()
240267
.wait('Enter a name for the project')
241268
.sendLine(s.name)
242269
.wait('Initialize the project with the above configuration?')
@@ -286,6 +313,10 @@ export function initProjectWithAccessKey(
286313
CLI_DEV_INTERNAL_DISABLE_AMPLIFY_APP_CREATION: '1',
287314
},
288315
})
316+
.wait('Do you want to continue with Amplify Gen 1?')
317+
.sendYes()
318+
.wait('Why would you like to use Amplify Gen 1?')
319+
.sendCarriageReturn()
289320
.wait('Enter a name for the project')
290321
.sendLine(s.name)
291322
.wait('Initialize the project with the above configuration?')

packages/amplify-e2e-core/src/utils/pinpoint.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ export function initProjectForPinpoint(cwd: string): Promise<void> {
6666
CLI_DEV_INTERNAL_DISABLE_AMPLIFY_APP_CREATION: '1',
6767
},
6868
})
69+
.wait('Do you want to continue with Amplify Gen 1?')
70+
.sendYes()
71+
.wait('Why would you like to use Amplify Gen 1?')
72+
.sendCarriageReturn()
6973
.wait('Enter a name for the project')
7074
.sendLine(settings.name)
7175
.wait('Initialize the project with the above configuration?')

packages/amplify-e2e-tests/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"lodash": "^4.17.21",
5858
"moment": "^2.24.0",
5959
"node-fetch": "^2.6.7",
60-
"node-pty": "beta",
60+
"node-pty": "^1.0.0",
6161
"rimraf": "^3.0.0",
6262
"title-case": "^3.0.3",
6363
"upper-case": "^2.0.2",

packages/amplify-e2e-tests/src/init-special-cases/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ async function initWorkflow(cwd: string, settings: { accessKeyId: string; secret
5151
CLI_DEV_INTERNAL_DISABLE_AMPLIFY_APP_CREATION: '1',
5252
},
5353
})
54+
.wait('Do you want to continue with Amplify Gen 1?')
55+
.sendYes()
56+
.wait('Why would you like to use Amplify Gen 1?')
57+
.sendCarriageReturn()
5458
.wait('Enter a name for the project')
5559
.sendCarriageReturn()
5660
.wait('Initialize the project with the above configuration?')

packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration-2.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe('amplify key force push', () => {
2828
await initJSProjectWithProfile(projRoot, {
2929
name: 'gqlkeytwomigration',
3030
includeUsageDataPrompt: false,
31+
includeGen2RecommendationPrompt: false,
3132
});
3233
});
3334

packages/amplify-migration-tests/src/__tests__/migration_tests/transformer_migration/api.key.migration.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe('amplify key force push', () => {
2828
await initJSProjectWithProfile(projRoot, {
2929
name: 'gqlkeymigration',
3030
includeUsageDataPrompt: false,
31+
includeGen2RecommendationPrompt: false,
3132
});
3233
});
3334

packages/amplify-migration-tests/src/__tests__/migration_tests_v12/auth.migration.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ describe('v12: amplify migration test auth', () => {
3737

3838
describe('...uses user groups and role mappings', () => {
3939
it('...maintains correct role mapping when updated with latest version', async () => {
40-
await initJSProjectWithProfile(projRoot1, { name: 'authTest', disableAmplifyAppCreation: false });
40+
await initJSProjectWithProfile(projRoot1, {
41+
name: 'authTest',
42+
disableAmplifyAppCreation: false,
43+
includeGen2RecommendationPrompt: false,
44+
});
4145
await addAuthWithGroups(projRoot1);
4246
await amplifyPushAuth(projRoot1);
4347

0 commit comments

Comments
 (0)