Summary
A change to a Custom::CDKBucketDeployment's SourceObjectKeys (i.e. new content was bundled — the everyday case for a static site) is classified by cloudformation-diff as MAY_REPLACE. In src/diff.ts (L148–159) MAY_REPLACE is pushed to destructiveChanges, so:
- the comment renders a
***Destructive Changes*** :bangbang: warning, and
- with the default
failOnDestructiveChanges: true, the job fails on every content-only PR.
Effectively, the destructive gate is unusable for any app that ships content through BucketDeployment or otherwise has asset-hash-only churn.
Example (a PR that changed no infrastructure — only a bundled asset hash moved):
> ***Destructive Changes*** :bangbang:
> Resource: ...deployCustomResource... - Impact: MAY_REPLACE
[~] Custom::CDKBucketDeployment ... may be replaced
└─ [~] SourceObjectKeys (may cause replacement)
└─ [-] "7f7312…zip" [+] "c6f703…zip"
Why this is inconsistent today
src/diff.ts (L119–129) already exempts AWS::Lambda::Function whose only changes are Code/Metadata, returning before the destructive-change push. So Lambda asset churn is correctly ignored — but the identical situation for Custom::CDKBucketDeployment SourceObjectKeys (and S3Key/CodeHash generally) is not, and instead trips the destructive gate. Related: #161 (the Lambda exemption already surprises users on the count side); #4 ("Summarize non-asset changes") is the original intent this extends.
Proposal
Opt-in ignoreAssetChanges (boolean, default false): before counting/classification, drop any resource difference whose property updates are entirely CDK asset hashes (S3Key, SourceObjectKeys, CodeHash, Lambda Code/Metadata). Applied to the TemplateDiff itself, it fixes the destructive flag, the counts, and the rendered body in one place (today's Lambda special-case only touches counts). Mixed-change resources are left fully intact.
DifferenceCollection.filter()/.remove() + ResourceDifference.differenceCount make this straightforward.
Optional follow-up: ignoreResourcePaths (logical-id/glob list) for the general case.
I'm happy to open the PR: input wiring (inputs.ts/action.yml), the filter pass, and tests (diff.test.ts/stage-processor.test.ts) — including a Custom::CDKBucketDeployment MAY_REPLACE case asserting it no longer gates. Would you accept this, and do you have a preference on the knob shape/naming?
Summary
A change to a
Custom::CDKBucketDeployment'sSourceObjectKeys(i.e. new content was bundled — the everyday case for a static site) is classified bycloudformation-diffasMAY_REPLACE. Insrc/diff.ts(L148–159)MAY_REPLACEis pushed todestructiveChanges, so:***Destructive Changes*** :bangbang:warning, andfailOnDestructiveChanges: true, the job fails on every content-only PR.Effectively, the destructive gate is unusable for any app that ships content through
BucketDeploymentor otherwise has asset-hash-only churn.Example (a PR that changed no infrastructure — only a bundled asset hash moved):
Why this is inconsistent today
src/diff.ts(L119–129) already exemptsAWS::Lambda::Functionwhose only changes areCode/Metadata, returning before the destructive-change push. So Lambda asset churn is correctly ignored — but the identical situation forCustom::CDKBucketDeploymentSourceObjectKeys(andS3Key/CodeHashgenerally) is not, and instead trips the destructive gate. Related: #161 (the Lambda exemption already surprises users on the count side); #4 ("Summarize non-asset changes") is the original intent this extends.Proposal
Opt-in
ignoreAssetChanges(boolean, defaultfalse): before counting/classification, drop any resource difference whose property updates are entirely CDK asset hashes (S3Key,SourceObjectKeys,CodeHash, LambdaCode/Metadata). Applied to theTemplateDiffitself, it fixes the destructive flag, the counts, and the rendered body in one place (today's Lambda special-case only touches counts). Mixed-change resources are left fully intact.DifferenceCollection.filter()/.remove()+ResourceDifference.differenceCountmake this straightforward.Optional follow-up:
ignoreResourcePaths(logical-id/glob list) for the general case.I'm happy to open the PR: input wiring (
inputs.ts/action.yml), the filter pass, and tests (diff.test.ts/stage-processor.test.ts) — including aCustom::CDKBucketDeploymentMAY_REPLACEcase asserting it no longer gates. Would you accept this, and do you have a preference on the knob shape/naming?