Skip to content

BucketDeployment asset-hash changes are flagged MAY_REPLACE → destructive gate blocks routine content PRs #162

Description

@laazyj

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions