Skip to content

Commit f2d330f

Browse files
feat: allow forceNewDeployment (#116)
* feat: allow forceNewDeployment * test: remove trailing whitespace & comment adjustment Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 1ee28ca commit f2d330f

File tree

3 files changed

+51
-14
lines changed

3 files changed

+51
-14
lines changed

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ inputs:
2828
codedeploy-deployment-group:
2929
description: "The name of the AWS CodeDeploy deployment group, if the ECS service uses the CODE_DEPLOY deployment controller. Will default to 'DgpECS-{cluster}-{service}'."
3030
required: false
31+
force-new-deployment:
32+
description: 'Whether to force a new deployment of the service. Valid value is "true". Will default to not force a new deployment.'
33+
required: false
3134
outputs:
3235
task-definition-arn:
3336
description: 'The ARN of the registered ECS task definition'

index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ const IGNORED_TASK_DEFINITION_ATTRIBUTES = [
1818
];
1919

2020
// Deploy to a service that uses the 'ECS' deployment controller
21-
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes) {
21+
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment) {
2222
core.debug('Updating the service');
2323
await ecs.updateService({
2424
cluster: clusterName,
2525
service: service,
26-
taskDefinition: taskDefArn
26+
taskDefinition: taskDefArn,
27+
forceNewDeployment: forceNewDeployment
2728
}).promise();
2829
core.info(`Deployment started. Watch this deployment's progress in the Amazon ECS console: https://console.aws.amazon.com/ecs/home?region=${aws.config.region}#/clusters/${clusterName}/services/${service}/events`);
2930

@@ -221,6 +222,7 @@ async function run() {
221222
if (waitForMinutes > MAX_WAIT_MINUTES) {
222223
waitForMinutes = MAX_WAIT_MINUTES;
223224
}
225+
const forceNewDeployment = core.getInput('force-new-deployment', { required: false }) || false;
224226

225227
// Register the task definition
226228
core.debug('Registering the task definition');
@@ -263,7 +265,7 @@ async function run() {
263265

264266
if (!serviceResponse.deploymentController) {
265267
// Service uses the 'ECS' deployment controller, so we can call UpdateService
266-
await updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes);
268+
await updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment);
267269
} else if (serviceResponse.deploymentController.type == 'CODE_DEPLOY') {
268270
// Service uses CodeDeploy, so we should start a CodeDeploy deployment
269271
await createCodeDeployDeployment(codedeploy, clusterName, service, taskDefArn, waitForService, waitForMinutes);

index.test.js

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ describe('Deploy to ECS', () => {
146146
});
147147
});
148148

