unity-builder/src/model/aws.js

136 lines
4.1 KiB
JavaScript

/* eslint-disable no-plusplus */
/* eslint-disable no-await-in-loop */
import * as SDK from 'aws-sdk';
const fs = require('fs');
const core = require('@actions/core');
class AWS {
static async runBuildJob(buildParameters, baseImage) {
SDK.config.update({ region: buildParameters.awsRegion });
await this.run(buildParameters.awsStackName, baseImage.toString());
}
static async run(stackName, image) {
const ECS = new SDK.ECS();
const CF = new SDK.CloudFormation();
const taskDefStackName = `${stackName}-taskDef-${image}`;
const stackExists =
(await CF.listStacks().promise()).StackSummaries.find(
(x) => x.StackName === taskDefStackName,
) !== undefined;
if (!stackExists) {
core.info("Task Definition doesn't exist, creating a task definition stack");
const taskDefCloudFormation = fs.readFileSync(`${__dirname}\\task-def-formation.yml`, 'utf8');
await CF.createStack({
StackName: taskDefStackName,
TemplateBody: taskDefCloudFormation,
Parameters: [
{
ParameterKey: 'ImageUrl',
ParameterValue: image,
},
],
}).promise();
await CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise();
} else {
core.info('Task definition stack exists already');
}
const taskDefResources = await CF.describeStackResources({
StackName: taskDefStackName,
}).promise();
const baseResources = await CF.describeStackResources({ StackName: stackName }).promise();
const clusterName = baseResources.StackResources.find(
(x) => x.LogicalResourceId === 'ECSCluster',
).PhysicalResourceId;
const task = await ECS.runTask({
cluster: clusterName,
taskDefinition: taskDefResources.StackResources.find(
(x) => x.LogicalResourceId === 'TaskDefinition',
).PhysicalResourceId,
platformVersion: '1.4.0',
launchType: 'FARGATE',
overrides: {
containerOverrides: [
{
name: 'example',
// command: ["echo 't'"],
// environment: []
},
],
},
networkConfiguration: {
awsvpcConfiguration: {
subnets: [
baseResources.StackResources.find((x) => x.LogicalResourceId === 'PublicSubnetOne')
.PhysicalResourceId,
baseResources.StackResources.find((x) => x.LogicalResourceId === 'PublicSubnetTwo')
.PhysicalResourceId,
],
assignPublicIp: 'ENABLED',
securityGroups: [
baseResources.StackResources.find(
(x) => x.LogicalResourceId === 'ContainerSecurityGroup',
).PhysicalResourceId,
],
},
},
}).promise();
await ECS.waitFor('tasksRunning', {
cluster: clusterName,
tasks: [task],
}).promise();
core.info('Build job is running, watching logs');
// watching logs
await this.watch(async () => {
return (await ECS.describeTasks({ tasks: [task], cluster: clusterName }).promise()).tasks[0]
.lastStatus;
}, 'example');
await ECS.waitFor('tasksStopped', {
cluster: clusterName,
tasks: [task],
}).promise();
core.info('Build job has ended');
return task;
}
static async watch(statusFunc, logGroupName) {
const CloudWatchLogs = new SDK.CloudWatchLogs();
let latestLogTimestamp = new Date().getUTCSeconds();
let complete = false;
while (!complete) {
await new Promise((resolve) => setTimeout(resolve, 10000));
if ((await statusFunc()) === 'Stopped') {
complete = true;
}
const log = await CloudWatchLogs.getLogEvents({
startTime: latestLogTimestamp,
logGroupName,
logStreamName: (
await CloudWatchLogs.describeLogStreams({
logGroupName,
}).promise()
).logStreams[0].logStreamName,
}).promise();
if (log.events.length > 0) {
for (let index = 0; index < log.events.length; index++) {
core.info(log.events[index].message);
}
latestLogTimestamp = log.events[log.events.length - 1].timestamp;
}
}
}
}
export default AWS;