Skip to content
Draft
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
31 changes: 31 additions & 0 deletions action-items.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Action Items — 2026-05-01

Issues solved: #14517, #14487, #14813

## Before creating PRs

- [ ] Review each branch: `git log -p fix/gen2-migration-14517`, `git log -p fix/gen2-migration-14487`, `git log -p fix/gen2-migration-14813`
- [ ] Review PR message files: `pr-message-14517.md`, `pr-message-14487.md`, `pr-message-14813.md`
- [ ] **Rebase #14813 onto #14517** — both modify `function.renderer.ts`, `function.generator.test.ts`, and the `product-catalog/lowstockproducts/resource.ts` snapshot. After rebase, resolve conflicts and run `UPDATE_SNAPSHOTS=1 yarn test` in the package.
- [ ] **Rebase #14813 onto #14487** (or merge order accordingly) — both modify `data.generator.test.ts`. Conflict is minor (both add new test cases at the end of the describe block).
- [ ] After rebasing, run full test suite: `cd packages/amplify-cli && yarn test`

## File conflicts

| File | Branches |
|------|----------|
| `function.renderer.ts` | #14517, #14813 |
| `function.generator.test.ts` | #14517, #14813 |
| `product-catalog/.../lowstockproducts/resource.ts` | #14517, #14813 |
| `data.generator.test.ts` | #14487, #14813 |

## Snapshot conflicts

- **product-catalog** app: `lowstockproducts/resource.ts` snapshot updated by both #14517 (adds `secret()` calls) and #14813 (removes `REGION` env var). The later branch needs rebasing + `UPDATE_SNAPSHOTS=1 yarn test`.
- **9 other apps** updated by #14813 only (REGION removal) — no conflicts.

## Suggested merge order

