Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7b68908

Browse files
committedJan 10, 2025
fix(cli): "no stack found in the main cloud assembly" (#32839)
Reverts #32636 It leads to a problem in case of applications where there are no top-level stacks, but only stacks in nested stages: #32836. Closes #32836.
1 parent 703e81f commit 7b68908

File tree

3 files changed

+0
-132
lines changed

3 files changed

+0
-132
lines changed
 

‎packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts

-14
Original file line numberDiff line numberDiff line change
@@ -2634,20 +2634,6 @@ integTest('hotswap ECS deployment respects properties override', withDefaultFixt
26342634
expect(describeServicesResponse.services?.[0].deploymentConfiguration?.maximumPercent).toEqual(ecsMaximumHealthyPercent);
26352635
}));
26362636

2637-
integTest('cdk destroy does not fail even if the stacks do not exist', withDefaultFixture(async (fixture) => {
2638-
const nonExistingStackName1 = 'non-existing-stack-1';
2639-
const nonExistingStackName2 = 'non-existing-stack-2';
2640-
2641-
await expect(fixture.cdkDestroy([nonExistingStackName1, nonExistingStackName2])).resolves.not.toThrow();
2642-
}));
2643-
2644-
integTest('cdk destroy with no force option exits without prompt if the stacks do not exist', withDefaultFixture(async (fixture) => {
2645-
const nonExistingStackName1 = 'non-existing-stack-1';
2646-
const nonExistingStackName2 = 'non-existing-stack-2';
2647-
2648-
await expect(fixture.cdk(['destroy', ...fixture.fullStackName([nonExistingStackName1, nonExistingStackName2])])).resolves.not.toThrow();
2649-
}));
2650-
26512637
async function listChildren(parent: string, pred: (x: string) => Promise<boolean>) {
26522638
const ret = new Array<string>();
26532639
for (const child of await fs.readdir(parent, { encoding: 'utf-8' })) {

‎packages/aws-cdk/lib/cdk-toolkit.ts

-54
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import * as cxapi from '@aws-cdk/cx-api';
44
import * as chalk from 'chalk';
55
import * as chokidar from 'chokidar';
66
import * as fs from 'fs-extra';
7-
import { minimatch } from 'minimatch';
87
import * as promptly from 'promptly';
98
import * as uuid from 'uuid';
109
import { DeploymentMethod, SuccessfulDeployStackResult } from './api';
@@ -800,16 +799,6 @@ export class CdkToolkit {
800799
public async destroy(options: DestroyOptions) {
801800
let stacks = await this.selectStacksForDestroy(options.selector, options.exclusively);
802801

803-
await this.suggestStacks({
804-
selector: options.selector,
805-
stacks,
806-
exclusively: options.exclusively,
807-
});
808-
if (stacks.stackArtifacts.length === 0) {
809-
warning(`No stacks match the name(s): ${chalk.red(options.selector.patterns.join(', '))}`);
810-
return;
811-
}
812-
813802
// The stacks will have been ordered for deployment, so reverse them for deletion.
814803
stacks = stacks.reversed();
815804

@@ -1173,49 +1162,6 @@ export class CdkToolkit {
11731162
return stacks;
11741163
}
11751164

1176-
private async suggestStacks(props: {
1177-
selector: StackSelector;
1178-
stacks: StackCollection;
1179-
exclusively?: boolean;
1180-
}) {
1181-
const assembly = await this.assembly();
1182-
const selectorWithoutPatterns: StackSelector = {
1183-
...props.selector,
1184-
allTopLevel: true,
1185-
patterns: [],
1186-
};
1187-
const stacksWithoutPatterns = await assembly.selectStacks(selectorWithoutPatterns, {
1188-
extend: props.exclusively ? ExtendedStackSelection.None : ExtendedStackSelection.Downstream,
1189-
defaultBehavior: DefaultSelection.OnlySingle,
1190-
});
1191-
1192-
const patterns = props.selector.patterns.map(pattern => {
1193-
const notExist = !props.stacks.stackArtifacts.find(stack =>
1194-
minimatch(stack.hierarchicalId, pattern),
1195-
);
1196-
1197-
const closelyMatched = notExist ? stacksWithoutPatterns.stackArtifacts.map(stack => {
1198-
if (minimatch(stack.hierarchicalId.toLowerCase(), pattern.toLowerCase())) {
1199-
return stack.hierarchicalId;
1200-
}
1201-
return;
1202-
}).filter((stack): stack is string => stack !== undefined) : [];
1203-
1204-
return {
1205-
pattern,
1206-
notExist,
1207-
closelyMatched,
1208-
};
1209-
});
1210-
1211-
for (const pattern of patterns) {
1212-
if (pattern.notExist) {
1213-
const closelyMatched = pattern.closelyMatched.length > 0 ? ` Do you mean ${chalk.blue(pattern.closelyMatched.join(', '))}?` : '';
1214-
warning(`${chalk.red(pattern.pattern)} does not exist.${closelyMatched}`);
1215-
}
1216-
};
1217-
}
1218-
12191165
/**
12201166
* Validate the stacks for errors and warnings according to the CLI's current settings
12211167
*/

‎packages/aws-cdk/test/cdk-toolkit.test.ts

-64
Original file line numberDiff line numberDiff line change
@@ -953,70 +953,6 @@ describe('destroy', () => {
953953
});
954954
}).resolves;
955955
});
956-
957-
test('does not throw and warns if there are only non-existent stacks', async () => {
958-
const toolkit = defaultToolkitSetup();
959-
960-
await toolkit.destroy({
961-
selector: { patterns: ['Test-Stack-X', 'Test-Stack-Y'] },
962-
exclusively: true,
963-
force: true,
964-
fromDeploy: true,
965-
});
966-
967-
expect(flatten(stderrMock.mock.calls)).toEqual(
968-
expect.arrayContaining([
969-
expect.stringMatching(/Test-Stack-X does not exist./),
970-
expect.stringMatching(/Test-Stack-Y does not exist./),
971-
expect.stringMatching(/No stacks match the name\(s\): Test-Stack-X, Test-Stack-Y/),
972-
]),
973-
);
974-
});
975-
976-
test('does not throw and warns if there is a non-existent stack and the other exists', async () => {
977-
const toolkit = defaultToolkitSetup();
978-
979-
await toolkit.destroy({
980-
selector: { patterns: ['Test-Stack-X', 'Test-Stack-B'] },
981-
exclusively: true,
982-
force: true,
983-
fromDeploy: true,
984-
});
985-
986-
expect(flatten(stderrMock.mock.calls)).toEqual(
987-
expect.arrayContaining([
988-
expect.stringMatching(/Test-Stack-X does not exist./),
989-
]),
990-
);
991-
expect(flatten(stderrMock.mock.calls)).not.toEqual(
992-
expect.arrayContaining([
993-
expect.stringMatching(/Test-Stack-B does not exist./),
994-
]),
995-
);
996-
expect(flatten(stderrMock.mock.calls)).not.toEqual(
997-
expect.arrayContaining([
998-
expect.stringMatching(/No stacks match the name\(s\)/),
999-
]),
1000-
);
1001-
});
1002-
1003-
test('does not throw and suggests valid names if there is a non-existent but closely matching stack', async () => {
1004-
const toolkit = defaultToolkitSetup();
1005-
1006-
await toolkit.destroy({
1007-
selector: { patterns: ['test-stack-b'] },
1008-
exclusively: true,
1009-
force: true,
1010-
fromDeploy: true,
1011-
});
1012-
1013-
expect(flatten(stderrMock.mock.calls)).toEqual(
1014-
expect.arrayContaining([
1015-
expect.stringMatching(/test-stack-b does not exist. Do you mean Test-Stack-B?/),
1016-
expect.stringMatching(/No stacks match the name\(s\): test-stack-b/),
1017-
]),
1018-
);
1019-
});
1020956
});
1021957

1022958
describe('watch', () => {

0 commit comments

Comments
 (0)
Please sign in to comment.