Skip to content

Commit

Permalink
feat: add run-task-capacity-provider-strategy input (#661)
Browse files Browse the repository at this point in the history
When you use cluster auto scaling, you must specify `capacityProviderStrategy` and not `launchType`. Unfortunately this is not possible to configure when running a one-off task with this action.

This adds a new input `run-task-capacity-provider-strategy` which takes a JSON array of capacity provider strategy items. When this is specified, `run-task-launch-type` will not be applied.
  • Loading branch information
stenlarsson authored Nov 12, 2024
1 parent 96cda52 commit 6ebedf4
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 3 deletions.
5 changes: 4 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,11 @@ inputs:
run-task-assign-public-IP:
description: "Whether the task's elastic network interface receives a public IP address. The default value is DISABLED but will only be applied if run-task-subnets or run-task-security-groups are also set."
required: false
run-task-capacity-provider-strategy:
description: 'A JSON array of capacity provider strategy items which should applied when running a task outside of a service. Will default to none.'
required: false
run-task-launch-type:
description: "ECS launch type for tasks run outside of a service. Valid values are 'FARGATE' or 'EC2'. Will default to 'FARGATE'."
description: "ECS launch type for tasks run outside of a service. Valid values are 'FARGATE' or 'EC2'. Will default to 'FARGATE'. Will only be applied if run-task-capacity-provider-strategy is not set."
required: false
run-task-started-by:
description: "A name to use for the startedBy tag when running a task outside of a service. Will default to 'GitHub-Actions'."
Expand Down
4 changes: 3 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
const containerOverrides = JSON.parse(core.getInput('run-task-container-overrides', { required: false }) || '[]');
const assignPublicIP = core.getInput('run-task-assign-public-IP', { required: false }) || 'DISABLED';
const tags = JSON.parse(core.getInput('run-task-tags', { required: false }) || '[]');
const capacityProviderStrategy = JSON.parse(core.getInput('run-task-capacity-provider-strategy', { required: false }) || '[]');

let awsvpcConfiguration = {}

Expand All @@ -60,7 +61,8 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
overrides: {
containerOverrides: containerOverrides
},
launchType: launchType,
capacityProviderStrategy: capacityProviderStrategy.length === 0 ? null : capacityProviderStrategy,
launchType: capacityProviderStrategy.length === 0 ? launchType : null,
networkConfiguration: Object.keys(awsvpcConfiguration).length === 0 ? null : { awsvpcConfiguration: awsvpcConfiguration },
enableECSManagedTags: enableECSManagedTags,
tags: tags
Expand Down
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
const containerOverrides = JSON.parse(core.getInput('run-task-container-overrides', { required: false }) || '[]');
const assignPublicIP = core.getInput('run-task-assign-public-IP', { required: false }) || 'DISABLED';
const tags = JSON.parse(core.getInput('run-task-tags', { required: false }) || '[]');
const capacityProviderStrategy = JSON.parse(core.getInput('run-task-capacity-provider-strategy', { required: false }) || '[]');

let awsvpcConfiguration = {}

Expand All @@ -54,7 +55,8 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
overrides: {
containerOverrides: containerOverrides
},
launchType: launchType,
capacityProviderStrategy: capacityProviderStrategy.length === 0 ? null : capacityProviderStrategy,
launchType: capacityProviderStrategy.length === 0 ? launchType : null,
networkConfiguration: Object.keys(awsvpcConfiguration).length === 0 ? null : { awsvpcConfiguration: awsvpcConfiguration },
enableECSManagedTags: enableECSManagedTags,
tags: tags
Expand Down
46 changes: 46 additions & 0 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,7 @@ describe('Deploy to ECS', () => {
expect(mockRunTask).toHaveBeenNthCalledWith(1,{
startedBy: 'GitHub-Actions',
cluster: 'default',
capacityProviderStrategy: null,
launchType: 'FARGATE',
taskDefinition: 'task:def:arn',
overrides: {"containerOverrides": []},
Expand Down Expand Up @@ -1185,6 +1186,7 @@ describe('Deploy to ECS', () => {
expect(mockRunTask).toHaveBeenCalledWith({
startedBy: 'someJoe',
cluster: 'somecluster',
capacityProviderStrategy: null,
launchType: 'EC2',
taskDefinition: 'task:def:arn',
overrides: { containerOverrides: [{ name: 'someapp', command: 'somecmd' }] },
Expand All @@ -1195,6 +1197,48 @@ describe('Deploy to ECS', () => {
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'run-task-arn', ["arn:aws:ecs:fake-region:account_id:task/arn"]);
});

test('run task with capacity provider strategy', async () => {
core.getInput = jest
.fn()
.mockReturnValueOnce('task-definition.json') // task-definition
.mockReturnValueOnce('') // service
.mockReturnValueOnce('somecluster') // cluster
.mockReturnValueOnce('') // wait-for-service-stability
.mockReturnValueOnce('') // wait-for-minutes
.mockReturnValueOnce('') // force-new-deployment
.mockReturnValueOnce('') // desired-count
.mockReturnValueOnce('false') // enable-ecs-managed-tags
.mockReturnValueOnce('') // propagate-tags
.mockReturnValueOnce('true') // run-task
.mockReturnValueOnce('false') // wait-for-task-stopped
.mockReturnValueOnce('someJoe') // run-task-started-by
.mockReturnValueOnce('') // run-task-launch-type
.mockReturnValueOnce('a,b') // run-task-subnet-ids
.mockReturnValueOnce('c,d') // run-task-security-group-ids
.mockReturnValueOnce(JSON.stringify([{ name: 'someapp', command: 'somecmd' }])) // run-task-container-overrides
.mockReturnValueOnce('') // run-task-assign-public-IP
.mockReturnValueOnce('[{"key": "project", "value": "myproject"}]') // run-task-tags
.mockReturnValueOnce('[{"capacityProvider":"FARGATE_SPOT","weight":1}]'); // run-task-capacity-provider-strategy

await run();
expect(core.setFailed).toHaveBeenCalledTimes(0);

expect(mockEcsRegisterTaskDef).toHaveBeenNthCalledWith(1, { family: 'task-def-family' });
expect(core.setOutput).toHaveBeenNthCalledWith(1, 'task-definition-arn', 'task:def:arn');
expect(mockRunTask).toHaveBeenCalledWith({
startedBy: 'someJoe',
cluster: 'somecluster',
capacityProviderStrategy: [{"capacityProvider":"FARGATE_SPOT","weight":1}],
launchType: null,
taskDefinition: 'task:def:arn',
overrides: { containerOverrides: [{ name: 'someapp', command: 'somecmd' }] },
networkConfiguration: { awsvpcConfiguration: { subnets: ['a', 'b'], securityGroups: ['c', 'd'], assignPublicIp: "DISABLED" } },
enableECSManagedTags: false,
tags: [{"key": "project", "value": "myproject"}],
});
expect(core.setOutput).toHaveBeenNthCalledWith(2, 'run-task-arn', ["arn:aws:ecs:fake-region:account_id:task/arn"]);
});

test('run task and service ', async () => {
core.getInput = jest
.fn()
Expand Down Expand Up @@ -1236,6 +1280,7 @@ describe('Deploy to ECS', () => {
startedBy: 'someJoe',
cluster: 'somecluster',
taskDefinition: 'task:def:arn',
capacityProviderStrategy: null,
launchType: 'EC2',
overrides: { containerOverrides: [{ name: 'someapp', command: 'somecmd' }] },
networkConfiguration: { awsvpcConfiguration: { subnets: ['a', 'b'], securityGroups: ['c', 'd'], assignPublicIp: "DISABLED" } },
Expand Down Expand Up @@ -1296,6 +1341,7 @@ describe('Deploy to ECS', () => {
startedBy: 'someJoe',
cluster: 'somecluster',
taskDefinition: 'task:def:arn',
capacityProviderStrategy: null,
launchType: 'EC2',
overrides: { containerOverrides: [] },
networkConfiguration: null,
Expand Down

0 comments on commit 6ebedf4

Please sign in to comment.