Skip to content

Commit ce69720

Browse files
committed
"Added support for creating individual clusters for tasks and services, updated runTask and updateEcsService functions to use new cluster names, and modified tests to accommodate new cluster creation"
1 parent 9bf2bd1 commit ce69720

File tree

3 files changed

+176
-36
lines changed

3 files changed

+176
-36
lines changed

action.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,22 @@ inputs:
5757
run-task-launch-type:
5858
description: "ECS launch type for tasks run outside of a service. Valid values are 'FARGATE' or 'EC2'. Will default to 'FARGATE'."
5959
required: false
60+
run-task-capacity-provider-strategy:
61+
description: "Allows users who use capacity provider to have the launch type ommited"
62+
required: false
6063
run-task-started-by:
6164
description: "A name to use for the startedBy tag when running a task outside of a service. Will default to 'GitHub-Actions'."
6265
required: false
6366
wait-for-task-stopped:
6467
description: 'Whether to wait for the task to stop when running it outside of a service. Will default to not wait.'
6568
required: false
69+
task-cluster-name:
70+
description: 'Whether to run the task or service within the same cluster or in different clusters'
71+
required: false
72+
service-cluster-name:
73+
description: 'Whether to run the task or service within the same cluster or in different clusters'
74+
required: false
75+
6676
#back to normal inputs
6777
outputs:
6878
task-definition-arn:

index.js

Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
const path = require('path');
22
const core = require('@actions/core');
33
const { CodeDeploy, waitUntilDeploymentSuccessful } = require('@aws-sdk/client-codedeploy');
4-
const { ECS, waitUntilServicesStable, waitUntilTasksStopped } = require('@aws-sdk/client-ecs');
4+
const { ECS, waitUntilServicesStable, waitUntilTasksStopped,CreateClusterCommand} = require('@aws-sdk/client-ecs');
55
const yaml = require('yaml');
66
const fs = require('fs');
77
const crypto = require('crypto');
8+
const { default: cluster } = require('cluster');
89

910
const MAX_WAIT_MINUTES = 360; // 6 hours
1011
const WAIT_DEFAULT_DELAY_SEC = 15;
@@ -21,6 +22,50 @@ const IGNORED_TASK_DEFINITION_ATTRIBUTES = [
2122
'registeredBy'
2223
];
2324

25+
async function createClusterCommand(){
26+
const taskClusterName = core.getInput('task-cluster-name', { required: true } ) || 'default';
27+
const serviceClusterName = core.getInput('service-cluster-name', { required: true })|| 'default';
28+
29+
// Creating an individual cluster for service or task
30+
if(createTaskCluster){
31+
core.debug('Creating a single cluster for a one-off task ...');
32+
const createTaskClusterInput = {
33+
clusterTaskName: `github-actions-task-cluster-${Date.now}`,
34+
tags:[
35+
{
36+
key:'github-actions-task-cluster',
37+
value:'true'
38+
}
39+
]
40+
};
41+
const createTaskClusterCommand = new CreateClusterCommand(createTaskClusterInput);
42+
const createTaskClusterResponse = await ecs.send(createTaskClusterCommand);
43+
taskClusterName = createTaskClusterResponse.cluster.clusterTaskName;
44+
core.setOutput('task-cluster-name', taskClusterName);
45+
46+
}
47+
else if(createServiceCluster){
48+
core.debug('Creating a new cluster for a service ...');
49+
const createServiceClusterInput ={
50+
clusterServiceName: `github-actions-service-cluster-${Date.now}`,
51+
tags:[
52+
{
53+
key:'github-actions-service-cluster',
54+
value:'true'
55+
}
56+
]
57+
};
58+
const createServiceClusterCommand = new CreateClusterCommand(createServiceClusterInput);
59+
const createServiceClusterResponse = await ecs.send(createServiceClusterCommand);
60+
serviceClusterName = createServiceClusterResponse.cluster.clusterServiceName;
61+
core.setOutput('service-cluster-name', serviceClusterName);
62+
}
63+
else{
64+
core.debug('Running using the default cluster');
65+
}
66+
67+
}
68+
2469
//Code to run task outside of a service aka (also known as) a one-off task
2570

