catch stack creation errors

pull/263/head
Frostebite 2021-05-22 00:48:47 +01:00
parent 7b98b2c992
commit 4e4e9e0b11
5 changed files with 158 additions and 144 deletions

145
dist/index.js vendored
View File

@ -54,7 +54,7 @@ function run() {
break; break;
case 'aws': case 'aws':
core.info('Building with AWS'); core.info('Building with AWS');
yield model_1.AWS.runBuildJob(buildParameters, baseImage); yield model_1.AWS.build(buildParameters, baseImage);
break; break;
// default and local case // default and local case
default: default:
@ -1231,6 +1231,8 @@ class AWSBuildEnvironment {
`; `;
const taskDefStackName = `${stackName}-${buildUid}`; const taskDefStackName = `${stackName}-${buildUid}`;
let taskDefCloudFormation = this.readTaskCloudFormationTemplate(); let taskDefCloudFormation = this.readTaskCloudFormationTemplate();
const cleanupTaskDefStackName = `${taskDefStackName}-cleanup`;
const cleanupCloudFormation = fs.readFileSync(`${__dirname}/cloud-formations/cloudformation-stack-ttl.yml`, 'utf8');
// Debug secrets // Debug secrets
// core.info(JSON.stringify(secrets, undefined, 4)); // core.info(JSON.stringify(secrets, undefined, 4));
for (const secret of secrets) { for (const secret of secrets) {
@ -1274,78 +1276,71 @@ class AWSBuildEnvironment {
const mappedSecrets = secrets.map((x) => { const mappedSecrets = secrets.map((x) => {
return { ParameterKey: x.ParameterKey.replace(/[^\dA-Za-z]/g, ''), ParameterValue: x.ParameterValue }; return { ParameterKey: x.ParameterKey.replace(/[^\dA-Za-z]/g, ''), ParameterValue: x.ParameterValue };
}); });
yield CF.createStack({
StackName: taskDefStackName,
TemplateBody: taskDefCloudFormation,
Parameters: [
{
ParameterKey: 'ImageUrl',
ParameterValue: image,
},
{
ParameterKey: 'ServiceName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'Command',
ParameterValue: commands.join(','),
},
{
ParameterKey: 'EntryPoint',
ParameterValue: entrypoint.join(','),
},
{
ParameterKey: 'WorkingDirectory',
ParameterValue: workingdir,
},
{
ParameterKey: 'EFSMountDirectory',
ParameterValue: mountdir,
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
...mappedSecrets,
],
}).promise();
core.info('Creating worker cluster...');
const cleanupTaskDefStackName = `${taskDefStackName}-cleanup`;
const cleanupCloudFormation = fs.readFileSync(`${__dirname}/cloud-formations/cloudformation-stack-ttl.yml`, 'utf8');
yield CF.createStack({
StackName: cleanupTaskDefStackName,
TemplateBody: cleanupCloudFormation,
Capabilities: ['CAPABILITY_IAM'],
Parameters: [
{
ParameterKey: 'StackName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'DeleteStackName',
ParameterValue: cleanupTaskDefStackName,
},
{
ParameterKey: 'TTL',
ParameterValue: '100',
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
],
}).promise();
core.info('Creating cleanup cluster...');
try { try {
yield CF.createStack({
StackName: taskDefStackName,
TemplateBody: taskDefCloudFormation,
Parameters: [
{
ParameterKey: 'ImageUrl',
ParameterValue: image,
},
{
ParameterKey: 'ServiceName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'Command',
ParameterValue: commands.join(','),
},
{
ParameterKey: 'EntryPoint',
ParameterValue: entrypoint.join(','),
},
{
ParameterKey: 'WorkingDirectory',
ParameterValue: workingdir,
},
{
ParameterKey: 'EFSMountDirectory',
ParameterValue: mountdir,
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
...mappedSecrets,
],
}).promise();
core.info('Creating worker cluster...');
yield CF.createStack({
StackName: cleanupTaskDefStackName,
TemplateBody: cleanupCloudFormation,
Capabilities: ['CAPABILITY_IAM'],
Parameters: [
{
ParameterKey: 'StackName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'DeleteStackName',
ParameterValue: cleanupTaskDefStackName,
},
{
ParameterKey: 'TTL',
ParameterValue: '100',
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
],
}).promise();
core.info('Creating cleanup cluster...');
yield CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise(); yield CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise();
} }
catch (error) { catch (error) {
core.error(error); yield AWSBuildEnvironment.handleStackCreationFailure(error, CF, taskDefStackName, taskDefCloudFormation);
const events = (yield CF.describeStackEvents({ StackName: taskDefStackName }).promise()).StackEvents;
const resources = (yield CF.describeStackResources({ StackName: taskDefStackName }).promise()).StackResources;
core.info(taskDefCloudFormation);
core.info(JSON.stringify(events, undefined, 4));
core.info(JSON.stringify(resources, undefined, 4));
throw error; throw error;
} }
const taskDefResources = (yield CF.describeStackResources({ const taskDefResources = (yield CF.describeStackResources({
@ -1365,6 +1360,16 @@ class AWSBuildEnvironment {
}; };
}); });
} }
static handleStackCreationFailure(error, CF, taskDefStackName, taskDefCloudFormation) {
return __awaiter(this, void 0, void 0, function* () {
core.error(error);
const events = (yield CF.describeStackEvents({ StackName: taskDefStackName }).promise()).StackEvents;
const resources = (yield CF.describeStackResources({ StackName: taskDefStackName }).promise()).StackResources;
core.info(taskDefCloudFormation);
core.info(JSON.stringify(events, undefined, 4));
core.info(JSON.stringify(resources, undefined, 4));
});
}
static readTaskCloudFormationTemplate() { static readTaskCloudFormationTemplate() {
return fs.readFileSync(`${__dirname}/cloud-formations/task-def-formation.yml`, 'utf8'); return fs.readFileSync(`${__dirname}/cloud-formations/task-def-formation.yml`, 'utf8');
} }
@ -1625,7 +1630,7 @@ const repositoryDirectoryName = 'repo';
const efsDirectoryName = 'data'; const efsDirectoryName = 'data';
const cacheDirectoryName = 'cache'; const cacheDirectoryName = 'cache';
class RemoteBuilder { class RemoteBuilder {
static runBuildJob(buildParameters, baseImage) { static build(buildParameters, baseImage) {
var _a; var _a;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,7 @@ async function run() {
case 'aws': case 'aws':
core.info('Building with AWS'); core.info('Building with AWS');
await AWS.runBuildJob(buildParameters, baseImage); await AWS.build(buildParameters, baseImage);
break; break;
// default and local case // default and local case

View File

@ -58,6 +58,8 @@ class AWSBuildEnvironment {
`; `;
const taskDefStackName = `${stackName}-${buildUid}`; const taskDefStackName = `${stackName}-${buildUid}`;
let taskDefCloudFormation = this.readTaskCloudFormationTemplate(); let taskDefCloudFormation = this.readTaskCloudFormationTemplate();
const cleanupTaskDefStackName = `${taskDefStackName}-cleanup`;
const cleanupCloudFormation = fs.readFileSync(`${__dirname}/cloud-formations/cloudformation-stack-ttl.yml`, 'utf8');
// Debug secrets // Debug secrets
// core.info(JSON.stringify(secrets, undefined, 4)); // core.info(JSON.stringify(secrets, undefined, 4));
@ -106,81 +108,72 @@ class AWSBuildEnvironment {
const mappedSecrets = secrets.map((x) => { const mappedSecrets = secrets.map((x) => {
return { ParameterKey: x.ParameterKey.replace(/[^\dA-Za-z]/g, ''), ParameterValue: x.ParameterValue }; return { ParameterKey: x.ParameterKey.replace(/[^\dA-Za-z]/g, ''), ParameterValue: x.ParameterValue };
}); });
await CF.createStack({
StackName: taskDefStackName,
TemplateBody: taskDefCloudFormation,
Parameters: [
{
ParameterKey: 'ImageUrl',
ParameterValue: image,
},
{
ParameterKey: 'ServiceName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'Command',
ParameterValue: commands.join(','),
},
{
ParameterKey: 'EntryPoint',
ParameterValue: entrypoint.join(','),
},
{
ParameterKey: 'WorkingDirectory',
ParameterValue: workingdir,
},
{
ParameterKey: 'EFSMountDirectory',
ParameterValue: mountdir,
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
...mappedSecrets,
],
}).promise();
core.info('Creating worker cluster...');
const cleanupTaskDefStackName = `${taskDefStackName}-cleanup`;
const cleanupCloudFormation = fs.readFileSync(`${__dirname}/cloud-formations/cloudformation-stack-ttl.yml`, 'utf8');
await CF.createStack({
StackName: cleanupTaskDefStackName,
TemplateBody: cleanupCloudFormation,
Capabilities: ['CAPABILITY_IAM'],
Parameters: [
{
ParameterKey: 'StackName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'DeleteStackName',
ParameterValue: cleanupTaskDefStackName,
},
{
ParameterKey: 'TTL',
ParameterValue: '100',
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
],
}).promise();
core.info('Creating cleanup cluster...');
try { try {
await CF.createStack({
StackName: taskDefStackName,
TemplateBody: taskDefCloudFormation,
Parameters: [
{
ParameterKey: 'ImageUrl',
ParameterValue: image,
},
{
ParameterKey: 'ServiceName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'Command',
ParameterValue: commands.join(','),
},
{
ParameterKey: 'EntryPoint',
ParameterValue: entrypoint.join(','),
},
{
ParameterKey: 'WorkingDirectory',
ParameterValue: workingdir,
},
{
ParameterKey: 'EFSMountDirectory',
ParameterValue: mountdir,
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
...mappedSecrets,
],
}).promise();
core.info('Creating worker cluster...');
await CF.createStack({
StackName: cleanupTaskDefStackName,
TemplateBody: cleanupCloudFormation,
Capabilities: ['CAPABILITY_IAM'],
Parameters: [
{
ParameterKey: 'StackName',
ParameterValue: taskDefStackName,
},
{
ParameterKey: 'DeleteStackName',
ParameterValue: cleanupTaskDefStackName,
},
{
ParameterKey: 'TTL',
ParameterValue: '100',
},
{
ParameterKey: 'BUILDID',
ParameterValue: buildUid,
},
],
}).promise();
core.info('Creating cleanup cluster...');
await CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise(); await CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise();
} catch (error) { } catch (error) {
core.error(error); await AWSBuildEnvironment.handleStackCreationFailure(error, CF, taskDefStackName, taskDefCloudFormation);
const events = (await CF.describeStackEvents({ StackName: taskDefStackName }).promise()).StackEvents;
const resources = (await CF.describeStackResources({ StackName: taskDefStackName }).promise()).StackResources;
core.info(taskDefCloudFormation);
core.info(JSON.stringify(events, undefined, 4));
core.info(JSON.stringify(resources, undefined, 4));
throw error; throw error;
} }
@ -207,6 +200,22 @@ class AWSBuildEnvironment {
}; };
} }
private static async handleStackCreationFailure(
error: any,
CF: SDK.CloudFormation,
taskDefStackName: string,
taskDefCloudFormation: string,
) {
core.error(error);
const events = (await CF.describeStackEvents({ StackName: taskDefStackName }).promise()).StackEvents;
const resources = (await CF.describeStackResources({ StackName: taskDefStackName }).promise()).StackResources;
core.info(taskDefCloudFormation);
core.info(JSON.stringify(events, undefined, 4));
core.info(JSON.stringify(resources, undefined, 4));
}
static readTaskCloudFormationTemplate(): string { static readTaskCloudFormationTemplate(): string {
return fs.readFileSync(`${__dirname}/cloud-formations/task-def-formation.yml`, 'utf8'); return fs.readFileSync(`${__dirname}/cloud-formations/task-def-formation.yml`, 'utf8');
} }

View File

@ -8,7 +8,7 @@ const efsDirectoryName = 'data';
const cacheDirectoryName = 'cache'; const cacheDirectoryName = 'cache';
class RemoteBuilder { class RemoteBuilder {
static async runBuildJob(buildParameters: BuildParameters, baseImage) { static async build(buildParameters: BuildParameters, baseImage) {
try { try {
const nanoid = customAlphabet(RemoteBuilderAlphabet.alphabet, 4); const nanoid = customAlphabet(RemoteBuilderAlphabet.alphabet, 4);
const buildUid = `${process.env.GITHUB_RUN_NUMBER}-${buildParameters.platform const buildUid = `${process.env.GITHUB_RUN_NUMBER}-${buildParameters.platform