Skip to content

Commit 7ee91cf

Browse files
authored
feat(aws-codedeploy): add auto rollback configuration to server Deployment Group. (#925)
1 parent 36f29b6 commit 7ee91cf

File tree

5 files changed

+147
-0
lines changed

5 files changed

+147
-0
lines changed

packages/@aws-cdk/aws-codedeploy/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ const deploymentGroup = new codedeploy.ServerDeploymentGroup(this, 'CodeDeployDe
6060
// whether to ignore failure to fetch the status of alarms from CloudWatch
6161
// default: false
6262
ignorePollAlarmsFailure: false,
63+
// auto-rollback configuration
64+
autoRollback: {
65+
failedDeployment: true, // default: true
66+
stoppedDeployment: true, // default: false
67+
deploymentInAlarm: true, // default: true if you provided any alarms, false otherwise
68+
},
6369
});
6470
```
6571

packages/@aws-cdk/aws-codedeploy/lib/deployment-group.ts

+67
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,33 @@ export class InstanceTagSet {
135135
}
136136
}
137137

138+
/**
139+
* The configuration for automatically rolling back deployments in a given Deployment Group.
140+
*/
141+
export interface AutoRollbackConfig {
142+
/**
143+
* Whether to automatically roll back a deployment that fails.
144+
*
145+
* @default true
146+
*/
147+
failedDeployment?: boolean;
148+
149+
/**
150+
* Whether to automatically roll back a deployment that was manually stopped.
151+
*
152+
* @default false
153+
*/
154+
stoppedDeployment?: boolean;
155+
156+
/**
157+
* Whether to automatically roll back a deployment during which one of the configured
158+
* CloudWatch alarms for this Deployment Group went off.
159+
*
160+
* @default true if you've provided any Alarms with the `alarms` property, false otherwise
161+
*/
162+
deploymentInAlarm?: boolean;
163+
}
164+
138165
/**
139166
* Construction properties for {@link ServerDeploymentGroup}.
140167
*/
@@ -224,6 +251,11 @@ export interface ServerDeploymentGroupProps {
224251
* @default false
225252
*/
226253
ignorePollAlarmsFailure?: boolean;
254+
255+
/**
256+
* The auto-rollback configuration for this Deployment Group.
257+
*/
258+
autoRollback?: AutoRollbackConfig;
227259
}
228260

229261
/**
@@ -281,6 +313,7 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupRef {
281313
ec2TagSet: this.ec2TagSet(props.ec2InstanceTags),
282314
onPremisesTagSet: this.onPremiseTagSet(props.onPremiseInstanceTags),
283315
alarmConfiguration: new cdk.Token(() => this.renderAlarmConfiguration(props.ignorePollAlarmsFailure)),
316+
autoRollbackConfiguration: new cdk.Token(() => this.renderAutoRollbackConfiguration(props.autoRollback)),
284317
});
285318

286319
this.deploymentGroupName = resource.deploymentGroupName;
@@ -455,6 +488,40 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupRef {
455488
ignorePollAlarmFailure,
456489
};
457490
}
491+
492+
private renderAutoRollbackConfiguration(autoRollbackConfig: AutoRollbackConfig = {}):
493+
cloudformation.DeploymentGroupResource.AutoRollbackConfigurationProperty | undefined {
494+
const events = new Array<string>();
495+
496+
// we roll back failed deployments by default
497+
if (autoRollbackConfig.failedDeployment !== false) {
498+
events.push('DEPLOYMENT_FAILURE');
499+
}
500+
501+
// we _do not_ roll back stopped deployments by default
502+
if (autoRollbackConfig.stoppedDeployment === true) {
503+
events.push('DEPLOYMENT_STOP_ON_REQUEST');
504+
}
505+
506+
// we _do not_ roll back alarm-triggering deployments by default
507+
// unless the Deployment Group has at least one alarm
508+
if (autoRollbackConfig.deploymentInAlarm !== false) {
509+
if (this.alarms.length > 0) {
510+
events.push('DEPLOYMENT_STOP_ON_ALARM');
511+
} else if (autoRollbackConfig.deploymentInAlarm === true) {
512+
throw new Error(
513+
"The auto-rollback setting 'deploymentInAlarm' does not have any effect unless you associate " +
514+
"at least one CloudWatch alarm with the Deployment Group");
515+
}
516+
}
517+
518+
return events.length > 0
519+
? {
520+
enabled: true,
521+
events,
522+
}
523+
: undefined;
524+
}
458525
}
459526

460527
function deploymentGroupName2Arn(applicationName: string, deploymentGroupName: string): string {

packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.ts

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ new codedeploy.ServerDeploymentGroup(stack, 'CodeDeployGroup', {
3636
evaluationPeriods: 1,
3737
}),
3838
],
39+
autoRollback: {
40+
failedDeployment: false,
41+
deploymentInAlarm: false,
42+
},
3943
});
4044

4145
app.run();

packages/@aws-cdk/aws-codedeploy/test/test.deployment-group.ts

+64
Original file line numberDiff line numberDiff line change
@@ -296,5 +296,69 @@ export = {
296296

297297
test.done();
298298
},
299+
300+
'only automatically rolls back failed deployments by default'(test: Test) {
301+
const stack = new cdk.Stack();
302+
303+
new codedeploy.ServerDeploymentGroup(stack, 'DeploymentGroup');
304+
305+
expect(stack).to(haveResource('AWS::CodeDeploy::DeploymentGroup', {
306+
"AutoRollbackConfiguration": {
307+
"Enabled": true,
308+
"Events": [
309+
"DEPLOYMENT_FAILURE",
310+
],
311+
},
312+
}));
313+
314+
test.done();
315+
},
316+
317+
'rolls back alarmed deployments if at least one alarm has been added'(test: Test) {
318+
const stack = new cdk.Stack();
319+
320+
const alarm = new cloudwatch.Alarm(stack, 'Alarm1', {
321+
metric: new cloudwatch.Metric({
322+
metricName: 'Errors',
323+
namespace: 'my.namespace',
324+
}),
325+
threshold: 1,
326+
evaluationPeriods: 1,
327+
});
328+
329+
const deploymentGroup = new codedeploy.ServerDeploymentGroup(stack, 'DeploymentGroup', {
330+
autoRollback: {
331+
failedDeployment: false,
332+
},
333+
});
334+
deploymentGroup.addAlarm(alarm);
335+
336+
expect(stack).to(haveResource('AWS::CodeDeploy::DeploymentGroup', {
337+
"AutoRollbackConfiguration": {
338+
"Enabled": true,
339+
"Events": [
340+
"DEPLOYMENT_STOP_ON_ALARM",
341+
],
342+
},
343+
}));
344+
345+
test.done();
346+
},
347+
348+
'setting to roll back on alarms without providing any results in an exception'(test: Test) {
349+
const stack = new cdk.Stack();
350+
351+
new codedeploy.ServerDeploymentGroup(stack, 'DeploymentGroup', {
352+
autoRollback: {
353+
deploymentInAlarm: true,
354+
},
355+
});
356+
357+
test.throws(() => {
358+
stack.toCloudFormation();
359+
}, /deploymentInAlarm/);
360+
361+
test.done();
362+
},
299363
},
300364
};

packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-deploy.expected.json

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
"Arn"
4949
]
5050
},
51+
"AutoRollbackConfiguration": {
52+
"Enabled": true,
53+
"Events": [
54+
"DEPLOYMENT_FAILURE"
55+
]
56+
},
5157
"DeploymentConfigName": {
5258
"Ref": "CustomDeployConfig52EEBC13"
5359
},

0 commit comments

Comments
 (0)