Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion amplify-migration-apps/teardown.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Teardown } from '../packages/amplify-e2e-gen2-migration/src/core/teardown';
import { fromIni } from '@aws-sdk/credential-providers';

const deploymentName = process.argv[2];
const profile = process.argv[3];
Expand All @@ -8,7 +9,7 @@ if (!deploymentName || !profile) {
process.exit(1);
}

new Teardown(deploymentName, profile).clean().catch((e: Error) => {
new Teardown(deploymentName, { credentials: fromIni({ profile }) }).clean().catch((e: Error) => {
console.error(e.message);
process.exit(1);
});
72 changes: 0 additions & 72 deletions codebuild_specs/e2e_workflow_base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,75 +140,3 @@ batch:
buildspec: codebuild_specs/cleanup_resources.yml
depend-on:
- aggregate_e2e_reports
- migrate_backend_only
- migrate_discussions
- migrate_fitness_tracker
- migrate_media_vault
- migrate_mood_board
- migrate_product_catalog
- migrate_project_boards
- migrate_store_locator
- identifier: migrate_backend_only
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: backend-only
- identifier: migrate_discussions
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: discussions
- identifier: migrate_fitness_tracker
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: fitness-tracker
- identifier: migrate_media_vault
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: media-vault
- identifier: migrate_mood_board
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: mood-board
- identifier: migrate_product_catalog
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: product-catalog
- identifier: migrate_project_boards
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: project-boards
- identifier: migrate_store_locator
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: store-locator
144 changes: 72 additions & 72 deletions codebuild_specs/e2e_workflow_generated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,78 +140,6 @@ batch:
buildspec: codebuild_specs/cleanup_resources.yml
depend-on:
- aggregate_e2e_reports
- migrate_backend_only
- migrate_discussions
- migrate_fitness_tracker
- migrate_media_vault
- migrate_mood_board
- migrate_product_catalog
- migrate_project_boards
- migrate_store_locator
- identifier: migrate_backend_only
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: backend-only
- identifier: migrate_discussions
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: discussions
- identifier: migrate_fitness_tracker
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: fitness-tracker
- identifier: migrate_media_vault
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: media-vault
- identifier: migrate_mood_board
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: mood-board
- identifier: migrate_product_catalog
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: product-catalog
- identifier: migrate_project_boards
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: project-boards
- identifier: migrate_store_locator
buildspec: codebuild_specs/run_gen2_migration_e2e.yml
depend-on:
- upb
env:
compute-type: BUILD_GENERAL1_LARGE
variables:
MIGRATION_APP: store-locator
- identifier: l_diagnose_mock_api_hooks_a
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
Expand Down Expand Up @@ -1039,6 +967,78 @@ batch:
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_store_locator
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-store-locator.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_project_boards
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-project-boards.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_product_catalog
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-product-catalog.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_mood_board
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-mood-board.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_media_vault
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-media-vault.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_fitness_tracker
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-fitness-tracker.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_discussions
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-discussions.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_migrate_backend_only
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
variables:
compute-type: BUILD_GENERAL1_LARGE
TEST_SUITE: src/__tests__/gen2-migration/migrate-backend-only.test.ts
DISABLE_COVERAGE: 1
depend-on:
- upb
- identifier: l_js_frontend_config
buildspec: codebuild_specs/run_e2e_tests_linux.yml
env:
Expand Down
22 changes: 0 additions & 22 deletions codebuild_specs/run_gen2_migration_e2e.yml

This file was deleted.

8 changes: 8 additions & 0 deletions codebuild_specs/wait_for_ids.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@
"l_ios_analytics_pinpoint_config_flutter_notifications_pinpoint_config_flutter_analytics_pinpoint_config",
"l_javascript_notifications_pinpoint_config_javascript_analytics_pinpoint_config_ios_notifications_pinpoint_config",
"l_js_frontend_config",
"l_migrate_backend_only",
"l_migrate_discussions",
"l_migrate_fitness_tracker",
"l_migrate_media_vault",
"l_migrate_mood_board",
"l_migrate_product_catalog",
"l_migrate_project_boards",
"l_migrate_store_locator",
"l_notifications_analytics_compatibility_in_app_1_studio_modelgen",
"l_notifications_apns_init_b_container_hosting",
"l_notifications_in_app_messaging",
Expand Down
2 changes: 1 addition & 1 deletion packages/amplify-e2e-core/src/init/amplifyPush.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export function cancelIterativeAmplifyPush(
.wait(`Deploying iterative update ${idx.current} of ${idx.max} into`)
.wait(/.*AWS::AppSync::GraphQLSchema\s*UPDATE_IN_PROGRESS.*/)
.sendCtrlC()
.runAsync((err: Error) => err.message === 'Process exited with non zero exit code 130');
.runAsync((err: Error) => err.message.startsWith('Process exited with non zero exit code 130'));
}

/**
Expand Down
7 changes: 6 additions & 1 deletion packages/amplify-e2e-gen2-migration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ npx tsx src/cli.ts --app project-boards --profile default --verbose

### Credential Refresh

Full migration runs take 30+ minutes, which exceeds typical STS session TTLs. When `TEST_ACCOUNT_ROLE` is used, the CLI re-assumes the role and rewrites `~/.aws/credentials` before every long-running step (`init`, `push`, `assess`, `lock`, `generate`, `refactor`, `deployGen2Sandbox`, `teardown`) so sessions don't expire mid-operation. Spawned subprocesses (Amplify CLI, `ampx sandbox`) pick up the refreshed profile via `AWS_PROFILE`. In `--profile` mode, no refresh happens — the caller-supplied profile is assumed to be long-lived.
Full migration runs take 30+ minutes, which exceeds typical STS session TTLs. In CI, `CredentialManager` performs a two-hop assume-role chain on each `refresh()` call:

1. CodeBuild container credentials (long-lived) → assume `TEST_ACCOUNT_ROLE` (parent account, 1hr)
2. Parent account credentials → assume `OrganizationAccountAccessRole` in `CHILD_ACCOUNT_ID` (1hr)

Because each `refresh()` starts from the long-lived CodeBuild container credentials, the resulting sessions are always fresh regardless of total migration duration. Spawned subprocesses (Amplify CLI, `ampx sandbox`) pick up the refreshed profile via `AWS_PROFILE`. In `--profile` mode, no refresh happens — the caller-supplied profile is assumed to be long-lived.

## Migration Workflow

Expand Down
4 changes: 2 additions & 2 deletions packages/amplify-e2e-gen2-migration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"private": true,
"version": "1.0.1",
"description": "Migration automation system for AWS Amplify Gen1 to Gen2",
"main": "dist/index.js",
"main": "lib/index.js",
"bin": {
"amplify-migrate": "dist/cli.js"
"amplify-migrate": "lib/cli.js"
},
"scripts": {
"build": "tsc",
Expand Down
2 changes: 1 addition & 1 deletion packages/amplify-e2e-gen2-migration/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ async function main(): Promise<void> {
} finally {
if (argv.teardown) {
await app.refreshCredentials();
await new Teardown(app.deploymentName, app.profile).clean();
await new Teardown(app.deploymentName, app.getClientConfig()).clean();
}
}
}
Expand Down
34 changes: 33 additions & 1 deletion packages/amplify-e2e-gen2-migration/src/core/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export class App {
*/
public async init(): Promise<void> {
await this.refreshCredentials();
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await ensureGen1PlaceholderApp(new AmplifyClient(this.getClientConfig()));
this.logger.info('amplify init started');
const mainTsx = path.join(this.sourceAppPath, 'src', 'main.tsx');
Expand Down Expand Up @@ -361,6 +362,7 @@ export class App {
*/
public async deployGen2Sandbox(): Promise<string> {
await this.refreshCredentials();
await this.bootstrapCDK();
this.logger.info('Deploying Gen2 app using ampx sandbox...');
const startTime = Date.now();

Expand Down Expand Up @@ -501,7 +503,14 @@ export class App {
* credential signal — sub-processes resolve it via the shared AWS config.
*/
public getEnv(extra?: Record<string, string>): NodeJS.ProcessEnv {
return { ...process.env, AWS_PROFILE: this.profile, ...extra };
const env: NodeJS.ProcessEnv = { ...process.env, AWS_PROFILE: this.profile, ...extra };
// Remove credential env vars so subprocesses use only the profile.
// Without this, the AWS CLI and CDK prefer env var credentials over
// the profile, causing operations to run in the wrong account.
delete env.AWS_ACCESS_KEY_ID;
delete env.AWS_SECRET_ACCESS_KEY;
delete env.AWS_SESSION_TOKEN;
return env;
}

/**
Expand All @@ -517,6 +526,29 @@ export class App {
// Private Helpers
// ============================================================

/**
* Bootstrap CDK in the target account/region. Idempotent — succeeds
* silently if the CDKToolkit stack already exists.
*/
private async bootstrapCDK(): Promise<void> {
const region = process.env.CLI_REGION ?? 'us-east-1';
this.logger.info(`Bootstrapping CDK for region ${region}...`);

const identity = await execa('aws', ['sts', 'get-caller-identity', '--query', 'Account', '--output', 'text'], {
env: this.getEnv(),
});
const accountId = identity.stdout.trim();

const result = await execa('npx', ['cdk', 'bootstrap', `aws://${accountId}/${region}`], {
cwd: this.targetAppPath,
reject: false,
stdio: 'inherit',
env: this.getEnv(),
});
if (result.exitCode !== 0) {
this.logger.info('CDK bootstrap may already exist or failed, continuing...');
}
}
private removeGitignoreLine(line: string): void {
const gitignorePath = path.join(this.targetAppPath, '.gitignore');
if (!fs.existsSync(gitignorePath)) return;
Expand Down
Loading
Loading