Skip to content

Commit 7f09c13

Browse files
committed
fix(amplify-category-api-e2e-core): ensure gen1 placeholder app before e2e init
Add an idempotent, best-effort run-start step that guarantees the Gen1 deprecation-bypass placeholder app (DoNotDeleteAppToBypassGen1Deprecation) and its 'test' backend environment exist in each e2e shard's account + region before any `amplify init` runs, so the Gen1 end-of-life gate never blocks the suite and any prior cleanup-deletion is self-healed. The new ensureGen1PlaceholderApp(region) helper uses @aws-sdk/client-amplify: it paginates ListApps, creates the app via CreateApp only when missing, and creates the 'test' backend environment via CreateBackendEnvironment only when ListBackendEnvironments shows it absent. It is idempotent on both the app and the env, defaults region to process.env.CLI_REGION, relies on the ambient e2e credentials picked up by the SDK default provider chain, and swallows/logs all errors so an already-healthy run is never broken. It is wired as a Jest globalSetup hook (amplify-category-api-e2e-core/global-setup) in both Gen1 e2e packages (amplify-e2e-tests and graphql-transformers-e2e-tests) so it runs exactly once per shard before any test file or `amplify init`. The hook and helper live in standalone modules that avoid importing the heavy e2e-core barrel (and its native node-pty dependency), keeping globalSetup light. --- Prompt: Gen1 PR #3494 — add an at-test-start step that ENSURES the Gen1 placeholder app DoNotDeleteAppToBypassGen1Deprecation (+ backend env 'test') exists in each shard's account+region before `amplify init`, so the Gen1 EOL gate never blocks and cleanup-deletion is self-healed. Idempotent. Implement ensureGen1PlaceholderApp(region) using @aws-sdk/client-amplify, wire into the chosen run-start hook, build, commit (no --no-verify), push to fix/bitnami-ecr-removal-and-tls.
1 parent dd61fbf commit 7f09c13

7 files changed

Lines changed: 97 additions & 0 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Allow people to use `amplify-category-api-e2e-core/global-setup` as a jest globalSetup.
2+
const globalSetup = require('./lib/jest-global-setup');
3+
4+
module.exports = globalSetup.default || globalSetup;

