Skip to content

feat(gen2-migration): detecting service type to distinguish between cdk and cfn custom resources#14410

Closed
sanjanaravikumar-az wants to merge 9 commits intogen2-migrationfrom
sanjrkmr/cfn-service-type-detection
Closed

feat(gen2-migration): detecting service type to distinguish between cdk and cfn custom resources#14410
sanjanaravikumar-az wants to merge 9 commits intogen2-migrationfrom
sanjrkmr/cfn-service-type-detection

Conversation

@sanjanaravikumar-az
Copy link
Copy Markdown
Contributor

Overview

This PR adds service type detection for custom resources during Gen1 to Gen2 migration. It introduces the ability to distinguish between CDK-based (customCDK) and CloudFormation-based (customCloudformation) custom resources.

Key Changes

  1. Custom Resource Service Type Detection (command-handlers.ts)
  • Added CustomResourceServiceType type to distinguish between customCDK and customCloudformation resources
  • Added getCustomResourcesWithType() function that reads from amplify-meta.json and returns a map of resource names to their service types
  • This enables different handling paths for CDK vs CloudFormation custom resources during migration
  1. API Key Attribute Mapping Fix (amplify-helper-transformer.ts)
  • Reverted GraphQLAPIKeyOutput mapping back to cfnResources.cfnGraphqlApi.attrApiKey
  • Removed incorrect comment about CfnApiKey construct

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@sanjanaravikumar-az sanjanaravikumar-az requested a review from a team as a code owner December 24, 2025 07:53

type CustomResourceServiceType = 'customCDK' | 'customCloudformation';

const getCustomResourcesWithType = (): Map<string, CustomResourceServiceType> => {

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused variable getCustomResourcesWithType.

Copilot Autofix

AI 4 months ago

To fix the problem, remove the unused function getCustomResourcesWithType. This eliminates the unused binding and any dead logic inside it, without affecting existing functionality, because nothing currently depends on it.

Concretely:

  • In packages/amplify-cli/src/commands/gen2-migration/codegen-generate/src/codegen-head/command-handlers.ts, delete the entire getCustomResourcesWithType declaration (lines 327–338 in the snippet), keeping the surrounding type CustomResourceServiceType and getCustomResources definitions intact.
  • No imports, exports, or other definitions need to be added or changed, since the function is local and not referenced.
Suggested changeset 1
packages/amplify-cli/src/commands/gen2-migration/codegen-generate/src/codegen-head/command-handlers.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/amplify-cli/src/commands/gen2-migration/codegen-generate/src/codegen-head/command-handlers.ts b/packages/amplify-cli/src/commands/gen2-migration/codegen-generate/src/codegen-head/command-handlers.ts
--- a/packages/amplify-cli/src/commands/gen2-migration/codegen-generate/src/codegen-head/command-handlers.ts
+++ b/packages/amplify-cli/src/commands/gen2-migration/codegen-generate/src/codegen-head/command-handlers.ts
@@ -324,19 +324,6 @@
 
 type CustomResourceServiceType = 'customCDK' | 'customCloudformation';
 
-const getCustomResourcesWithType = (): Map<string, CustomResourceServiceType> => {
-  const meta = stateManager.getMeta();
-  const customCategory = meta?.custom;
-  const resourceMap = new Map<string, CustomResourceServiceType>();
-
-  if (customCategory) {
-    Object.entries(customCategory).forEach(([name, config]: [string, { service: CustomResourceServiceType }]) => {
-      resourceMap.set(name, config.service);
-    });
-  }
-  return resourceMap;
-};
-
 const getCustomResources = (): string[] => {
   const meta = stateManager.getMeta();
   const customCategory = meta?.custom;
EOF
@@ -324,19 +324,6 @@

type CustomResourceServiceType = 'customCDK' | 'customCloudformation';

const getCustomResourcesWithType = (): Map<string, CustomResourceServiceType> => {
const meta = stateManager.getMeta();
const customCategory = meta?.custom;
const resourceMap = new Map<string, CustomResourceServiceType>();

if (customCategory) {
Object.entries(customCategory).forEach(([name, config]: [string, { service: CustomResourceServiceType }]) => {
resourceMap.set(name, config.service);
});
}
return resourceMap;
};

const getCustomResources = (): string[] => {
const meta = stateManager.getMeta();
const customCategory = meta?.custom;
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you address this as either true positive or false positive?

Copy link
Copy Markdown
Contributor

@iankhou iankhou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but difficult for me to verify functionality by looking at it. How was it tested?

We are making a lot of changes to transformations here. I think it would be good to have unit tests that cover functionality introduced by the new parameter resourceDependencies.


type CustomResourceServiceType = 'customCDK' | 'customCloudformation';

const getCustomResourcesWithType = (): Map<string, CustomResourceServiceType> => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you address this as either true positive or false positive?

Comment on lines +514 to +537
for (const resource of customResources) {
const cdkStackFilePath = path.join(destinationCustomResourcePath, resource, 'cdk-stack.ts');

try {
const cdkStackContent = await fs.readFile(cdkStackFilePath, { encoding: 'utf-8' });
const dependencies: string[] = [];

// Parse for AmplifyHelpers.addResourceDependency calls
const dependencyRegex = /AmplifyHelpers\.addResourceDependency\s*\([^,]+,[^,]+,[^,]+,\s*\[([^\]]+)\]/g;
let match;

while ((match = dependencyRegex.exec(cdkStackContent)) !== null) {
const dependenciesArray = match[1];

// Extract category values from dependency objects
const categoryRegex = /category:\s*['"]([^'"]+)['"]/g;
let categoryMatch;

while ((categoryMatch = categoryRegex.exec(dependenciesArray)) !== null) {
const category = categoryMatch[1];
if (!dependencies.includes(category)) {
dependencies.push(category);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this kind of logic I would generally like to see some kind of test, since regex is not verifiable by reading it (at least not by me). A unit test may be sufficient for now.

`throw new Error('Follow https://docs.amplify.aws/react/start/migrate-to-gen2/ to update the resource dependency');\n\nexport class`,
);
}
// AmplifyHelpers.addResourceDependency is now supported by the transformer
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

@iliapolo iliapolo changed the title feat: detecting service type to distinguish between cdk and cfn custom resources feat(gen2-migration): detecting service type to distinguish between cdk and cfn custom resources Dec 30, 2025
@sanjanaravikumar-az sanjanaravikumar-az marked this pull request as draft March 19, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants