cdk-diff-report
v1.6.0
Published
Automated AWS CDK infrastructure diff for pull requests. Posts a formatted summary of added, modified, removed, and replaced resources to GitHub, GitLab, and Bitbucket PRs/MRs. Free and open source. Cost, security, and policy analysis available via the Ia
Maintainers
Readme
cdk-diff-report
Review AWS CDK infrastructure changes directly in your pull requests.
cdk-diff-report runs cdk diff in your CI pipeline, summarizes which
resources each stack will add, modify, replace, or remove, and posts that
summary as a comment on the pull request. On every new push it updates the same
comment instead of adding another one. It works with GitHub, GitLab, and
Bitbucket, and is free and open source under the MIT license.
Contents
- Why use it
- What the comment looks like
- Requirements
- Getting started with GitHub Actions
- Getting started with GitLab CI/CD
- Getting started with Bitbucket Pipelines
- Running the CLI locally or in other CI systems
- Command-line reference
- Configuration
- Passing CDK context
- Hiding changes you do not need to review
- Reading the report
- Exit codes
- Troubleshooting
- Using it as a library
- IaCReview plan
- License
Why use it
Raw cdk diff output is long, easy to miss in CI logs, and hard to read for
reviewers who are not CDK specialists. cdk-diff-report turns it into a short,
structured summary on the pull request, where the review happens:
- A per-stack breakdown of added, modified, replaced, and removed resources.
- Replacements called out explicitly, with the property that triggers them.
- IAM and security group changes flagged for closer review.
- Optional filters that hide noise such as tag-only changes.
- One comment per pull request, updated in place on every push.
- An optional standalone HTML report you can keep as a CI artifact.
- Available as a GitHub Action, a command-line tool, and a Node.js library.
What the comment looks like
A pull request that touches two of three stacks produces a comment like this:
CDK Diff Report
This pull request changes 5 resources in 2 of 3 stacks.
> Security review required. IAM or security group changes were detected in
> PipelineStack. Review the full cdk diff output before approving this pull request.
> Resource replacement. 1 resource will be replaced. CloudFormation creates a new
> resource and deletes the existing one, which can cause downtime or data loss
> for stateful resources.
| Added | Modified | Replaced | Removed |
|-------|----------|----------|---------|
| 2 | 1 | 1 | 1 |
Changes by stack
PipelineStack: 2 added, 1 modified, 1 removed; IAM changes
| Change | Logical ID | Resource type | Details |
| Removed | LegacyQueue | AWS::SQS::Queue | |
| Modified | ApiHandler | AWS::Lambda::Function | Changed: Code, MemorySize |
| Added | DeployRole | AWS::IAM::Role | |
| Added | Build | AWS::CodeBuild::Project | |
DataStack: 1 replaced
| Replaced | Sessions | AWS::DynamoDB::Table | Replacement caused by TableName |
Stacks without changes: MonitoringStackOn GitHub and GitLab, each stack is a collapsible section so long reports stay readable. Within a stack, the riskiest changes are listed first.
Requirements
- Node.js 18 or later.
- AWS CDK CLI v2 available as
cdkon thePATH. Install it globally withnpm install -g aws-cdk. Installing it only as a project dependency is not enough, becausenode_modules/.binis not on thePATHin most CI steps. - AWS credentials that can run
cdk diffagainst your target accounts. These are the same credentials you would use to runcdk difflocally. In a bootstrapped environment, permission to assume the CDK bootstrap lookup role is usually sufficient. Read-only credentials are recommended. - A token for your Git platform with permission to comment on pull requests. See the platform sections below.
Getting started with GitHub Actions
Add a workflow such as .github/workflows/cdk-diff.yml:
name: CDK diff
on:
pull_request:
permissions:
contents: read
pull-requests: write # required to post the comment
id-token: write # only needed for AWS OIDC authentication
jobs:
cdk-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies and the CDK CLI
run: |
npm ci
npm install -g aws-cdk
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/cdk-diff-readonly
aws-region: eu-central-1
- name: Post CDK diff report
uses: dzon337/cdk-diff-report@v1The action posts the comment with the workflow's built-in token, so no extra
secret is needed. If you authenticate to AWS with access keys instead of OIDC,
replace the credentials step with AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
and AWS_DEFAULT_REGION environment variables from repository secrets.
Action inputs
| Input | Description | Default |
|-------|-------------|---------|
| cdk-args | Arguments passed to cdk diff, separated by commas, such as stack names: MyStack,OtherStack. | empty (every stack) |
| context | CDK context values, one key=value pair per line. | empty |
| ignore-properties | Comma-separated properties to ignore, for example Tags,Metadata. See Hiding changes. | empty |
| ignore-resource-types | Comma-separated resource types to hide. * is a wildcard. | empty |
| working-directory | Directory that contains cdk.json. | . |
| html-output | Path for a standalone HTML report, relative to working-directory. Leave empty to skip. | empty |
| dry-run | Set to true to print the comment to the log without posting it. | false |
| github-token | Token used to post the comment. Needs the pull-requests: write permission. | workflow token |
| version | Version of the cdk-diff-report CLI to install. Set latest to always use the newest release. | version of the action release |
| node-version | Node.js version used by the action. Must be 18 or later. | 20 |
The action also accepts inputs for the IaCReview plan (api-key, api-url,
environment, fail-on-block, sarif-output, and ai-fixes). These have no
effect without an IaCReview API key. See IaCReview plan.
Context and filters in the action
Pass CDK context with context, one pair per line, and hide noise with the
two ignore inputs:
- name: Post CDK diff report
uses: dzon337/cdk-diff-report@v1
with:
context: |
stage=dev
version=1.2.3
ignore-properties: Tags,Metadata
ignore-resource-types: AWS::CDK::MetadataThe same settings can also live in a .cdkdiffreportrc file. See
Configuration.
Getting started with GitLab CI/CD
- Create a project access token with the
apiscope and add it as a masked CI/CD variable namedGITLAB_TOKEN. The defaultCI_JOB_TOKENusually cannot create merge request comments. - Add your AWS credentials as CI/CD variables.
- Add a job to
.gitlab-ci.yml:
cdk-diff:
image: node:20
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
CDK_DIFF_PLATFORM: gitlab
AWS_DEFAULT_REGION: eu-central-1
script:
- npm ci
- npm install -g aws-cdk cdk-diff-report
- cdk-diff-reportThe job must run in a merge request pipeline. GitLab sets CI_PROJECT_ID,
CI_MERGE_REQUEST_IID, and CI_API_V4_URL automatically in those pipelines,
including on self-managed instances.
Getting started with Bitbucket Pipelines
- Create a repository access token with the Pull requests: Write scope and
add it as a secured repository variable named
BITBUCKET_ACCESS_TOKEN. - Add your AWS credentials as secured repository variables.
- Add a pull request pipeline to
bitbucket-pipelines.yml:
pipelines:
pull-requests:
'**':
- step:
name: CDK diff
image: node:20
script:
- export CDK_DIFF_PLATFORM=bitbucket
- npm ci
- npm install -g aws-cdk cdk-diff-report
- cdk-diff-reportBitbucket sets BITBUCKET_PR_ID, BITBUCKET_WORKSPACE, and
BITBUCKET_REPO_SLUG automatically in pull request pipelines.
Running the CLI locally or in other CI systems
Install the CLI globally, or run it with npx:
npm install -g cdk-diff-report
cd path/to/your/cdk-app
cdk-diff-report --dry-run--dry-run runs the diff and prints the comment to your terminal without
posting anything, which is the easiest way to preview the output.
In CI systems other than the three above (for example AWS CodeBuild or Jenkins), set the variables the target platform would normally provide:
| Platform | Required variables |
|----------|--------------------|
| GitHub | GITHUB_TOKEN, GITHUB_REPOSITORY (owner/repo), GITHUB_REPOSITORY_OWNER, GITHUB_PR_NUMBER. Set GITHUB_API_URL for GitHub Enterprise Server. |
| GitLab | GITLAB_TOKEN, CI_PROJECT_ID, CI_MERGE_REQUEST_IID. Set CI_API_V4_URL or gitlabApiUrl for self-managed GitLab. |
| Bitbucket | BITBUCKET_ACCESS_TOKEN, BITBUCKET_PR_ID, BITBUCKET_WORKSPACE, BITBUCKET_REPO_SLUG. The workspace and repository can also be set with workspace and repoSlug. |
Remember to set CDK_DIFF_PLATFORM as well, because the default platform is
bitbucket.
Command-line reference
cdk-diff-report [options]| Option | Description |
|--------|-------------|
| --dry-run | Run the diff and print the comment without posting it. Alias: --dry. |
| --markdown | With --dry-run, print the raw markdown instead of the formatted terminal preview. Useful for saving to a file. |
| --cwd <path> | Run in a different CDK project directory. Defaults to the current directory. |
| -c, --context <key=value> | Pass a context value to cdk diff. Repeat for multiple values. |
| --ignore-property <names> | Hide modified resources whose only changes are these properties. Comma-separated and repeatable. |
| --ignore-type <types> | Hide all changes to these resource types. Comma-separated and repeatable. * is a wildcard. |
| --env <name> | Run a single environment from your configuration (IaCReview plan). |
| -h, --help | Show help. |
The tool always runs cdk diff --ci, followed by the configured cdkArgs and
then any context values from the command line.
Examples:
# Diff every stack and post the comment
cdk-diff-report
# Preview the comment for one stack with stage-specific context
cdk-diff-report --dry-run -c stage=prod -c version=1.4.0
# Ignore tag-only changes and CDK's own metadata resource
cdk-diff-report --ignore-property Tags --ignore-type AWS::CDK::MetadataConfiguration
Settings are read from three places. When the same setting appears in more than one, the higher entry wins:
- Environment variables, which suit CI pipelines.
- A
.cdkdiffreportrc(or.cdkdiffreportrc.json) file in the CDK project directory, next tocdk.json. - Built-in defaults.
Context values and ignore filters given on the command line are added to the ones from configuration rather than replacing them.
A complete configuration file:
{
"platform": "github",
"htmlOutput": "cdk-diff.html",
"ignoreProperties": ["Tags", "Metadata"],
"ignoreResourceTypes": ["AWS::CDK::Metadata"]
}| Setting | Config key | Environment variable | Default |
|---------|------------|----------------------|---------|
| Git platform: github, gitlab, or bitbucket | platform | CDK_DIFF_PLATFORM | bitbucket |
| Arguments for cdk diff | cdkArgs | CDK_DIFF_CDK_ARGS (comma-separated) | none (every stack) |
| HTML report path | htmlOutput | CDK_DIFF_HTML_OUTPUT | none |
| Preview without posting | dryRun | CDK_DIFF_DRY_RUN | false |
| Properties to ignore | ignoreProperties | CDK_DIFF_IGNORE_PROPERTIES (comma-separated) | none |
| Resource types to ignore | ignoreResourceTypes | CDK_DIFF_IGNORE_RESOURCE_TYPES (comma-separated) | none |
| Bitbucket workspace | workspace | CDK_DIFF_WORKSPACE | BITBUCKET_WORKSPACE |
| Bitbucket repository slug | repoSlug | CDK_DIFF_REPO_SLUG | BITBUCKET_REPO_SLUG |
| Bitbucket API URL | bitbucketApiUrl | CDK_DIFF_BITBUCKET_API_URL | https://api.bitbucket.org/2.0 |
| GitLab API URL | gitlabApiUrl | CDK_DIFF_GITLAB_API_URL | CI_API_V4_URL, then https://gitlab.com/api/v4 |
With no cdkArgs, cdk diff compares every stack in the app. Set it to stack
names, such as ["MyStack"], to diff only those.
For safety, arguments that contain shell metacharacters such as ;, |, or
$( are rejected, and cdk is never started through a shell.
Passing CDK context
If your CDK app reads context values, for example
app.node.tryGetContext('stage'), pass them the same way you would to cdk:
cdk-diff-report -c stage=dev -c version=1.2.3This runs:
cdk diff --ci --context stage=dev --context version=1.2.3The forms -c key=value, --context key=value, -c=key=value, and
--context=key=value are all accepted, and a value may itself contain =.
A value that is not in key=value form is rejected with an error.
Fixed context values can also go in cdkArgs, for example
"cdkArgs": ["-c", "stage=dev"].
Hiding changes you do not need to review
Some changes are expected on almost every pull request and add little to a review, such as tag updates or changes to CDK's own metadata. Two filters let you leave them out of the comment.
ignoreProperties hides a modified resource only when every property that
changed is on the list. With ["Tags"], a bucket whose tags changed is hidden,
but a Lambda function whose tags and code both changed is still shown, because
the code change matters.
ignoreResourceTypes hides every change to the listed resource types,
including additions and removals. Use it for resources you never want to
review, such as AWS::CDK::Metadata or Custom::*.
The filters are deliberately conservative:
- A property filter never hides an addition, a removal, or a replacement.
- If the tool cannot tell which properties changed on a resource, the resource is shown.
- Matching is not case-sensitive, and
*is a wildcard. - The comment states how many changes were hidden, so reviewers know a filter was applied.
- The raw
cdk diffoutput in the CI log and in the HTML report is not filtered.
Reading the report
| Term | Meaning |
|------|---------|
| Added | A new resource will be created. |
| Modified | An existing resource will be updated in place. The Details column lists the properties that changed. |
| Replaced | CloudFormation will create a new resource and delete the existing one. The Details column names the property that requires the replacement. Treat replacements of databases, buckets, and other stateful resources with care. |
| Removed | The resource will be deleted, or orphaned if its removal policy retains it. |
| Security review required | The diff contains IAM policy or security group changes. Check the full cdk diff output for the exact statements and rules. |
The summary table counts each resource once, so the four columns add up to the total number of changed resources.
Exit codes
| Code | Meaning |
|------|---------|
| 0 | The diff ran successfully. If the comment could not be posted, the error is logged but the run still succeeds, so a platform outage does not block your pipeline. |
| 1 | cdk diff failed (for example a synthesis error or invalid credentials), or the configuration or arguments are invalid. |
| 2 | The IaCReview merge verdict is blocked and failOnBlock is enabled (IaCReview plan only). |
Troubleshooting
cdk not found on PATH. Install the CDK CLI globally with
npm install -g aws-cdk. A project-local install is not on the PATH.
cdk diff failed (exit code 1). The CDK app failed to synthesize, or the
credentials could not reach the account. The cdk output just above the error
explains the cause. Run cdk diff locally with the same arguments to reproduce.
No comment appears on the pull request. Check the log for a warning that
names missing variables. The most common causes are a pipeline that does not
run for pull request events, a token without permission to comment, or a
platform setting that does not match your Git host. On GitHub, workflows
triggered from forks receive a read-only token and cannot post comments.
Failed to post PR comment with HTTP 403 on a later push. The tool finds
its previous comment by a hidden marker and updates it. If that comment was
created with a different token or user, the platform does not allow the update.
Delete the old comment, or post with the same token that created it.
Refusing to run cdk: argument contains shell metacharacters. One of the
configured arguments contains characters such as ;, |, or $(. Remove them
from cdkArgs or the context values.
Using it as a library
The same functionality is available from Node.js:
import { run, parseCdkDiff, filterDiff, generateMarkdownComment } from 'cdk-diff-report';
// Run the full pipeline, just like the CLI
await run({ dryRun: true, context: ['stage=dev'], ignoreProperties: ['Tags'] });
// Or work with cdk diff output you already have
const diff = filterDiff(parseCdkDiff(rawCdkDiffOutput), { ignoreProperties: ['Tags'] });
console.log(diff.totalAdded, diff.totalReplaced);
console.log(generateMarkdownComment(diff));| Export | Description |
|--------|-------------|
| run(options) | Runs the full pipeline: diff, report, and comment. |
| parseCdkDiff(raw) | Parses cdk diff output into structured data, including replacements and changed properties. |
| filterDiff(diff, filter) | Applies ignoreProperties and ignoreResourceTypes to a parsed diff. |
| generateMarkdownComment(diff) | Renders the pull request comment. |
| generateHtml(diff) | Renders the standalone HTML report. |
| loadConfig(cwd) | Loads configuration from the environment and .cdkdiffreportrc. |
| runCdkDiff, resolvePrUrl, postComment | Lower-level building blocks for custom pipelines. |
| upsertGitHubPrComment, upsertMrNote, upsertPrComment | Create or update a comment directly on GitHub, GitLab, or Bitbucket. |
TypeScript type definitions are included.
IaCReview plan
The free tool tells reviewers what changes. The IaCReview plan adds analysis of what those changes mean, in the same pull request comment:
| Capability | Description | |------------|-------------| | Cost impact | Monthly and annual cost change per resource and per environment, based on live AWS pricing. | | Security scanning | Checkov findings mapped to the CDK source file and line that caused them. | | Policy checks | Organization rules such as required tags, banned resource types, and naming conventions. | | Multi-environment view | Results across environments, such as test, staging, and production, in one comment. | | Merge verdict | A Ready, Review, or Blocked verdict that can optionally fail the pipeline. |
To enable it, set IACREVIEW_API_KEY (or the api-key action input) with a key
from iacreview.com. When the key is present, the tool
uploads the parsed diff and the changed template resources to the IaCReview API
for analysis. If the API cannot be reached, the tool falls back to the free
comment so your pipeline is never blocked. Self-hosted deployments can point the
tool at their own API with IACREVIEW_API_URL.
License
MIT. The IaCReview engine is a separate, proprietary product.
