1
1
const path = require ( 'path' ) ;
2
2
const core = require ( '@actions/core' ) ;
3
3
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' ) ;
5
5
const yaml = require ( 'yaml' ) ;
6
6
const fs = require ( 'fs' ) ;
7
7
const crypto = require ( 'crypto' ) ;
8
+ const { default : cluster } = require ( 'cluster' ) ;
8
9
9
10
const MAX_WAIT_MINUTES = 360 ; // 6 hours
10
11
const WAIT_DEFAULT_DELAY_SEC = 15 ;
@@ -21,6 +22,50 @@ const IGNORED_TASK_DEFINITION_ATTRIBUTES = [
21
22
'registeredBy'
22
23
] ;
23
24
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
+
24
69
//Code to run task outside of a service aka (also known as) a one-off task
25
70
26
71
async function runTask ( ecs , clusterName , taskDefArn , waitForMinutes ) {
@@ -29,6 +74,7 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
29
74
const waitForTask = core . getInput ( 'wait-for-task-stopped' , { required : false } ) || 'false' ;
30
75
const startedBy = core . getInput ( 'run-task-started-by' , { required : false } ) || 'GitHub-Actions' ;
31
76
const launchType = core . getInput ( 'run-task-launch-type' , { required : false } ) || 'FARGATE' ;
77
+ const capacityProviderStrategy = core . getInput ( 'run-task-capacity-provider-strategy' , { required : false } ) ;
32
78
const subnetIds = core . getInput ( 'run-task-subnets' , { required : false } ) || '' ;
33
79
const securityGroupIds = core . getInput ( 'run-task-security-groups' , { required : false } ) || '' ;
34
80
const containerOverrides = JSON . parse ( core . getInput ( 'run-task-container-overrides' , { required : false } ) || '[]' ) ;
@@ -43,6 +89,14 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
43
89
awsvpcConfiguration [ "securityGroups" ] = securityGroupIds . split ( ',' )
44
90
}
45
91
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
+
46
100
const runTaskResponse = await ecs . runTask ( {
47
101
startedBy : startedBy ,
48
102
cluster : clusterName ,
@@ -126,7 +180,6 @@ async function tasksExitCode(ecs, clusterName, taskArns) {
126
180
}
127
181
128
182
129
-
130
183
// Deploy to a service that uses the 'ECS' deployment controller
131
184
async function updateEcsService ( ecs , clusterName , service , taskDefArn , waitForService , waitForMinutes , forceNewDeployment , desiredCount ) {
132
185
core . debug ( 'Updating the service' ) ;
@@ -386,8 +439,8 @@ async function run() {
386
439
const forceNewDeployInput = core . getInput ( 'force-new-deployment' , { required : false } ) || 'false' ;
387
440
const forceNewDeployment = forceNewDeployInput . toLowerCase ( ) === 'true' ;
388
441
const desiredCount = parseInt ( ( core . getInput ( 'desired-count' , { required : false } ) ) ) ;
389
-
390
-
442
+
443
+
391
444
// Register the task definition
392
445
core . debug ( 'Registering the task definition' ) ;
393
446
const taskDefPath = path . isAbsolute ( taskDefinitionFile ) ?
@@ -406,18 +459,30 @@ async function run() {
406
459
}
407
460
const taskDefArn = registerResponse . taskDefinition . taskDefinitionArn ;
408
461
core . setOutput ( 'task-definition-arn' , taskDefArn ) ;
409
-
410
-
462
+
411
463
// Run the task outside of the service
412
464
const clusterName = cluster ? cluster : 'default' ;
413
465
const shouldRunTaskInput = core . getInput ( 'run-task' , { required : false } ) || 'false' ;
414
466
const shouldRunTask = shouldRunTaskInput . toLowerCase ( ) === 'true' ;
467
+ const taskClusterNameInput = core . getInput ( 'task-cluster-name' , { required : true } ) || 'default' ;
468
+ const taskClusterNameRun = taskClusterNameInput . toLowerCase ( ) === 'task' ;
415
469
core . debug ( `shouldRunTask: ${ shouldRunTask } ` ) ;
470
+
416
471
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
+ }
418
480
await runTask ( ecs , clusterName , taskDefArn , waitForMinutes ) ;
419
481
}
420
482
483
+ const serviceClusterNameInput = core . getInput ( 'service-cluster-name' , { required : true } ) || 'default' ;
484
+ const serviceClusterNameRun = serviceClusterNameInput . toLowerCase ( ) === 'service' ;
485
+
421
486
// Update the service with the new task definition
422
487
if ( service ) {
423
488
//const clusterName = cluster ? cluster : 'default';
@@ -440,9 +505,24 @@ async function run() {
440
505
441
506
if ( ! serviceResponse . deploymentController || ! serviceResponse . deploymentController . type || serviceResponse . deploymentController . type === 'ECS' ) {
442
507
// 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
+
443
516
await updateEcsService ( ecs , clusterName , service , taskDefArn , waitForService , waitForMinutes , forceNewDeployment , desiredCount ) ;
517
+
444
518
} else if ( serviceResponse . deploymentController . type === 'CODE_DEPLOY' ) {
445
519
// 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' ) ;
446
526
await createCodeDeployDeployment ( codedeploy , clusterName , service , taskDefArn , waitForService , waitForMinutes ) ;
447
527
} else {
448
528
throw new Error ( `Unsupported deployment controller: ${ serviceResponse . deploymentController . type } ` ) ;
0 commit comments