Skip to content

fix: skip CDK-managed singletons in ResourcePrefixAspect#1702

Merged
toddhainsworth merged 2 commits into
mainfrom
feature/resource-prefix-skip-cdk-managed-singletons
Jun 5, 2026
Merged

fix: skip CDK-managed singletons in ResourcePrefixAspect#1702
toddhainsworth merged 2 commits into
mainfrom
feature/resource-prefix-skip-cdk-managed-singletons

Conversation

@toddhainsworth

@toddhainsworth toddhainsworth commented Jun 4, 2026

Copy link
Copy Markdown
Member

Summary

ResourcePrefixAspect assigned deterministic, logical-id-derived physical names to CDK-managed singleton/framework resources — notably the BucketDeployment custom-resource handler and its nested IAM service role and log group. Because these singletons share a fixed logical id across every stack, the prefixed name collapses to a single value per prefix scope, removing the per-stack and per-creation uniqueness CloudFormation normally provides. This caused two distinct deploy failures.

Failure mode 1 (severe): cross-stack IAM role collision

Two BucketDeployment-using stacks in the same stage/brand received the same account-global RoleName, so the second stack failed:

CREATE_FAILED | AWS::IAM::Role | ...CustomCDKBucketDeployment8693-... already exists

Version-independent (the aspect has set explicit RoleName/FunctionName on these singletons since ≥ 0.5.7).

Failure mode 2: orphaned /aws/lambda LogGroup collision on retry

The handler runs during deploy; the Lambda service auto-creates /aws/lambda/<fn>. A failed/rolled-back deploy orphans that group (CFN never owned it, so cdk destroy doesn't clear it), and the deterministic function name regenerates the identical name on retry:

Resource of type 'AWS::Logs::LogGroup' with identifier
'.../aws/lambda/...-CustomCDKBucketDeployment8693-<hash>' already exists.

Surfaced after 0.6.1 (which correctly stopped mangling /aws/ log group names — that fix exposed the latent collision).

Fix

  • Extract the singleton path-fragment list + isCdkManagedSingleton helper into a new internal lib/cdk-managed-singletons.ts — single source of truth.
  • MicroserviceChecks refactored to consume it (behaviour-preserving).
  • ResourcePrefixAspect.visit() skips these resources, leaving their physical names CloudFormation-generated. The path-includes skip covers the handler and its nested children (IAM service role, log group), resolving both failure modes at once. Keeps the 0.6.1 /aws/ log-group fix intact.

Covered singletons: Custom::CDKBucketDeployment, LogRetention, Custom::S3AutoDeleteObjects, cr.Provider (AWS679f53fac002430cb0da5b7982bd2287).

Testing

  • TDD (red → green). Behaviour tests assert the BucketDeployment handler lambda, its IAM service role, and the S3AutoDeleteObjects handler all keep CloudFormation-generated names.
  • Verified against the unfixed aspect that the role/function were previously pinned to myapp-CustomCDKBucketDeployment8693-....
  • build + test (58 passed) + lint all green.

Changeset

@aligent/cdk-aspects: patch

ResourcePrefixAspect pinned deterministic physical names onto CDK-managed
singleton/framework resources (BucketDeployment handler, LogRetention,
S3AutoDeleteObjects, cr.Provider lambdas). That removed CloudFormation's
random-suffix orphan-avoidance, so a failed deploy could orphan the
service-created /aws/lambda/<fn> log group and wedge every subsequent
deploy on 'AWS::Logs::LogGroup ... already exists'.

Extract the shared singleton path-fragment list and isCdkManagedSingleton
helper into lib/cdk-managed-singletons.ts, consumed by both MicroserviceChecks
and ResourcePrefixAspect, and skip these resources during prefixing.
@toddhainsworth toddhainsworth marked this pull request as ready for review June 4, 2026 23:08
@toddhainsworth toddhainsworth requested a review from a team as a code owner June 4, 2026 23:08
The path-fragment skip already covers the singleton handler's nested IAM
service role and log group, resolving the cross-stack IAM role collision
(account-global RoleName identical across stacks) alongside the log group
orphan collision. Add a regression test asserting the role keeps its
CloudFormation-generated name, and expand the README and changeset to
document both failure modes.

@kai-nguyen-aligent kai-nguyen-aligent left a comment

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.

Wow, you're faster than me, Todd. I had this in my list but you beat me ❤️

@toddhainsworth toddhainsworth merged commit 9565808 into main Jun 5, 2026
8 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 5, 2026
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