packages/amplify-e2e-core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"clean": "rimraf ./lib"
2323
},
2424
"dependencies": {
25+
"@aws-sdk/client-amplify": "~3.600.0",
2526
"@aws-sdk/client-amplifybackend": "~3.600.0",
2627
"@aws-sdk/client-appsync": "~3.600.0",
2728
"@aws-sdk/client-cloudformation": "~3.600.0",
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {
2+
AmplifyClient,
3+
ListAppsCommand,
4+
CreateAppCommand,
5+
ListBackendEnvironmentsCommand,
6+
CreateBackendEnvironmentCommand,
7+
} from '@aws-sdk/client-amplify';
8+
9+
/**
10+
* Name of the placeholder Amplify Gen1 app that, when present in an account +
11+
* region, bypasses the Gen1 end-of-life gate during `amplify init`.
12+
*/
13+
export const GEN1_PLACEHOLDER_APP_NAME = 'DoNotDeleteAppToBypassGen1Deprecation';
14+
15+
/**
16+
* Backend environment name required on the placeholder app for the bypass to
17+
* take effect.
18+
*/
19+
export const GEN1_PLACEHOLDER_BACKEND_ENV_NAME = 'test';
20+
21+
const LIST_APPS_PAGE_SIZE = 100;
22+
23+
/**
24+
* Ensures the Gen1 deprecation-bypass placeholder app (and its `test` backend
25+
* environment) exists in the given region so the Gen1 EOL gate never blocks
26+
* `amplify init` during e2e runs, self-healing any prior cleanup deletion.
27+
*
28+
* Idempotent: the app and backend environment are created only when missing.
29+
* Never throws — all failures are logged and swallowed so an already-healthy
30+
* run is never broken by this best-effort setup step. Relies on the ambient
31+
* e2e credentials picked up by the AWS SDK default provider chain.
32+
*
33+
* @param region target AWS region; defaults to `process.env.CLI_REGION`.
34+
*/
35+
export async function ensureGen1PlaceholderApp(region: string = process.env.CLI_REGION): Promise<void> {
36+
if (!region) {
37+
console.log('⚠️ ensureGen1PlaceholderApp: no region provided (CLI_REGION unset); skipping');
38+
return;
39+
}
40+
41+
try {
42+
const client = new AmplifyClient({ region });
43+
44+
let appId: string | undefined;
45+
let nextToken: string | undefined;
46+
do {
47+
const { apps, nextToken: token } = await client.send(new ListAppsCommand({ maxResults: LIST_APPS_PAGE_SIZE, nextToken }));
48+
const existing = (apps ?? []).find((app) => app.name === GEN1_PLACEHOLDER_APP_NAME);
49+
if (existing) {
50+
appId = existing.appId;
51+
break;
52+
}
53+
nextToken = token;
54+
} while (nextToken);
55+
56+
if (!appId) {
57+
const { app } = await client.send(new CreateAppCommand({ name: GEN1_PLACEHOLDER_APP_NAME }));
58+
appId = app?.appId;
59+
console.log(`✅ ensureGen1PlaceholderApp: created placeholder app '${GEN1_PLACEHOLDER_APP_NAME}' (${appId}) in ${region}`);
60+
}
61+
62+
if (!appId) {
63+
console.log(`⚠️ ensureGen1PlaceholderApp: could not resolve placeholder appId in ${region}; skipping backend env`);
64+
return;
65+
}
66+
67+
const { backendEnvironments } = await client.send(new ListBackendEnvironmentsCommand({ appId }));
68+
const hasEnv = (backendEnvironments ?? []).some((env) => env.environmentName === GEN1_PLACEHOLDER_BACKEND_ENV_NAME);
69+
if (!hasEnv) {
70+
await client.send(new CreateBackendEnvironmentCommand({ appId, environmentName: GEN1_PLACEHOLDER_BACKEND_ENV_NAME }));
71+
console.log(
72+
`✅ ensureGen1PlaceholderApp: created backend env '${GEN1_PLACEHOLDER_BACKEND_ENV_NAME}' for placeholder app in ${region}`,
73+
);
74+
}
75+
} catch (err) {
76+
console.log(`⚠️ ensureGen1PlaceholderApp: best-effort setup failed in ${region} (continuing): ${err?.message ?? err}`);
77+
}
78+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ export * from './amplifyPull';
22
export * from './amplifyPush';
33
export * from './deleteProject';
44
export * from './initProjectHelper';
5+
export * from './ensureGen1PlaceholderApp';
56
export * from './adminUI';
67
export * from './overrideStack';
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ensureGen1PlaceholderApp } from './init/ensureGen1PlaceholderApp';
2+
3+
/**
4+
* Jest `globalSetup` hook. Runs exactly once per jest invocation (i.e. once per
5+
* e2e shard) before any test file executes or any `amplify init` runs, ensuring
6+
* the Gen1 deprecation-bypass placeholder app exists in the shard's region
7+
* (`process.env.CLI_REGION`). Best-effort and idempotent — never throws.
8+
*/
9+
export default async function globalSetup(): Promise<void> {
10+
await ensureGen1PlaceholderApp(process.env.CLI_REGION);
11+
}

packages/amplify-e2e-tests/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"jest": {
7070
"verbose": false,
7171
"preset": "ts-jest",
72+
"globalSetup": "amplify-category-api-e2e-core/global-setup",
7273
"testRunner": "amplify-category-api-e2e-core/runner",
7374
"testEnvironment": "amplify-category-api-e2e-core/environment",
7475
"transform": {

packages/graphql-transformers-e2e-tests/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
"^axios$": "<rootDir>/../../node_modules/axios/dist/node/axios.cjs"
120120
},
121121
"testEnvironment": "../../FixJestEnvironment.js",
122+
"globalSetup": "amplify-category-api-e2e-core/global-setup",
122123
"coveragePathIgnorePatterns": [
123124
"/node_modules",
124125
"/__tests__/"

0 commit comments

Comments
 (0)