feat(cli): warn of non-existent stacks in cdk destroy#984
Conversation
Head branch was pushed to by a user without write access
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #984 +/- ##
==========================================
- Coverage 89.14% 89.13% -0.02%
==========================================
Files 77 77
Lines 11539 11528 -11
Branches 1605 1602 -3
==========================================
- Hits 10287 10276 -11
Misses 1221 1221
Partials 31 31
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The `refactor` command only operates on the stacks that are relevant for the target CDK application. However, it gets all the templates of the deployed stacks before filtering them, which is wasteful. Invert the order, so that the filtering happens before getting the templates. --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license
|
@go-to-k I am looking to get this in soon (hence the rebase), but first want to change |
toolkit-lib: add `force` to DestroyOptions; add W7010/W7011 warnings; move the stack-name suggestion + no-match warning + force-skip into `_destroy`; expose `destroyForAction` as protected so the CLI can keep `deploy` message attribution. aws-cdk: thin destroy delegation with selector -> StackSelector mapping; add `InternalToolkit.destroyFromDeploy`; remove `fromDeploy`/legacy loop; preserve graceful abort on a declined confirmation.
Generated output of routing destroy through toolkit-lib: message-registry.md is regenerated from messages.ts, and the destroy command's __io_snapshots__ reflect the messages now emitted by toolkit-lib. No hand edits.
Move the destroy logic tests to toolkit-lib (including stage/nested-stage regression coverage and the force / suggestion / no-match cases) with new stage fixtures; reduce the CLI tests to delegation/mapping checks; rework the destroy command snapshot test to spy on Deployments.prototype.
The destroy command snapshot test was non-deterministic across color modes: toolkit-lib wraps a leading newline inside a chalk color escape (`\n ✅ ...`), so `withTrimmedWhitespace`'s `.trim()` cannot remove it when colors are on (the string starts with the ANSI escape, not whitespace). The recorder stripped ANSI only after receiving the already-(un)trimmed message, so the leading newline survived with colors on and the snapshot differed between a TTY and CI. Trim in the recorder's `normalize()` after stripping ANSI so the recorded stream is the same regardless of whether colors were enabled, and regenerate the affected snapshots.
|
@mrgrain Done. Destroy output now flows through toolkit-lib, so it's coded and consistent with deploy (adds |
The destroy confirmation prompt colored the stack names red. Use blue to match the color the CLI used before destroy was routed through toolkit-lib.
Align cdk destroy with the confirmation-prompt contract from aws#1667: declining now throws AbortError('DestroyAborted', 'Deletion cancelled') and exits non-zero instead of emitting CDK_TOOLKIT_E7010 and exiting 0.
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
| if (stacks.stackCount === 0) { | ||
| await ioHelper.notify(IO.CDK_TOOLKIT_W7011.msg( | ||
| `No stacks match the name(s): ${chalk.red((selectStacks.patterns ?? []).join(', '))}`, | ||
| )); |
There was a problem hiding this comment.
Note on the exit code: no-match (W7011) exits 0, while a declined confirmation exits 1 (#1667). This is deliberate and keeps the existing behavior. The old selectStacksForDestroy had a // No validation comment and returned an empty selection, so cdk destroy <nonexistent> already exited 0 (deploy throws NoStacksMatched, destroy never did). We keep that contract and add a warning in place of the old empty prompt.
| // Trim only after stripping ANSI, so the snapshot is independent of the | ||
| // active color mode (TTY vs not). toolkit-lib trims its messages, but a | ||
| // leading newline that is wrapped inside a chalk color escape survives that | ||
| // trim (the string starts with the escape, not whitespace); once we strip | ||
| // the ANSI here the newline is re-exposed, so we trim again to keep the | ||
| // recorded stream deterministic regardless of whether colors were enabled. | ||
| return out.trim(); |
There was a problem hiding this comment.
Keeps snapshots independent of color mode (TTY vs not): a chalk-wrapped leading newline survives toolkit-lib's own trim, so without this the snapshot differs between color on/off.
| /** | ||
| * Whether the destroy request came from a deploy. | ||
| */ | ||
| fromDeploy?: boolean; | ||
|
|
There was a problem hiding this comment.
Not breaking: this DestroyOptions is internal to the aws-cdk package (not in its exports), so it isn't user-facing.



Fixes aws/aws-cdk#32836, aws/aws-cdk#32545, aws/aws-cdk#27179, aws/aws-cdk#22240
Reason for this change
This PR implements the feature that warns users when non-existent stacks are specified in
cdk destroy.Are you sure you want to delete:if there is no matching stack.cdk destroywill not fail, it will just print a warning.For examples (that have
Stacka,StackA,StackX):Difference from previous PR
The previous PR was reverted in aws/aws-cdk#32839 due to a regression with only nested stage stacks. So this version addresses that regression with comprehensive tests.
Description of changes
The original implementation added warnings for non-existent stacks in
cdk destroy, but it failed when applications had only nested stage stacks (no top-level stacks). This happened because the code usedallTopLevel: true, which only searched for stacks directly under the App, ignoring stacks within nested Stages.Fixed the regression by changing
suggestStacksmethod to useDefaultSelection.AllStacksinstead ofallTopLevel: true, ensuring the warning feature works for all stack configurations (top-level only, nested only, or both). Added regression tests to verify the fix for the nested stage scenario.private async suggestStacks(props: { selector: StackSelector; stacks: StackCollection; exclusively?: boolean; }) { const assembly = await this.assembly(); const selectorWithoutPatterns: StackSelector = { - ...props.selector, - allTopLevel: true, patterns: [], }; const stacksWithoutPatterns = await assembly.selectStacks(selectorWithoutPatterns, { extend: props.exclusively ? ExtendedStackSelection.None : ExtendedStackSelection.Downstream, - defaultBehavior: DefaultSelection.OnlySingle, + defaultBehavior: DefaultSelection.AllStacks, });Additional Information
When running
cdk destroy --allorcdk deploy --allagainst a configuration with no top-level stacks (nested stages only), the following error occurs.However, this behavior existed before this PR and is unrelated to the changes made here. Since it is outside the scope of this PR, no fix has been implemented for this behavior.
FYI: I have submitted an issue and a PR about this behavior.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license