diff --git a/README.md b/README.md index 4d5ad6e..1c0e2f0 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,8 @@ You can see a working example in the [example folder](./example/). * `postTrafficHook`: (optional) validation Lambda function that runs after traffic shifting. It must use the CodeDeploy SDK to notify about this step's success or failure (more info [here](https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html)) * `alarms`: (optional) list of CloudWatch alarms. If any of them is triggered during the deployment, the associated Lambda function will automatically roll back to the previous version. * `triggerConfigurations`: (optional) list of CodeDeploy Triggers. See more details in the [CodeDeploy TriggerConfiguration Documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentgroup-triggerconfig.html), or [this CodeDeploy notifications guide](https://docs.aws.amazon.com/codedeploy/latest/userguide/monitoring-sns-event-notifications-create-trigger.html) for example uses - +* `disableRollback`: (optional) disables the rollback of the canary deployment if it fails. Defaults to false. +* `disableAlarms`: (optional) disables the alarms for the canary deployment. Defaults to false. ### Default configurations You can set default values for all functions in a top-level custom deploymentSettings section. E.g.: diff --git a/example/serverless.yml b/example/serverless.yml index 5407ef3..c3860c6 100644 --- a/example/serverless.yml +++ b/example/serverless.yml @@ -70,6 +70,8 @@ functions: deploymentSettings: type: Linear10PercentEvery1Minute alias: Live + disableAlarms: true + disableRollback: true preTrafficHook: preHook postTrafficHook: postHook alarms: diff --git a/lib/CfTemplateGenerators/CodeDeploy.js b/lib/CfTemplateGenerators/CodeDeploy.js index c4c3a16..53eadba 100644 --- a/lib/CfTemplateGenerators/CodeDeploy.js +++ b/lib/CfTemplateGenerators/CodeDeploy.js @@ -17,7 +17,7 @@ function buildFnDeploymentGroup ({ codeDeployAppName, codeDeployGroupName, codeD Ref: codeDeployAppName }, AutoRollbackConfiguration: { - Enabled: true, + Enabled: !deploymentSettings.disableRollback, Events: [ 'DEPLOYMENT_FAILURE', 'DEPLOYMENT_STOP_ON_ALARM', @@ -45,9 +45,10 @@ function buildFnDeploymentGroup ({ codeDeployAppName, codeDeployGroupName, codeD const name = _.propOr({ Ref: a }, 'name', a) return { Name: name } }) + console.log({ deploymentSettings }) const alarmConfig = { Alarms: alarmNames, - Enabled: true + Enabled: !deploymentSettings.disableAlarms } Object.assign(deploymentGroup.Properties, { AlarmConfiguration: alarmConfig }) } diff --git a/lib/CfTemplateGenerators/CodeDeploy.test.js b/lib/CfTemplateGenerators/CodeDeploy.test.js index 2a4bd6d..6b2d188 100644 --- a/lib/CfTemplateGenerators/CodeDeploy.test.js +++ b/lib/CfTemplateGenerators/CodeDeploy.test.js @@ -6,7 +6,7 @@ const CodeDeploy = require('./CodeDeploy') describe('CodeDeploy', () => { describe('.buildApplication', () => { - it('generates a CodeDeploy::Application resouce', () => { + it('generates a CodeDeploy::Application resource', () => { const expected = { Type: 'AWS::CodeDeploy::Application', Properties: { ComputePlatform: 'Lambda' } @@ -85,6 +85,53 @@ describe('CodeDeploy', () => { }) }) + context('when disableAlarms is provided and true', () => { + it('should disable the alarm configuration', () => { + const deploymentSettings = { + type: 'Linear10PercentEvery1Minute', + alarms: ['Alarm1', { name: 'Alarm2' }], + disableAlarms: true + } + const expectedAlarms = { + Alarms: [{ Name: { Ref: 'Alarm1' } }, { Name: 'Alarm2' }], + Enabled: false + } + const expected = _.pipe( + _.set('Properties.ApplicationName', { Ref: codeDeployAppName }), + _.set('Properties.DeploymentGroupName', codeDeployGroupName), + _.set('Properties.AlarmConfiguration', expectedAlarms), + _.set('Properties.DeploymentConfigName.Fn::Sub[1].ConfigName', deploymentSettings.type) + )(baseDeploymentGroup) + const actual = CodeDeploy.buildFnDeploymentGroup({ codeDeployAppName, codeDeployGroupName, deploymentSettings }) + console.log(actual) + expect(actual).to.deep.equal(expected) + }) + }) + + context('when disableRollback is provided and true', () => { + it('should disable the automatic rollback configuration', () => { + const deploymentSettings = { + type: 'Linear10PercentEvery1Minute', + alarms: ['Alarm1', { name: 'Alarm2' }], + disableRollback: true + } + const expectedAlarms = { + Alarms: [{ Name: { Ref: 'Alarm1' } }, { Name: 'Alarm2' }], + Enabled: true + } + const expected = _.pipe( + _.set('Properties.ApplicationName', { Ref: codeDeployAppName }), + _.set('Properties.DeploymentGroupName', codeDeployGroupName), + _.set('Properties.AlarmConfiguration', expectedAlarms), + _.set('Properties.DeploymentConfigName.Fn::Sub[1].ConfigName', deploymentSettings.type), + _.set('Properties.AutoRollbackConfiguration.Enabled', false) + )(baseDeploymentGroup) + const actual = CodeDeploy.buildFnDeploymentGroup({ codeDeployAppName, codeDeployGroupName, deploymentSettings }) + console.log(actual) + expect(actual).to.deep.equal(expected) + }) + }) + context('when a codeDeploy role is provided', () => { it('should include the arn of the existing role instead of trying to lookup a generated role', () => { const deploymentSettings = { type: 'Linear10PercentEvery1Minute' }