Skip to content

Commit dde5975

Browse files
authored
fix(cli): direct deploy method fails when there are no updates (#28523)
This is correctly handled for empty change sets here: https://github.com/aws/aws-cdk/blob/9d8b06f6478a98e01e3aaa86c1dbf22d6e861f05/packages/aws-cdk/lib/api/util/cloudformation.ts#L290-L296 but not for direct updates. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent a2f0553 commit dde5975

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

packages/aws-cdk/lib/api/deploy-stack.ts

+17-9
Original file line numberDiff line numberDiff line change
@@ -478,16 +478,24 @@ class FullCloudFormationDeployment {
478478
const startTime = new Date();
479479

480480
if (this.update) {
481-
await this.cfn.updateStack({
482-
StackName: this.stackName,
483-
ClientRequestToken: `update${this.uuid}`,
484-
...this.commonPrepareOptions(),
485-
...this.commonExecuteOptions(),
486-
}).promise();
487-
488-
const ret = await this.monitorDeployment(startTime, undefined);
489481
await this.updateTerminationProtection();
490-
return ret;
482+
483+
try {
484+
await this.cfn.updateStack({
485+
StackName: this.stackName,
486+
ClientRequestToken: `update${this.uuid}`,
487+
...this.commonPrepareOptions(),
488+
...this.commonExecuteOptions(),
489+
}).promise();
490+
} catch (err: any) {
491+
if (err.message === 'No updates are to be performed.') {
492+
debug('No updates are to be performed for stack %s', this.stackName);
493+
return { noOp: true, outputs: this.cloudFormationStack.outputs, stackArn: this.cloudFormationStack.stackId };
494+
}
495+
throw err;
496+
}
497+
498+
return this.monitorDeployment(startTime, undefined);
491499
} else {
492500
// Take advantage of the fact that we can set termination protection during create
493501
const terminationProtection = this.stackArtifact.terminationProtection ?? false;

packages/aws-cdk/test/api/deploy-stack.test.ts

+19
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,25 @@ test('call UpdateStack when method=direct and the stack exists already', async (
206206
expect(cfnMocks.updateStack).toHaveBeenCalled();
207207
});
208208

209+
test('method=direct and no updates to be performed', async () => {
210+
cfnMocks.updateStack?.mockRejectedValueOnce({
211+
code: 'ValidationError',
212+
message: 'No updates are to be performed.',
213+
} as never);
214+
215+
// WHEN
216+
givenStackExists();
217+
218+
const ret = await deployStack({
219+
...standardDeployStackArguments(),
220+
deploymentMethod: { method: 'direct' },
221+
force: true,
222+
});
223+
224+
// THEN
225+
expect(ret).toEqual(expect.objectContaining({ noOp: true }));
226+
});
227+
209228
test("does not call tryHotswapDeployment() if 'hotswap' is false", async () => {
210229
// WHEN
211230
await deployStack({

0 commit comments

Comments
 (0)