Skip to content

Commit ce2218e

Browse files
committed
ugh
1 parent fc62b08 commit ce2218e

File tree

1 file changed

+111
-2
lines changed

1 file changed

+111
-2
lines changed

dist/index.js

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,107 @@ const IGNORED_TASK_DEFINITION_ATTRIBUTES = [
192192
'registeredBy'
193193
];
194194

195+
// Run task outside of a service
196+
async function runTask(ecs, clusterName, taskDefArn, waitForMinutes) {
197+
core.info('Running task')
198+
199+
const waitForTask = core.getInput('wait-for-task-stopped', { required: false }) || 'false';
200+
const startedBy = core.getInput('run-task-started-by', { required: false }) || 'GitHub-Actions';
201+
const launchType = core.getInput('run-task-launch-type', { required: false }) || 'FARGATE';
202+
const subnetIds = core.getInput('run-task-subnet-ids', { required: false }) || '';
203+
const securityGroupIds = core.getInput('run-task-security-group-ids', { required: false }) || '';
204+
const containerOverrides = JSON.parse(core.getInput('run-task-container-overrides', { required: false }) || '[]');
205+
let awsVpcNetworkConfiguration = {}
206+
207+
if (subnetIds != "") {
208+
awsVpcNetworkConfiguration["subnets"] = subnetIds.split(',')
209+
}
210+
211+
if (securityGroupIds != "") {
212+
awsVpcNetworkConfiguration["securityGroups"] = securityGroupIds.split(',')
213+
}
214+
215+
const runTaskResponse = await ecs.runTask({
216+
startedBy: startedBy,
217+
cluster: clusterName,
218+
taskDefinition: taskDefArn,
219+
overrides: {
220+
containerOverrides: containerOverrides
221+
},
222+
launchType: launchType,
223+
networkConfiguration: awsVpcNetworkConfiguration === {} ? {} : { awsVpcNetworkConfiguration: awsVpcNetworkConfiguration }
224+
}).promise();
225+
226+
core.debug(`Run task response ${JSON.stringify(runTaskResponse)}`)
227+
228+
const taskArns = runTaskResponse.tasks.map(task => task.taskArn);
229+
core.setOutput('run-task-arn', taskArns);
230+
231+
taskArns.map(taskArn => {
232+
let taskId = taskArn.split('/').pop();
233+
core.info(`Task running: https://console.aws.amazon.com/ecs/home?region=${aws.config.region}#/clusters/${clusterName}/tasks`)
234+
});
235+
236+
if (runTaskResponse.failures && runTaskResponse.failures.length > 0) {
237+
const failure = runTaskResponse.failures[0];
238+
throw new Error(`${failure.arn} is ${failure.reason}`);
239+
}
240+
241+
// Wait for task to end
242+
if (waitForTask && waitForTask.toLowerCase() === "true") {
243+
await waitForTasksStopped(ecs, clusterName, taskArns, waitForMinutes)
244+
await tasksExitCode(ecs, clusterName, taskArns)
245+
} else {
246+
core.debug('Not waiting for the task to stop');
247+
}
248+
}
249+
250+
// Poll tasks until they enter a stopped state
251+
async function waitForTasksStopped(ecs, clusterName, taskArns, waitForMinutes) {
252+
if (waitForMinutes > MAX_WAIT_MINUTES) {
253+
waitForMinutes = MAX_WAIT_MINUTES;
254+
}
255+
256+
core.info(`Waiting for tasks to stop. Will wait for ${waitForMinutes} minutes`);
257+
258+
const waitTaskResponse = await ecs.waitFor('tasksStopped', {
259+
cluster: clusterName,
260+
tasks: taskArns,
261+
$waiter: {
262+
delay: WAIT_DEFAULT_DELAY_SEC,
263+
maxAttempts: (waitForMinutes * 60) / WAIT_DEFAULT_DELAY_SEC
264+
}
265+
}).promise();
266+
267+
core.debug(`Run task response ${JSON.stringify(waitTaskResponse)}`);
268+
core.info('All tasks have stopped.');
269+
}
270+
271+
// Check a task's exit code and fail the job on error
272+
async function tasksExitCode(ecs, clusterName, taskArns) {
273+
const describeResponse = await ecs.describeTasks({
274+
cluster: clusterName,
275+
tasks: taskArns
276+
}).promise();
277+
278+
const containers = [].concat(...describeResponse.tasks.map(task => task.containers))
279+
const exitCodes = containers.map(container => container.exitCode)
280+
const reasons = containers.map(container => container.reason)
281+
282+
const failuresIdx = [];
283+
284+
exitCodes.filter((exitCode, index) => {
285+
if (exitCode !== 0) {
286+
failuresIdx.push(index)
287+
}
288+
})
289+
290+
const failures = reasons.filter((_, index) => failuresIdx.indexOf(index) !== -1)
291+
if (failures.length > 0) {
292+
throw new Error(`Run task failed: ${JSON.stringify(failures)}`);
293+
}
294+
}
295+
195296
// Deploy to a service that uses the 'ECS' deployment controller
196297
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment) {
197298
core.debug('Updating the service');
@@ -457,10 +558,18 @@ async function run() {
457558
const taskDefArn = registerResponse.taskDefinition.taskDefinitionArn;
458559
core.setOutput('task-definition-arn', taskDefArn);
459560

561+
// Run the task outside of the service
562+
const clusterName = cluster ? cluster : 'default';
563+
const shouldRunTaskInput = core.getInput('run-task', { required: false }) || 'false';
564+
const shouldRunTask = shouldRunTaskInput.toLowerCase() === 'true';
565+
core.debug(`shouldRunTask: ${shouldRunTask}`);
566+
if (shouldRunTask) {
567+
core.debug("Running ad-hoc task...");
568+
await runTask(ecs, clusterName, taskDefArn, waitForMinutes);
569+
}
570+
460571
// Update the service with the new task definition
461572
if (service) {
462-
const clusterName = cluster ? cluster : 'default';
463-
464573
// Determine the deployment controller
465574
const describeResponse = await ecs.describeServices({
466575
services: [service],

0 commit comments

Comments
 (0)