Skip to content

Commit

Permalink
fix(cli): direct deploy method fails when there are no updates (#28523)
Browse files Browse the repository at this point in the history
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*
  • Loading branch information
jogold committed Jan 3, 2024
1 parent a2f0553 commit dde5975
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 9 deletions.
26 changes: 17 additions & 9 deletions packages/aws-cdk/lib/api/deploy-stack.ts
Expand Up @@ -478,16 +478,24 @@ class FullCloudFormationDeployment {
const startTime = new Date();

if (this.update) {
await this.cfn.updateStack({
StackName: this.stackName,
ClientRequestToken: `update${this.uuid}`,
...this.commonPrepareOptions(),
...this.commonExecuteOptions(),
}).promise();

const ret = await this.monitorDeployment(startTime, undefined);
await this.updateTerminationProtection();
return ret;

try {
await this.cfn.updateStack({
StackName: this.stackName,
ClientRequestToken: `update${this.uuid}`,
...this.commonPrepareOptions(),
...this.commonExecuteOptions(),
}).promise();
} catch (err: any) {
if (err.message === 'No updates are to be performed.') {
debug('No updates are to be performed for stack %s', this.stackName);
return { noOp: true, outputs: this.cloudFormationStack.outputs, stackArn: this.cloudFormationStack.stackId };
}
throw err;
}

return this.monitorDeployment(startTime, undefined);
} else {
// Take advantage of the fact that we can set termination protection during create
const terminationProtection = this.stackArtifact.terminationProtection ?? false;
Expand Down
19 changes: 19 additions & 0 deletions packages/aws-cdk/test/api/deploy-stack.test.ts
Expand Up @@ -206,6 +206,25 @@ test('call UpdateStack when method=direct and the stack exists already', async (
expect(cfnMocks.updateStack).toHaveBeenCalled();
});

test('method=direct and no updates to be performed', async () => {
cfnMocks.updateStack?.mockRejectedValueOnce({
code: 'ValidationError',
message: 'No updates are to be performed.',
} as never);

// WHEN
givenStackExists();

const ret = await deployStack({
...standardDeployStackArguments(),
deploymentMethod: { method: 'direct' },
force: true,
});

// THEN
expect(ret).toEqual(expect.objectContaining({ noOp: true }));
});

test("does not call tryHotswapDeployment() if 'hotswap' is false", async () => {
// WHEN
await deployStack({
Expand Down

0 comments on commit dde5975

Please sign in to comment.