1. `fix/gen2-migration-14487` — standalone fix to `data.generator.ts`, no overlap with #14517
2. `fix/gen2-migration-14517` — function secrets, touches `function.renderer.ts` and one snapshot
3. `fix/gen2-migration-14813` — rebase onto both #14487 and #14517 first, then run `UPDATE_SNAPSHOTS=1 yarn test` to reconcile snapshots and resolve test file conflicts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const quotegeneratorbe = defineFunction({
name: `quotegeneratorbe-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const activityTrigger = defineFunction({
name: `activityTrigger-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const fetchuseractivity = defineFunction({
name: `fetchuseractivity-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const recorduseractivity = defineFunction({
name: `recorduseractivity-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const admin = defineFunction({
name: `admin-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const fitnesstracker33f5545533f55455PreSignup = defineFunction({
environment: {
ENV: `${branchName}`,
MODULES: 'email-filter-allowlist',
REGION: 'us-east-1',
REGION: process.env.AWS_REGION ?? '',
DOMAINALLOWLIST: 'amazon.com',
DOMAINBLACKLIST: '',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const lognutrition = defineFunction({
name: `lognutrition-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const importedresourcequotegenerator = defineFunction({
name: `importedresourcequotegenerator-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const addusertogroup = defineFunction({
name: `addusertogroup-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const removeuserfromgroup = defineFunction({
name: `removeuserfromgroup-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const thumbnailgen = defineFunction({
name: `thumbnailgen-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const moodboardGetRandomEmoji = defineFunction({
name: `moodboardGetRandomEmoji-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const moodboardKinesisReader = defineFunction({
name: `moodboardKinesisReader-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const moodboardKinesisTrigger = defineFunction({
name: `moodboardKinesisTrigger-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const S3Trigger1ef46783 = defineFunction({
name: `S3Trigger1ef46783-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const lowstockproducts = defineFunction({
memoryMB: 128,
environment: {
ENV: `${branchName}`,
REGION: 'us-east-1',
REGION: process.env.AWS_REGION ?? '',
LOW_STOCK_THRESHOLD: '5',
PRODUCT_CATALOG_SECRET:
'/amplify/productcatalog/x/AMPLIFY_lowstockproducts_PRODUCT_CATALOG_SECRET',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const quotegenerator = defineFunction({
name: `quotegenerator-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
environment: { ENV: `${branchName}`, REGION: process.env.AWS_REGION ?? '' },
runtime: 22,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const storelocator41a9495f41a9495fPostConfirmation = defineFunction({
environment: {
ENV: `${branchName}`,
MODULES: 'add-to-group',
REGION: 'us-east-1',
REGION: process.env.AWS_REGION ?? '',
GROUP: 'storeLocatorAdmin',
},
runtime: 22,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ describe('DataGenerator', () => {
expect(writtenFile('resource.ts')).toMatchInlineSnapshot(`
"import { defineData } from '@aws-amplify/backend';
import type { Backend } from '../backend';
import { myAuthFn } from '../function/myAuthFn/resource';

const schema = \`type Todo @model { id: ID! }\`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,106 @@ describe('FunctionGenerator', () => {
`);
});

it('renders REGION env var as dynamic process.env.AWS_REGION reference', async () => {
const gen1App = await createGen1App({
providers: { awscloudformation: { StackName: 'amplify-test-main-123456', Region: 'us-east-1' } },
function: {
myFunc: {
service: 'Lambda',
output: { Name: 'myFunc-main-abc', Arn: 'arn:aws:lambda:us-east-1:123:function:myFunc-main-abc' },
},
},
});
jest.spyOn(gen1App, 'resourceMetaOutput').mockReturnValue('myFunc-main-abc');
jest.spyOn(gen1App, 'json').mockReturnValue({ Resources: {} });
jest.spyOn(gen1App, 'file').mockReturnValue('{}');
jest.spyOn(gen1App, 'fileExists').mockReturnValue(false);
jest.spyOn(gen1App.aws, 'fetchFunctionConfig').mockResolvedValue({
FunctionName: 'myFunc-main-abc',
Handler: 'index.handler',
Timeout: 3,
MemorySize: 128,
Runtime: 'nodejs18.x',
Environment: { Variables: { ENV: 'main', REGION: 'us-east-1' } },
});
jest.spyOn(gen1App.aws, 'fetchFunctionSchedule').mockResolvedValue(undefined);

const generator = createFunctionGenerator({ gen1App, backendGenerator, packageJsonGenerator, outputDir });
const ops = await generator.plan();
await ops[0].execute();

expect(writtenFile('resource.ts')).toMatchInlineSnapshot(`
"import { defineFunction } from '@aws-amplify/backend';
import type { Backend } from '../../backend';

const branchName = process.env.AWS_BRANCH ?? 'sandbox';

export const myFunc = defineFunction({
entry: './index.js',
name: \`myFunc-\${branchName}\`,
timeoutSeconds: 3,
memoryMB: 128,
environment: { ENV: \`\${branchName}\`, REGION: process.env.AWS_REGION ?? '' },
runtime: 18,
});

export function applyEscapeHatches(backend: Backend) {
backend.myFunc.resources.cfnResources.cfnFunction.functionName = \`myFunc-\${branchName}\`;
}
"
`);
});

it('renders environment block when REGION is the only env var', async () => {
const gen1App = await createGen1App({
providers: { awscloudformation: { StackName: 'amplify-test-main-123456', Region: 'us-east-1' } },
function: {
myFunc: {
service: 'Lambda',
output: { Name: 'myFunc-main-abc', Arn: 'arn:aws:lambda:us-east-1:123:function:myFunc-main-abc' },
},
},
});
jest.spyOn(gen1App, 'resourceMetaOutput').mockReturnValue('myFunc-main-abc');
jest.spyOn(gen1App, 'json').mockReturnValue({ Resources: {} });
jest.spyOn(gen1App, 'file').mockReturnValue('{}');
jest.spyOn(gen1App, 'fileExists').mockReturnValue(false);
jest.spyOn(gen1App.aws, 'fetchFunctionConfig').mockResolvedValue({
FunctionName: 'myFunc-main-abc',
Handler: 'index.handler',
Timeout: 3,
MemorySize: 128,
Runtime: 'nodejs18.x',
Environment: { Variables: { REGION: 'us-east-1' } },
});
jest.spyOn(gen1App.aws, 'fetchFunctionSchedule').mockResolvedValue(undefined);

const generator = createFunctionGenerator({ gen1App, backendGenerator, packageJsonGenerator, outputDir });
const ops = await generator.plan();
await ops[0].execute();

expect(writtenFile('resource.ts')).toMatchInlineSnapshot(`
"import { defineFunction } from '@aws-amplify/backend';
import type { Backend } from '../../backend';

const branchName = process.env.AWS_BRANCH ?? 'sandbox';

export const myFunc = defineFunction({
entry: './index.js',
name: \`myFunc-\${branchName}\`,
timeoutSeconds: 3,
memoryMB: 128,
environment: { REGION: process.env.AWS_REGION ?? '' },
runtime: 18,
});

export function applyEscapeHatches(backend: Backend) {
backend.myFunc.resources.cfnResources.cfnFunction.functionName = \`myFunc-\${branchName}\`;
}
"
`);
});

it('renders API_KEY as secret when it matches SSM pattern', async () => {
const gen1App = await createGen1App({
providers: { awscloudformation: { StackName: 'amplify-test-main-123456', Region: 'us-east-1' } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export class DataRenderer {

const nodes: ts.Node[] = [this.renderNamedImport('defineData', '@aws-amplify/backend'), this.renderBackendTypeImport()];

const lambdaFunctionName = this.extractLambdaFunctionName(opts.authorizationModes);
if (lambdaFunctionName) {
nodes.push(this.renderNamedImport(lambdaFunctionName, `../function/${lambdaFunctionName}/resource`));
}

const escapeHatchResult = this.renderApplyEscapeHatches(opts);
for (const imp of escapeHatchResult.additionalImports) {
nodes.push(imp);
Expand Down Expand Up @@ -320,6 +325,23 @@ export class DataRenderer {
};
}

/**
* Extracts the Lambda function name from the authorization modes config,
* if a Lambda authorizer is configured.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- untyped JSON from amplify-meta.json authConfig
private extractLambdaFunctionName(authorizationModes?: any): string | undefined {
if (!authorizationModes) return undefined;
const defaultLambda = authorizationModes.defaultAuthentication?.lambdaAuthorizerConfig?.lambdaFunction;
if (defaultLambda) return defaultLambda;
for (const provider of authorizationModes.additionalAuthenticationProviders ?? []) {
if (provider.authenticationType === 'AWS_LAMBDA' && provider.lambdaAuthorizerConfig?.lambdaFunction) {
return provider.lambdaAuthorizerConfig.lambdaFunction;
}
}
return undefined;
}

/** Extracts additional auth providers from the raw AppSync API object. */
private extractAdditionalAuthProviders(graphqlApi: GraphqlApi): Record<string, unknown>[] | undefined {
return graphqlApi.additionalAuthenticationProviders?.map((provider) => ({
Expand Down
Loading
Loading