149-
test('registers the task definition contents and updates the service', async () => {
149+
test('registers the task definition contents and updates the service', async () => {
150150
await run();
151151
expect(core.setFailed).toHaveBeenCalledTimes(0);
152152
expect(mockEcsRegisterTaskDef).toHaveBeenNthCalledWith(1, { family: 'task-def-family'});
@@ -158,7 +158,8 @@ describe('Deploy to ECS', () => {
158158
expect(mockEcsUpdateService).toHaveBeenNthCalledWith(1, {
159159
cluster: 'cluster-789',
160160
service: 'service-456',
161-
taskDefinition: 'task:def:arn'
161+
taskDefinition: 'task:def:arn',
162+
forceNewDeployment: false
162163
});
163164
expect(mockEcsWaiter).toHaveBeenCalledTimes(0);
164165
expect(core.info).toBeCalledWith("Deployment started. Watch this deployment's progress in the Amazon ECS console: https://console.aws.amazon.com/ecs/home?region=fake-region#/clusters/cluster-789/services/service-456/events");
@@ -497,6 +498,7 @@ describe('Deploy to ECS', () => {
497498
.mockReturnValueOnce('cluster-789') // cluster
498499
.mockReturnValueOnce('false') // wait-for-service-stability
499500
.mockReturnValueOnce('') // wait-for-minutes
501+
.mockReturnValueOnce('') // force-new-deployment
500502
.mockReturnValueOnce('/hello/appspec.json') // codedeploy-appspec
501503
.mockReturnValueOnce('MyApplication') // codedeploy-application
502504
.mockReturnValueOnce('MyDeploymentGroup'); // codedeploy-deployment-group
@@ -608,7 +610,7 @@ describe('Deploy to ECS', () => {
608610
expect(mockEcsWaiter).toHaveBeenCalledTimes(0);
609611
});
610612

611-
test('registers the task definition contents at an absolute path', async () => {
613+
test('registers the task definition contents at an absolute path', async () => {
612614
core.getInput = jest.fn().mockReturnValueOnce('/hello/task-definition.json');
613615
fs.readFileSync.mockImplementation((pathInput, encoding) => {
614616
if (encoding != 'utf8') {
@@ -649,7 +651,8 @@ describe('Deploy to ECS', () => {
649651
expect(mockEcsUpdateService).toHaveBeenNthCalledWith(1, {
650652
cluster: 'cluster-789',
651653
service: 'service-456',
652-
taskDefinition: 'task:def:arn'
654+
taskDefinition: 'task:def:arn',
655+
forceNewDeployment: false
653656
});
654657
expect(mockEcsWaiter).toHaveBeenNthCalledWith(1, 'servicesStable', {
655658
services: ['service-456'],
@@ -668,7 +671,7 @@ describe('Deploy to ECS', () => {
668671
.mockReturnValueOnce('service-456') // service
669672
.mockReturnValueOnce('cluster-789') // cluster
670673
.mockReturnValueOnce('TRUE') // wait-for-service-stability
671-
.mockReturnValue('60'); // wait-for-minutes
674+
.mockReturnValueOnce('60'); // wait-for-minutes
672675

673676
await run();
674677
expect(core.setFailed).toHaveBeenCalledTimes(0);
@@ -682,7 +685,8 @@ describe('Deploy to ECS', () => {
682685
expect(mockEcsUpdateService).toHaveBeenNthCalledWith(1, {
683686
cluster: 'cluster-789',
684687
service: 'service-456',
685-
taskDefinition: 'task:def:arn'
688+
taskDefinition: 'task:def:arn',
689+
forceNewDeployment: false
686690
});
687691
expect(mockEcsWaiter).toHaveBeenNthCalledWith(1, 'servicesStable', {
688692
services: ['service-456'],
@@ -701,7 +705,7 @@ describe('Deploy to ECS', () => {
701705
.mockReturnValueOnce('service-456') // service
702706
.mockReturnValueOnce('cluster-789') // cluster
703707
.mockReturnValueOnce('TRUE') // wait-for-service-stability
704-
.mockReturnValue('1000'); // wait-for-minutes
708+
.mockReturnValueOnce('1000'); // wait-for-minutes
705709

706710
await run();
707711
expect(core.setFailed).toHaveBeenCalledTimes(0);
@@ -715,7 +719,8 @@ describe('Deploy to ECS', () => {
715719
expect(mockEcsUpdateService).toHaveBeenNthCalledWith(1, {
716720
cluster: 'cluster-789',
717721
service: 'service-456',
718-
taskDefinition: 'task:def:arn'
722+
taskDefinition: 'task:def:arn',
723+
forceNewDeployment: false
719724
});
720725
expect(mockEcsWaiter).toHaveBeenNthCalledWith(1, 'servicesStable', {
721726
services: ['service-456'],
@@ -727,6 +732,33 @@ describe('Deploy to ECS', () => {
727732
});
728733
});
729734

735+
test('force new deployment', async () => {
736+
core.getInput = jest
737+
.fn()
738+
.mockReturnValueOnce('task-definition.json') // task-definition
739+
.mockReturnValueOnce('service-456') // service
740+
.mockReturnValueOnce('cluster-789') // cluster
741+
.mockReturnValueOnce('false') // wait-for-service-stability
742+
.mockReturnValueOnce('') // wait-for-minutes
743+
.mockReturnValueOnce(true); // force-new-deployment
744+
745+
await run();
746+
expect(core.setFailed).toHaveBeenCalledTimes(0);
747+
748+
expect(mockEcsRegisterTaskDef).toHaveBeenNthCalledWith(1, { family: 'task-def-family'});
749+
expect(core.setOutput).toHaveBeenNthCalledWith(1, 'task-definition-arn', 'task:def:arn');
750+
expect(mockEcsDescribeServices).toHaveBeenNthCalledWith(1, {
751+
cluster: 'cluster-789',
752+
services: ['service-456']
753+
});
754+
expect(mockEcsUpdateService).toHaveBeenNthCalledWith(1, {
755+
cluster: 'cluster-789',
756+
service: 'service-456',
757+
taskDefinition: 'task:def:arn',
758+
forceNewDeployment: true
759+
});
760+
});
761+
730762
test('defaults to the default cluster', async () => {
731763
core.getInput = jest
732764
.fn()
@@ -745,7 +777,8 @@ describe('Deploy to ECS', () => {
745777
expect(mockEcsUpdateService).toHaveBeenNthCalledWith(1, {
746778
cluster: 'default',
747779
service: 'service-456',
748-
taskDefinition: 'task:def:arn'
780+
taskDefinition: 'task:def:arn',
781+
forceNewDeployment: false
749782
});
750783
});
751784

@@ -847,7 +880,6 @@ describe('Deploy to ECS', () => {
847880
expect(core.setFailed).toBeCalledWith('Unsupported deployment controller: EXTERNAL');
848881
});
849882

850-
851883
test('error is caught if task def registration fails', async () => {
852884
mockEcsRegisterTaskDef.mockImplementation(() => {
853885
throw new Error("Could not parse");
@@ -859,4 +891,4 @@ describe('Deploy to ECS', () => {
859891
expect(core.setFailed).toHaveBeenNthCalledWith(1, 'Failed to register task definition in ECS: Could not parse');
860892
expect(core.setFailed).toHaveBeenNthCalledWith(2, 'Could not parse');
861893
});
862-
});
894+
});

0 commit comments

Comments
 (0)