Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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 @@ -2389,6 +2317,78 @@ batch:
depend-on:
- build_windows
- upb
- identifier: l_migrate_store_locator_migration
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_migration
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_migration
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_migration
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_migration
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_migration
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_migration
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_migration
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: aggregate_e2e_reports
env:
compute-type: BUILD_GENERAL1_MEDIUM
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_migration",
"l_migrate_discussions_migration",
"l_migrate_fitness_tracker_migration",
"l_migrate_media_vault_migration",
"l_migrate_mood_board_migration",
"l_migrate_product_catalog_migration",
"l_migrate_project_boards_migration",
"l_migrate_store_locator_migration",
"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