feat(gen2-migration): generate per-table stacks for multiple DDB tables#14688
Merged
iliapolo merged 22 commits intogen2-migrationfrom Mar 24, 2026
Merged
feat(gen2-migration): generate per-table stacks for multiple DDB tables#14688iliapolo merged 22 commits intogen2-migrationfrom
iliapolo merged 22 commits intogen2-migrationfrom
Conversation
Previously, all DynamoDB tables were placed in a single shared storage
stack, causing conflicts when multiple tables existed. Each DDB table
now gets its own nested stack via backend.createStack('storage<name>'),
matching the Gen1 nested stack naming convention.
Also fixes resolveOutputs() crash when a Gen2 storage stack has no
Outputs section (happens when no cross-stack references exist for a
table).
Closes #14608, #14597
…ture data Recapture discussions app snapshots from live deployments: - Gen1: amplify-discussionsblade-blade-4edfd (activity + bookmarks tables) - Gen2: amplify-d1skq8aomhb772-e2etest-branch (per-table stacks) Pre-generate inputs use real amplify-pull data for bookmarks resource. Pre-refactor templates fetched from deployed CloudFormation stacks. Post-generate and post-refactor regenerated by test framework. Also adds bookmarks to migration-config.json and fixes snapshot.ts to use TemplateStage: Original for unprocessed templates.
Replace raw app ID d1skq8aomhb772 with sanitized name 'discussions' in all snapshot file contents and filenames.
9pace
commented
Mar 18, 2026
…er-table-stacks # Conflicts: # amplify-migration-apps/discussions/README.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Re-deployed discussions app with 3 storage types (activity DDB, bookmarks DDB, avatars S3) and captured fresh snapshots for all 4 stages. Per-table stacks refactor verified working for both DDB tables. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The S3 forward/rollback refactorers used findNestedStack with a bare
'storage' prefix, which matched DDB per-table stacks (e.g.
'storageactivity') before the S3 stack ('storage0EC3F24A'). Fixed by
using 'storage' + resourceName for Gen1 lookup and a new
findS3NestedStack method that distinguishes the CDK-hashed S3 stack
from lowercase-prefixed DDB stacks for Gen2 lookup.
Also refreshes discussions snapshots from a clean main/gen2-main deploy.
9pace
commented
Mar 23, 2026
9pace
commented
Mar 23, 2026
- Replace fragile char-based findS3NestedStack with template-based S3 detection (fetch template, check for AWS::S3::Bucket resource) - Export findS3NestedStack from storage-forward.ts, import in rollback - Remove dead STORAGE_RESOURCE_TYPES export - Remove storage:S3 from validateSingleResourcePerStack (only one defineStorage() possible) - Make scopeVarName required (no default) in DynamoDBRenderer - Set Outputs default empty object in cfn-output-resolver, use templateOutputs consistently - Add comments for optional Outputs in cfn-template.ts and resolver
Keep S3 validation as a defensive spot check even though the collision can't happen in practice (JSON key uniqueness prevents same-name resources within a category).
Resolved conflicts: - refactor.ts: pass both logger and resourceName to storage constructors - category-plan-orchestration.test.ts: use noOpLogger() + resourceName, adopt upstream error messages (throws on missing stacks) - refactor.test.ts: use step.forward() with per-stack validation message
… script Extends the discussions gen1 test script to cover all stateful resources that get refactored during migration: S3 avatars bucket (upload/getUrl/remove) and bookmarks DynamoDB table (put/get/delete via AWS SDK). Verified with full forward→rollback→forward round-trip on live app.
…sed table lookup Remove ListTablesCommand discovery in favor of reading table name from amplifyconfiguration.json. Share a single DynamoDBDocumentClient across all bookmark test functions instead of creating one per call.
Remove .gitignore that ignored local dev helper scripts (add-bookmarks.ts, deploy-gen1.ts) that no longer exist.
…solution backend-only and discussions were missing typescript as a devDependency, causing npx tsc to fall back to the root tsc v4.9.5 which doesn't support moduleResolution:"bundler". Also restores monorepo metadata in discussions snapshot package.json files.
a91fce3 to
a514ec7
Compare
…pshots
Replace "Your verification code is {####}" with "Here is your verification code
{####}" to match the discussions README instructions, preventing drift when
snapshots are regenerated.
Only email verification fields should use the README-specified message. SMS fields should retain their original values.
iliapolo
reviewed
Mar 24, 2026
iliapolo
approved these changes
Mar 24, 2026
iankhou
pushed a commit
that referenced
this pull request
Mar 26, 2026
…es (#14688) * feat: avatar s3 feature for discussions app * feat(cli): generate per-table stacks for multiple DDB tables Previously, all DynamoDB tables were placed in a single shared storage stack, causing conflicts when multiple tables existed. Each DDB table now gets its own nested stack via backend.createStack('storage<name>'), matching the Gen1 nested stack naming convention. Also fixes resolveOutputs() crash when a Gen2 storage stack has no Outputs section (happens when no cross-stack references exist for a table). Closes #14608, #14597 * fix(discussions): replace hand-crafted snapshots with real infrastructure data Recapture discussions app snapshots from live deployments: - Gen1: amplify-discussionsblade-blade-4edfd (activity + bookmarks tables) - Gen2: amplify-d1skq8aomhb772-e2etest-branch (per-table stacks) Pre-generate inputs use real amplify-pull data for bookmarks resource. Pre-refactor templates fetched from deployed CloudFormation stacks. Post-generate and post-refactor regenerated by test framework. Also adds bookmarks to migration-config.json and fixes snapshot.ts to use TemplateStage: Original for unprocessed templates. * docs(discussions): add bookmarks table setup instructions to README * fix(discussions): sanitize Amplify App ID in Gen2 snapshot files Replace raw app ID d1skq8aomhb772 with sanitized name 'discussions' in all snapshot file contents and filenames. * docs(discussions): add S3 avatars bucket to migration config Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(discussions): update snapshots with S3 avatars + bookmarks DDB Re-deployed discussions app with 3 storage types (activity DDB, bookmarks DDB, avatars S3) and captured fresh snapshots for all 4 stages. Per-table stacks refactor verified working for both DDB tables. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cli): disambiguate S3 nested stack from DDB per-table stacks The S3 forward/rollback refactorers used findNestedStack with a bare 'storage' prefix, which matched DDB per-table stacks (e.g. 'storageactivity') before the S3 stack ('storage0EC3F24A'). Fixed by using 'storage' + resourceName for Gen1 lookup and a new findS3NestedStack method that distinguishes the CDK-hashed S3 stack from lowercase-prefixed DDB stacks for Gen2 lookup. Also refreshes discussions snapshots from a clean main/gen2-main deploy. * fix(cli): address PR review comments for per-table stacks - Replace fragile char-based findS3NestedStack with template-based S3 detection (fetch template, check for AWS::S3::Bucket resource) - Export findS3NestedStack from storage-forward.ts, import in rollback - Remove dead STORAGE_RESOURCE_TYPES export - Remove storage:S3 from validateSingleResourcePerStack (only one defineStorage() possible) - Make scopeVarName required (no default) in DynamoDBRenderer - Set Outputs default empty object in cfn-output-resolver, use templateOutputs consistently - Add comments for optional Outputs in cfn-template.ts and resolver * fix(cli): restore storage:S3 case in validateSingleResourcePerStack Keep S3 validation as a defensive spot check even though the collision can't happen in practice (JSON key uniqueness prevents same-name resources within a category). * feat(cli): add S3 avatars and bookmarks DDB tests to discussions test script Extends the discussions gen1 test script to cover all stateful resources that get refactored during migration: S3 avatars bucket (upload/getUrl/remove) and bookmarks DynamoDB table (put/get/delete via AWS SDK). Verified with full forward→rollback→forward round-trip on live app. * refactor(cli): clean up bookmarks test - shared DDB client, config-based table lookup Remove ListTablesCommand discovery in favor of reading table name from amplifyconfiguration.json. Share a single DynamoDBDocumentClient across all bookmark test functions instead of creating one per call. * chore(cli): remove dev-only .gitignore from amplify-cli package Remove .gitignore that ignored local dev helper scripts (add-bookmarks.ts, deploy-gen1.ts) that no longer exist. * fix(cli): add typescript devDep to fix typecheck for bundler moduleResolution backend-only and discussions were missing typescript as a devDependency, causing npx tsc to fall back to the root tsc v4.9.5 which doesn't support moduleResolution:"bundler". Also restores monorepo metadata in discussions snapshot package.json files. * fix: use README-specified emailVerificationMessage in discussions snapshots Replace "Your verification code is {####}" with "Here is your verification code {####}" to match the discussions README instructions, preventing drift when snapshots are regenerated. * fix: replace remaining old verification message in discussions snapshots * fix: align gen2 branch verification messages with README * fix: revert SMS verification messages to original values Only email verification fields should use the README-specified message. SMS fields should retain their original values. * fix: remove trailing newlines from parameters files * fix: remove unnecessary typescript devDependency from migration apps --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
storage<resourceName>) instead of a single sharedstoragestack, matching Gen1's per-resource naming and enabling independent refactor/rollback of each table.resourceNamethrough DDB and S3 forward/rollback refactorers for per-table stack lookups.findNestedStack(facade, 'storage')ambiguously matched DDB per-table stacks (e.g.storageactivity). NewfindS3NestedStackdistinguishes the CDK-hashed S3 stack from lowercase DDB stacks.validateSingleResourcePerStackreplacesvalidateSingleResourcePerCategory, rejecting only when multiple resources target the same stack.resolveOutputs()handles missingOutputssection (CDK omits it when there are no cross-stack references).typescriptdevDependency tobackend-onlyanddiscussionssonpx tscuses TS 5+ (required formoduleResolution: "bundler"in Gen2 tsconfigs).E2E Verification
Discussions app: auth, API, 2 DDB tables (activity, bookmarks), S3 (avatars), 2 lambdas. The bookmarks table has no frontend — it exercises the no-Outputs case where CDK omits the Outputs section from the nested stack template.
The avatars frontend:
createStack('storageactivity')+createStack('storagebookmarks')+ S3storageactivityA346F297,storagebookmarks210DAF62,storage0EC3F24ATest plan
yarn buildandtypecheck-migration-appspass locallyCloses #14608, #14597