2671
async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
@@ -29,6 +74,7 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
2974
const waitForTask = core.getInput('wait-for-task-stopped', { required: false }) || 'false';
3075
const startedBy = core.getInput('run-task-started-by', { required: false }) || 'GitHub-Actions';
3176
const launchType = core.getInput('run-task-launch-type', { required: false }) || 'FARGATE';
77+
const capacityProviderStrategy = core.getInput('run-task-capacity-provider-strategy', {required: false});
3278
const subnetIds = core.getInput('run-task-subnets', { required: false }) || '';
3379
const securityGroupIds = core.getInput('run-task-security-groups', { required: false }) || '';
3480
const containerOverrides = JSON.parse(core.getInput('run-task-container-overrides', { required: false }) || '[]');
@@ -43,6 +89,14 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
4389
awsvpcConfiguration["securityGroups"] = securityGroupIds.split(',')
4490
}
4591

92+
if (capacityProviderStrategy){
93+
//if the capacity provider is given then the launch type is ommited
94+
launchType = undefined;
95+
}
96+
else{
97+
launchType = launchType || 'FARGATE';
98+
}
99+
46100
const runTaskResponse = await ecs.runTask({
47101
startedBy: startedBy,
48102
cluster: clusterName,
@@ -126,7 +180,6 @@ async function tasksExitCode(ecs, clusterName, taskArns) {
126180
}
127181

128182

129-
130183
// Deploy to a service that uses the 'ECS' deployment controller
131184
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount) {
132185
core.debug('Updating the service');
@@ -386,8 +439,8 @@ async function run() {
386439
const forceNewDeployInput = core.getInput('force-new-deployment', { required: false }) || 'false';
387440
const forceNewDeployment = forceNewDeployInput.toLowerCase() === 'true';
388441
const desiredCount = parseInt((core.getInput('desired-count', {required: false})));
389-
390-
442+
443+
391444
// Register the task definition
392445
core.debug('Registering the task definition');
393446
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
@@ -406,18 +459,30 @@ async function run() {
406459
}
407460
const taskDefArn = registerResponse.taskDefinition.taskDefinitionArn;
408461
core.setOutput('task-definition-arn', taskDefArn);
409-
410-
462+
411463
// Run the task outside of the service
412464
const clusterName = cluster ? cluster : 'default';
413465
const shouldRunTaskInput = core.getInput('run-task', { required: false }) || 'false';
414466
const shouldRunTask = shouldRunTaskInput.toLowerCase() === 'true';
467+
const taskClusterNameInput = core.getInput('task-cluster-name', { required: true } ) || 'default';
468+
const taskClusterNameRun = taskClusterNameInput.toLowerCase() === 'task';
415469
core.debug(`shouldRunTask: ${shouldRunTask}`);
470+
416471
if (shouldRunTask) {
417-
core.debug("Running ad-hoc task...");
472+
core.debug("Running one-off task...");
473+
if(taskClusterNameRun == 'task'){
474+
core.debug("Running one-off task in an individual cluster ...");
475+
await runTask(ecs, createClusterCommand, taskDefArn, waitForMinutes);
476+
}
477+
else{
478+
core.debug('The default cluster will be used to execute your one-off task')
479+
}
418480
await runTask(ecs, clusterName, taskDefArn, waitForMinutes);
419481
}
420482

483+
const serviceClusterNameInput = core.getInput('service-cluster-name', { required: true } ) || 'default';
484+
const serviceClusterNameRun = serviceClusterNameInput.toLowerCase() === 'service';
485+
421486
// Update the service with the new task definition
422487
if (service) {
423488
//const clusterName = cluster ? cluster : 'default';
@@ -440,9 +505,24 @@ async function run() {
440505

441506
if (!serviceResponse.deploymentController || !serviceResponse.deploymentController.type || serviceResponse.deploymentController.type === 'ECS') {
442507
// Service uses the 'ECS' deployment controller, so we can call UpdateService
508+
core.debug('Updating service...');
509+
510+
if(serviceClusterNameRun == 'service'){
511+
core.debug('Running service in a individual cluster...');
512+
await updateEcsService(ecs, createClusterCommand, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount);
513+
}
514+
core.debug('Running your service in the default cluster');
515+
443516
await updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount);
517+
444518
} else if (serviceResponse.deploymentController.type === 'CODE_DEPLOY') {
445519
// Service uses CodeDeploy, so we should start a CodeDeploy deployment
520+
core.debug('deploying service in selected cluster...')
521+
if(serviceClusterNameRun == 'service'){
522+
core.debug('Deploying service in a individual cluster...');
523+
await updateEcsService(ecs, createClusterCommand, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount);
524+
}
525+
core.debug('Deploying service in the default cluster');
446526
await createCodeDeployDeployment(codedeploy, clusterName, service, taskDefArn, waitForService, waitForMinutes);
447527
} else {
448528
throw new Error(`Unsupported deployment controller: ${serviceResponse.deploymentController.type}`);

0 commit comments

Comments
 (0)