Stop on Destructive Changes
Most changes to a CDK app are safe to deploy without a second look. The ones that are not are the changes that lose an existing resource: a property change that forces a replacement, a refactor that renames a construct's logical ID, a resource dropped from the template. cdkd can stop on exactly those changes and let everything else through:
# CI check: exit 1 if a change would lose a resource
cdkd diff --all --fail-on=destructive
# deploy, but ask first if a change would lose one
cdkd deploy MyStack --require-approval=destructive
Both use the same rule for what counts as destructive, so a change the diff flags is the change the deploy asks about.
What counts as destructive
A change is destructive when it replaces, deletes or orphans a resource that already exists. Additions and in-place updates are not.
| Impact | When |
|---|---|
will be replaced |
A create-only property changes, or the resource's Type changes. |
may be replaced |
A create-only property reads a value only the deploy can resolve. |
will be destroyed |
The resource leaves the template. |
will be orphaned |
The resource leaves the template with DeletionPolicy: Retain or RetainExceptOnCreate. |
Both commands list each destructive change by stack, resource type, construct path and logical ID:
MyStack: AWS::S3::Bucket MyBucket MyBucketF68F3FF0 will be replaced
MyStack: AWS::DynamoDB::Table MyTable MyTable794EDED1 will be orphaned
Nested stacks are always checked. AWS::CDK::Metadata is never reported.
Fail a CI check: cdkd diff --fail-on=destructive
Run the diff as a pull-request check. It prints the full diff, lists the
destructive changes, and exits 1 if there is at least one:
$ cdkd diff --all --fail-on=destructive
...
❌ Found 2 destructive change(s) (--fail-on=destructive):
MyStack: AWS::S3::Bucket MyBucket MyBucketF68F3FF0 will be replaced
MyStack: AWS::DynamoDB::Table MyTable MyTable794EDED1 will be orphaned
When cdkd deploy would refuse to start, the diff exits 3 instead and
lists the refusal, not the destructive changes, so treat any non-zero exit as
a failed check. Exit 1 also means the command itself failed, for example on
an authentication error; a failed command prints an error instead of the
report.
cdkd diff lists every exit code.
Use --fail-on=any-change instead to fail on every difference.
Ask before deploying: cdkd deploy --require-approval=destructive
With this level, cdkd deploy stops before a stack with a destructive change,
lists the changes, and asks:
Destructive changes:
MyStack: AWS::DynamoDB::Table MyTable MyTable794EDED1 will be orphaned
Stack MyStack: 0 to create, 1 to update, 1 to delete.
Stack includes destructive updates and "--require-approval" is set to 'destructive'.
Do you wish to deploy these changes? (y/n)
Answering no fails that stack's deploy with nothing changed. A nested stack asks when its parent reaches it; declining fails the nested stack, and the parent rolls back. A stack with no destructive change deploys without a question.
To make it the default for an app, set it in cdk.json, where the AWS CDK CLI
reads it too. The flag wins over the file:
{
"app": "npx ts-node bin/app.ts",
"requireApproval": "destructive"
}
Important
Without a terminal, as in CI, the deploy fails instead of asking. Pass
--yesto approve every question, or gate the pipeline oncdkd diff --fail-on=destructivebefore the deploy step.
A --recreate-via-* target counts as a replacement, so it asks too.
--dry-run never asks. The AWS CDK CLI's broadening level is not available,
because cdkd does not compute a security diff; in cdk.json it is ignored
with a warning.
Related
cdkd diff: every--fail-onvalue- cdkd deploy: strictness and approval flags:
--require-approvalwith nested stacks and parallel deploys - cdkd deploy: replacements and name collisions: what a replacement does to a named resource
- Orphan vs Destroy: what an orphaned resource is