Skip to content

fix(toolkit-lib): change-set diff hides an added key in a JSON string with an intrinsic - #2042

Merged
iliapolo merged 23 commits into
mainfrom
fix/2036-changeset-omits-json-key
Oct 16, 2026
Merged

iliapolo merged 23 commits into
mainfrom
fix/2036-changeset-omits-json-key

Conversation

@9pace

@9pace 9pace commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2036

This covers a regression described in the above issue: cdk diff says "There were no differences" when a JSON string built with an intrinsic only gains a key.

For reference I will take the following example:

const value = { stack: Aws.STACK_NAME, a: '1', b: '2' }; // b is the new key
new ssm.StringParameter(this, 'Param', { stringValue: this.toJsonString(value) });
Value:
  Fn::Join: ["", ['{"stack":"', {Ref: AWS::StackName}, '","a":"1","b":"2"}']]   # was '","a":"1"}'

The change-set diff compares the two templates, then asks CloudFormation which resources will change and trusts its answer. Since #1668 it asks with IncludePropertyValues, so that it can also show changes that only happen at deploy time (#641). The same change set described both ways (output trimmed):

## IncludePropertyValues=False
   Status=CREATE_COMPLETE StatusReason=None
   Changes=[('Modify', 'Param165332EC', ['Value'])]
## IncludePropertyValues=True
   Status=CREATE_COMPLETE StatusReason=None
   Changes=[]

With IncludePropertyValues, CloudFormation leaves the change out and gives no warning. An internal ticket tracks this with CloudFormation. It happens whenever a JSON string only gains a key, only reorders its keys, or only changes whitespace. If the same resource has another change too, CloudFormation still lists the resource, but only with the other change. The JSON property is missing from it.

The diff then hides the change because of a rule in the merger:
a property change that the change set does NOT contain is treated as unchanged when the value contains Ref, Fn::* or {{resolve:...}}.

This rule is there for rewrites that resolve to the same value, such as a Fn::Join turned into an equivalent Fn::Sub, which CloudFormation correctly leaves out. #1951 already keeps static values; for example a static JSON string that gains a key is still shown. In the example, if the Ref resolved to a different value as well, an existing key would change, CloudFormation would list the resource, and the diff would show it.

These cases were shown up to 2.1128.1, the last release before #1668. Back then the merger already treated a change missing from the change set as unchanged (until #1951 even for static values), but the diff described the change set without IncludePropertyValues, and CloudFormation includes these changes in a description without it.

Change to the JSON Example 2.1145.0 This PR
gains a key with a fixed value b: '2' added hidden shown
gains a key with a token value region: Aws.REGION added hidden shown
keys reordered { a, stack } instead of { stack, a } hidden shown
an existing value changes a: '2' shown shown
rewritten to the same resolved value Fn::Join to Fn::Sub hidden hidden

The fix leaves the merger's behaviour as it is. Before the diff uses the change set described with IncludePropertyValues, it checks whether the merger would treat any template difference as unchanged because the change set leaves it out. Only then is the change set described again without IncludePropertyValues, and what the first description left out is merged back in (mergeDescriptions from #1785). A rewrite like the last row is missing from both descriptions, so it stays hidden.

The check has to run in ChangeSetDescriber because cloudformation-diff makes no AWS calls, and cdk diff deletes the change set before it calls fullDiff. The second DescribeChangeSet only happens when a template difference would otherwise be hidden.

Not covered here:

The integ tests added cover every row of the table, and a key added while the parameter's description also changes. Rows 1, 2 and 3 and that last case fail as expected on 2.1145.0.

Checklist

  • This change contains a major version upgrade for a dependency and I confirm all breaking changes are addressed
    • Release notes for the new version:

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

… with an intrinsic

Since #1668 diff change sets are described with IncludePropertyValues, and CloudFormation can
leave resource changes out of that response without the incomplete-data warning. Describe every
created change set a second time without property values and merge in what the first
description left out.

Fixes #2036
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@aws-cdk-automation
aws-cdk-automation requested a review from a team October 13, 2026 20:06
@9pace
9pace deployed to no-approval October 13, 2026 20:06 — with GitHub Actions Active
…uld hide a template difference

Replace the unconditional second describe with a check against the templates: a created change
set is described again without IncludePropertyValues only when the merger would otherwise treat a
template difference with a deploy-time value as unchanged. The check is exported from
cloudformation-diff as resourcesHiddenByChangeSet and shares its rule with the merger.

Adds integ tests for a key with a token value, reordered keys, and a rewrite that resolves to the
same value.

Fixes #2036
Comment thread packages/@aws-cdk/toolkit-lib/lib/api/change-sets/change-set-describer.ts Outdated
Comment thread packages/@aws-cdk/cloudformation-diff/lib/diff-template.ts Outdated
Comment thread packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts Outdated
Comment thread packages/@aws-cdk/cloudformation-diff/test/diff-template.test.ts Outdated
Comment thread packages/@aws-cdk/toolkit-lib/lib/api/change-sets/change-set-describer.ts Outdated

This branch had an error being deployed

1 failed (outdated), 1 active, and 1 inactive deployments
run-tests — 4faf7b37 Deployed Oct 16, 2026 by 9pace via integ_cli (cli-integ-tests, 24.19, 11) #7196
no-approval — 4faf7b37 Deployed Oct 16, 2026 by 9pace via prepare #7196
automation — 3f68c644 Deployed Oct 13, 2026 by 9pace via Set AutoQueue on PR #2042 #3728
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(diff): change-set diff hides added key in JSON string property containing intrinsics

4 participants