Logging cleanup

pull/310/head
Frostebite 2021-09-21 19:27:04 +01:00
parent 9712dddf10
commit e802849d30
10 changed files with 206 additions and 214 deletions

252
dist/index.js vendored
View File

@ -355,6 +355,7 @@ const fs = __importStar(__webpack_require__(35747));
const core = __importStar(__webpack_require__(42186));
const cloud_runner_constants_1 = __importDefault(__webpack_require__(28394));
const aws_build_runner_1 = __importDefault(__webpack_require__(83230));
const cloud_runner_logger_1 = __importDefault(__webpack_require__(49899));
const crypto = __webpack_require__(33373);
class AWSBuildEnvironment {
constructor(buildParameters) {
@ -388,16 +389,16 @@ class AWSBuildEnvironment {
let t2;
try {
const t1 = Date.now();
core.info(`Setup job time: ${Math.floor((t1 - t0) / 1000)}s`);
cloud_runner_logger_1.default.log(`Setup job time: ${Math.floor((t1 - t0) / 1000)}s`);
yield aws_build_runner_1.default.runTask(taskDef, ECS, CF, environment, buildId, commands);
t2 = Date.now();
core.info(`Run job time: ${Math.floor((t2 - t1) / 1000)}s`);
cloud_runner_logger_1.default.log(`Run job time: ${Math.floor((t2 - t1) / 1000)}s`);
}
finally {
yield this.cleanupResources(CF, taskDef);
const t3 = Date.now();
if (t2 !== undefined)
core.info(`Cleanup job time: ${Math.floor((t3 - t2) / 1000)}s`);
cloud_runner_logger_1.default.log(`Cleanup job time: ${Math.floor((t3 - t2) / 1000)}s`);
}
});
}
@ -495,7 +496,7 @@ class AWSBuildEnvironment {
...secretsMappedToCloudFormationParameters,
],
}).promise();
core.info('Creating cloud runner job');
cloud_runner_logger_1.default.log('Creating cloud runner job');
yield CF.createStack({
StackName: cleanupTaskDefStackName,
TemplateBody: cleanupCloudFormation,
@ -523,7 +524,7 @@ class AWSBuildEnvironment {
},
],
}).promise();
// Side effect: core.info('Creating cleanup double checker cron job...');
// Side effect: CloudRunnerLogger.log('Creating cleanup double checker cron job...');
yield CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise();
}
catch (error) {
@ -586,9 +587,9 @@ class AWSBuildEnvironment {
});
try {
if (!stackExists) {
core.info(`${baseStackName} stack does not exist (${JSON.stringify(stacks)})`);
cloud_runner_logger_1.default.log(`${baseStackName} stack does not exist (${JSON.stringify(stacks)})`);
yield CF.createStack(createStackInput).promise();
core.info(`created stack (version: ${hash})`);
cloud_runner_logger_1.default.log(`created stack (version: ${hash})`);
}
const CFState = yield describeStack();
let stack = (_b = CFState.Stacks) === null || _b === void 0 ? void 0 : _b[0];
@ -600,13 +601,13 @@ class AWSBuildEnvironment {
yield CF.waitFor('stackCreateComplete', describeStackInput).promise();
}
if (stackExists) {
core.info(`Base stack exists (version: ${stackVersion}, local version: ${hash})`);
cloud_runner_logger_1.default.log(`Base stack exists (version: ${stackVersion}, local version: ${hash})`);
if (hash !== stackVersion) {
core.info(`Updating`);
cloud_runner_logger_1.default.log(`Updating`);
yield CF.updateStack(updateInput).promise();
}
else {
core.info(`No update required`);
cloud_runner_logger_1.default.log(`No update required`);
}
stack = (_e = (yield describeStack()).Stacks) === null || _e === void 0 ? void 0 : _e[0];
if (!stack) {
@ -616,7 +617,7 @@ class AWSBuildEnvironment {
yield CF.waitFor('stackUpdateComplete', describeStackInput).promise();
}
}
core.info('base stack is ready');
cloud_runner_logger_1.default.log('base stack is ready');
}
catch (error) {
core.error(JSON.stringify(yield describeStack(), undefined, 4));
@ -626,14 +627,14 @@ class AWSBuildEnvironment {
}
handleStackCreationFailure(error, CF, taskDefStackName, taskDefCloudFormation, secrets) {
return __awaiter(this, void 0, void 0, function* () {
core.info(JSON.stringify(secrets, undefined, 4));
core.info(taskDefCloudFormation);
cloud_runner_logger_1.default.log(JSON.stringify(secrets, undefined, 4));
cloud_runner_logger_1.default.log(taskDefCloudFormation);
core.error(error);
core.info('Getting events and resources for task stack');
cloud_runner_logger_1.default.log('Getting events and resources for task stack');
const events = (yield CF.describeStackEvents({ StackName: taskDefStackName }).promise()).StackEvents;
const resources = (yield CF.describeStackResources({ StackName: taskDefStackName }).promise()).StackResources;
core.info(JSON.stringify(events, undefined, 4));
core.info(JSON.stringify(resources, undefined, 4));
cloud_runner_logger_1.default.log(JSON.stringify(events, undefined, 4));
cloud_runner_logger_1.default.log(JSON.stringify(resources, undefined, 4));
});
}
readTaskCloudFormationTemplate() {
@ -642,7 +643,7 @@ class AWSBuildEnvironment {
cleanupResources(CF, taskDef) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
core.info('Cleanup starting');
cloud_runner_logger_1.default.log('Cleanup starting');
yield CF.deleteStack({
StackName: taskDef.taskDefStackName,
}).promise();
@ -656,9 +657,9 @@ class AWSBuildEnvironment {
StackName: taskDef.taskDefStackNameTTL,
}).promise();
const stacks = (_a = (yield CF.listStacks().promise()).StackSummaries) === null || _a === void 0 ? void 0 : _a.filter((x) => x.StackStatus !== 'DELETE_COMPLETE');
core.info(`Deleted Stacks: ${taskDef.taskDefStackName}, ${taskDef.taskDefStackNameTTL}`);
core.info(`Stacks: ${JSON.stringify(stacks, undefined, 4)}`);
core.info('Cleanup complete');
cloud_runner_logger_1.default.log(`Deleted Stacks: ${taskDef.taskDefStackName}, ${taskDef.taskDefStackNameTTL}`);
cloud_runner_logger_1.default.log(`Stacks: ${JSON.stringify(stacks, undefined, 4)}`);
cloud_runner_logger_1.default.log('Cleanup complete');
});
}
}
@ -700,10 +701,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const AWS = __importStar(__webpack_require__(71786));
const core = __importStar(__webpack_require__(42186));
const zlib = __importStar(__webpack_require__(78761));
const cloud_runner_logger_1 = __importDefault(__webpack_require__(49899));
class AWSBuildRunner {
static runTask(taskDef, ECS, CF, environment, buildGuid, commands) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
@ -736,7 +741,7 @@ class AWSBuildRunner {
},
},
}).promise();
core.info('Cloud runner job is starting');
cloud_runner_logger_1.default.log('Cloud runner job is starting');
const taskArn = ((_o = task.tasks) === null || _o === void 0 ? void 0 : _o[0].taskArn) || '';
try {
yield ECS.waitFor('tasksRunning', { tasks: [taskArn], cluster }).promise();
@ -744,20 +749,20 @@ class AWSBuildRunner {
catch (error_) {
const error = error_;
yield new Promise((resolve) => setTimeout(resolve, 3000));
core.info(`Cloud runner job has ended ${(_p = (yield AWSBuildRunner.describeTasks(ECS, cluster, taskArn)).containers) === null || _p === void 0 ? void 0 : _p[0].lastStatus}`);
cloud_runner_logger_1.default.log(`Cloud runner job has ended ${(_p = (yield AWSBuildRunner.describeTasks(ECS, cluster, taskArn)).containers) === null || _p === void 0 ? void 0 : _p[0].lastStatus}`);
core.setFailed(error);
core.error(error);
}
core.info(`Cloud runner job is running`);
cloud_runner_logger_1.default.log(`Cloud runner job is running`);
yield this.streamLogsUntilTaskStops(ECS, CF, taskDef, cluster, taskArn, streamName);
const exitCode = (_q = (yield AWSBuildRunner.describeTasks(ECS, cluster, taskArn)).containers) === null || _q === void 0 ? void 0 : _q[0].exitCode;
core.info(`Cloud runner job exit code ${exitCode}`);
cloud_runner_logger_1.default.log(`Cloud runner job exit code ${exitCode}`);
if (exitCode !== 0) {
core.error(`job failed with exit code ${exitCode} ${JSON.stringify(yield ECS.describeTasks({ tasks: [taskArn], cluster }).promise(), undefined, 4)}`);
throw new Error(`job failed with exit code ${exitCode}`);
}
else {
core.info(`Cloud runner job has finished successfully`);
cloud_runner_logger_1.default.log(`Cloud runner job has finished successfully`);
}
});
}
@ -782,9 +787,9 @@ class AWSBuildRunner {
const kinesis = new AWS.Kinesis();
const stream = yield AWSBuildRunner.getLogStream(kinesis, kinesisStreamName);
let iterator = yield AWSBuildRunner.getLogIterator(kinesis, stream);
core.info(`Cloud runner job status is ${(_a = (yield AWSBuildRunner.describeTasks(ECS, clusterName, taskArn))) === null || _a === void 0 ? void 0 : _a.lastStatus}`);
cloud_runner_logger_1.default.log(`Cloud runner job status is ${(_a = (yield AWSBuildRunner.describeTasks(ECS, clusterName, taskArn))) === null || _a === void 0 ? void 0 : _a.lastStatus}`);
const logBaseUrl = `https://${AWS.config.region}.console.aws.amazon.com/cloudwatch/home?region=${AWS.config.region}#logsV2:log-groups/log-group/${taskDef.taskDefStackName}`;
core.info(`You can also see the logs at AWS Cloud Watch: ${logBaseUrl}`);
cloud_runner_logger_1.default.log(`You can also see the logs at AWS Cloud Watch: ${logBaseUrl}`);
let readingLogs = true;
let timestamp = 0;
while (readingLogs) {
@ -810,14 +815,14 @@ class AWSBuildRunner {
static checkStreamingShouldContinue(taskData, timestamp, readingLogs) {
if ((taskData === null || taskData === void 0 ? void 0 : taskData.lastStatus) !== 'RUNNING') {
if (timestamp === 0) {
core.info('Cloud runner job stopped, streaming end of logs');
cloud_runner_logger_1.default.log('Cloud runner job stopped, streaming end of logs');
timestamp = Date.now();
}
if (timestamp !== 0 && Date.now() - timestamp < 30000) {
core.info('Cloud runner status is not RUNNING for 30 seconds, last query for logs');
cloud_runner_logger_1.default.log('Cloud runner status is not RUNNING for 30 seconds, last query for logs');
readingLogs = false;
}
core.info(`Status of job: ${taskData.lastStatus}`);
cloud_runner_logger_1.default.log(`Status of job: ${taskData.lastStatus}`);
}
return { timestamp, readingLogs };
}
@ -828,7 +833,7 @@ class AWSBuildRunner {
if (json.messageType === 'DATA_MESSAGE') {
for (let logEventsIndex = 0; logEventsIndex < json.logEvents.length; logEventsIndex++) {
if (json.logEvents[logEventsIndex].message.includes(taskDef.logid)) {
core.info('End of cloud runner job logs');
cloud_runner_logger_1.default.log('End of cloud runner job logs');
readingLogs = false;
}
else {
@ -836,7 +841,7 @@ class AWSBuildRunner {
if (message.includes('Rebuilding Library because the asset database could not be found!')) {
core.warning('LIBRARY NOT FOUND!');
}
core.info(message);
cloud_runner_logger_1.default.log(message);
}
}
}
@ -884,29 +889,7 @@ exports.default = CloudRunnerConstants;
/***/ }),
/***/ 93487:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const nanoid_1 = __webpack_require__(39140);
const cloud_runner_constants_1 = __importDefault(__webpack_require__(28394));
class CloudRunnerNamespace {
static generateBuildName(runNumber, platform) {
const nanoid = nanoid_1.customAlphabet(cloud_runner_constants_1.default.alphabet, 4);
return `${runNumber}-${platform.toLowerCase().replace('standalone', '')}-${nanoid()}`;
}
}
exports.default = CloudRunnerNamespace;
/***/ }),
/***/ 1669:
/***/ 49899:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
@ -932,11 +915,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const core = __importStar(__webpack_require__(42186));
class CloudRunnerTimerLogger {
class CloudRunnerLogger {
static setup() {
this.timestamp = this.createTimestamp();
this.globalTimestamp = this.timestamp;
}
static log(message) {
core.info(message);
}
static error(message) {
core.error(message);
}
static logWithTime(message) {
const newTimestamp = this.createTimestamp();
core.info(`${message} (Since previous: ${this.calculateTimeDiff(newTimestamp, this.timestamp)}, Total time: ${this.calculateTimeDiff(newTimestamp, this.globalTimestamp)})`);
@ -949,7 +938,29 @@ class CloudRunnerTimerLogger {
return Date.now();
}
}
exports.default = CloudRunnerTimerLogger;
exports.default = CloudRunnerLogger;
/***/ }),
/***/ 93487:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const nanoid_1 = __webpack_require__(39140);
const cloud_runner_constants_1 = __importDefault(__webpack_require__(28394));
class CloudRunnerNamespace {
static generateBuildName(runNumber, platform) {
const nanoid = nanoid_1.customAlphabet(cloud_runner_constants_1.default.alphabet, 4);
return `${runNumber}-${platform.toLowerCase().replace('standalone', '')}-${nanoid()}`;
}
}
exports.default = CloudRunnerNamespace;
/***/ }),
@ -997,13 +1008,13 @@ const cloud_runner_namespace_1 = __importDefault(__webpack_require__(93487));
const kubernetes_build_platform_1 = __importDefault(__webpack_require__(75944));
const image_environment_factory_1 = __importDefault(__webpack_require__(25145));
const yaml_1 = __importDefault(__webpack_require__(13552));
const cloud_runner_timer_logger_1 = __importDefault(__webpack_require__(1669));
const cloud_runner_logger_1 = __importDefault(__webpack_require__(49899));
const repositoryFolder = 'repo';
const buildVolumeFolder = 'data';
const cacheFolder = 'cache';
class CloudRunner {
static setup(buildParameters) {
cloud_runner_timer_logger_1.default.setup();
cloud_runner_logger_1.default.setup();
CloudRunner.buildGuid = cloud_runner_namespace_1.default.generateBuildName(CloudRunner.readRunNumber(), buildParameters.platform);
CloudRunner.buildParams = buildParameters;
CloudRunner.setupBranchName();
@ -1057,12 +1068,12 @@ class CloudRunner {
static setupBuildPlatform() {
switch (this.buildParams.cloudRunnerCluster) {
case 'aws':
core.info('Building with AWS');
cloud_runner_logger_1.default.log('Building with AWS');
this.CloudRunnerProviderPlatform = new aws_build_platform_1.default(this.buildParams);
break;
default:
case 'k8s':
core.info('Building with Kubernetes');
cloud_runner_logger_1.default.log('Building with Kubernetes');
this.CloudRunnerProviderPlatform = new kubernetes_build_platform_1.default(this.buildParams);
break;
}
@ -1193,26 +1204,26 @@ class CloudRunner {
static runMainJob(baseImage) {
return __awaiter(this, void 0, void 0, function* () {
if (this.buildParams.customBuildSteps !== '') {
core.info(`Cloud Runner is running in standard build automation mode`);
cloud_runner_logger_1.default.log(`Cloud Runner is running in standard build automation mode`);
yield CloudRunner.standardBuildAutomation(baseImage);
}
else {
core.info(`Cloud Runner is running in custom job mode`);
cloud_runner_logger_1.default.log(`Cloud Runner is running in custom job mode`);
yield CloudRunner.runCustomJob(this.buildParams.customBuildSteps);
}
});
}
static standardBuildAutomation(baseImage) {
return __awaiter(this, void 0, void 0, function* () {
cloud_runner_timer_logger_1.default.logWithTime('Pre build steps time');
cloud_runner_logger_1.default.logWithTime('Pre build steps time');
yield this.runCustomJob(this.buildParams.preBuildSteps);
cloud_runner_timer_logger_1.default.logWithTime('Setup time');
cloud_runner_logger_1.default.logWithTime('Setup time');
yield CloudRunner.BuildStep(baseImage);
cloud_runner_timer_logger_1.default.logWithTime('Build time');
cloud_runner_logger_1.default.logWithTime('Build time');
yield CloudRunner.CompressionStep();
cloud_runner_timer_logger_1.default.logWithTime('Compression time');
cloud_runner_logger_1.default.logWithTime('Compression time');
yield this.runCustomJob(this.buildParams.postBuildSteps);
cloud_runner_timer_logger_1.default.logWithTime('Post build steps time');
cloud_runner_logger_1.default.logWithTime('Post build steps time');
});
}
static runCustomJob(buildSteps) {
@ -1233,7 +1244,7 @@ class CloudRunner {
}
static setupStep() {
return __awaiter(this, void 0, void 0, function* () {
core.info('Starting step 1/4 clone and restore cache)');
cloud_runner_logger_1.default.log('Starting step 1/4 clone and restore cache)');
yield this.CloudRunnerProviderPlatform.runBuildTask(this.buildGuid, 'alpine/git', [
` printenv
apk update -q
@ -1255,7 +1266,7 @@ class CloudRunner {
}
static BuildStep(baseImage) {
return __awaiter(this, void 0, void 0, function* () {
core.info('Starting part 2/4 (build unity project)');
cloud_runner_logger_1.default.log('Starting part 2/4 (build unity project)');
yield this.CloudRunnerProviderPlatform.runBuildTask(this.buildGuid, baseImage.toString(), [
`
printenv
@ -1274,7 +1285,7 @@ class CloudRunner {
}
static CompressionStep() {
return __awaiter(this, void 0, void 0, function* () {
core.info('Starting step 3/4 build compression');
cloud_runner_logger_1.default.log('Starting step 3/4 build compression');
// Cleanup
yield this.CloudRunnerProviderPlatform.runBuildTask(this.buildGuid, 'alpine', [
`
@ -1304,7 +1315,7 @@ class CloudRunner {
},
],
], this.defaultSecrets);
core.info('compression step complete');
cloud_runner_logger_1.default.log('compression step complete');
});
}
static cleanupSharedBuildResources() {
@ -1314,7 +1325,7 @@ class CloudRunner {
}
static handleException(error) {
return __awaiter(this, void 0, void 0, function* () {
core.error(JSON.stringify(error, undefined, 4));
cloud_runner_logger_1.default.error(JSON.stringify(error, undefined, 4));
core.setFailed('Remote Builder failed');
yield this.CloudRunnerProviderPlatform.cleanupSharedBuildResources(this.buildGuid, this.buildParams, this.branchName, this.defaultSecrets);
});
@ -1377,6 +1388,7 @@ const kubernetes_utils_1 = __importDefault(__webpack_require__(35306));
const async_wait_until_1 = __importDefault(__webpack_require__(41299));
const kubernetes_job_spec_factory_1 = __importDefault(__webpack_require__(24418));
const kubernetes_service_account_1 = __importDefault(__webpack_require__(12871));
const cloud_runner_logger_1 = __importDefault(__webpack_require__(49899));
class Kubernetes {
constructor(buildParameters) {
this.buildGuid = '';
@ -1392,7 +1404,7 @@ class Kubernetes {
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
this.kubeClientBatchBeta = this.kubeConfig.makeApiClient(k8s.BatchV1beta1Api);
core.info('Loaded default Kubernetes configuration for this environment');
cloud_runner_logger_1.default.log('Loaded default Kubernetes configuration for this environment');
this.namespace = 'default';
this.buildParameters = buildParameters;
}
@ -1425,18 +1437,18 @@ class Kubernetes {
yield kubernetes_secret_1.default.createSecret(secrets, this.secretName, this.namespace, this.kubeClient);
const jobSpec = kubernetes_job_spec_factory_1.default.getJobSpec(commands, image, mountdir, workingdir, environment, this.buildGuid, this.buildParameters, this.secretName, this.pvcName, this.jobName, k8s);
//run
core.info('Creating build job');
cloud_runner_logger_1.default.log('Creating build job');
yield this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
core.info('Job created');
cloud_runner_logger_1.default.log('Job created');
this.setPodNameAndContainerName(yield kubernetes_utils_1.default.findPodFromJob(this.kubeClient, this.jobName, this.namespace));
core.info('Watching pod until running');
cloud_runner_logger_1.default.log('Watching pod until running');
yield kubernetes_utils_1.default.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
core.info('Pod running, streaming logs');
yield kubernetes_logging_1.default.streamLogs(this.kubeConfig, this.kubeClient, this.jobName, this.podName, 'main', this.namespace, core.info);
cloud_runner_logger_1.default.log('Pod running, streaming logs');
yield kubernetes_logging_1.default.streamLogs(this.kubeConfig, this.kubeClient, this.jobName, this.podName, 'main', this.namespace, cloud_runner_logger_1.default.log);
yield this.cleanupTaskResources();
}
catch (error) {
core.info('Running job failed');
cloud_runner_logger_1.default.log('Running job failed');
core.error(JSON.stringify(error, undefined, 4));
yield this.cleanupTaskResources();
throw error;
@ -1450,15 +1462,15 @@ class Kubernetes {
}
cleanupTaskResources() {
return __awaiter(this, void 0, void 0, function* () {
core.info('cleaning up');
cloud_runner_logger_1.default.log('cleaning up');
try {
yield this.kubeClientBatch.deleteNamespacedJob(this.jobName, this.namespace);
yield this.kubeClient.deleteNamespacedSecret(this.secretName, this.namespace);
}
catch (error) {
core.info('Failed to cleanup, error:');
cloud_runner_logger_1.default.log('Failed to cleanup, error:');
core.error(JSON.stringify(error, undefined, 4));
core.info('Abandoning cleanup, build error:');
cloud_runner_logger_1.default.log('Abandoning cleanup, build error:');
throw error;
}
try {
@ -1468,7 +1480,7 @@ class Kubernetes {
});
}
catch (_a) {
core.info('failed to read the state of the job while cleaning up?');
cloud_runner_logger_1.default.log('failed to read the state of the job while cleaning up?');
}
});
}
@ -1644,25 +1656,6 @@ exports.default = KubernetesJobSpecFactory;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
@ -1672,14 +1665,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const client_node_1 = __webpack_require__(89679);
const stream_1 = __webpack_require__(92413);
const core = __importStar(__webpack_require__(42186));
const cloud_runner_logger_1 = __importDefault(__webpack_require__(49899));
class KubernetesLogging {
static streamLogs(kubeConfig, kubeClient, jobName, podName, containerName, namespace, logCallback) {
return __awaiter(this, void 0, void 0, function* () {
core.info(`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace}`);
cloud_runner_logger_1.default.log(`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace}`);
const stream = new stream_1.Writable();
let didStreamAnyLogs = false;
stream._write = (chunk, encoding, next) => {
@ -1717,7 +1713,7 @@ class KubernetesLogging {
catch (error) {
throw error;
}
core.info('end of log stream');
cloud_runner_logger_1.default.log('end of log stream');
});
}
}
@ -1890,23 +1886,24 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
const async_wait_until_1 = __importDefault(__webpack_require__(41299));
const core = __importStar(__webpack_require__(42186));
const k8s = __importStar(__webpack_require__(89679));
const cloud_runner_logger_1 = __importDefault(__webpack_require__(49899));
class KubernetesStorage {
static createPersistentVolumeClaim(buildParameters, pvcName, kubeClient, namespace) {
return __awaiter(this, void 0, void 0, function* () {
if (buildParameters.kubeVolume) {
core.info(buildParameters.kubeVolume);
cloud_runner_logger_1.default.log(buildParameters.kubeVolume);
pvcName = buildParameters.kubeVolume;
return;
}
const pvcList = (yield kubeClient.listNamespacedPersistentVolumeClaim(namespace)).body.items.map((x) => { var _a; return (_a = x.metadata) === null || _a === void 0 ? void 0 : _a.name; });
core.info(`Current PVCs in namespace ${namespace}`);
core.info(JSON.stringify(pvcList, undefined, 4));
cloud_runner_logger_1.default.log(`Current PVCs in namespace ${namespace}`);
cloud_runner_logger_1.default.log(JSON.stringify(pvcList, undefined, 4));
if (pvcList.includes(pvcName)) {
core.info(`pvc ${pvcName} already exists`);
cloud_runner_logger_1.default.log(`pvc ${pvcName} already exists`);
core.setOutput('volume', pvcName);
return;
}
core.info(`Creating PVC ${pvcName} (does not exist)`);
cloud_runner_logger_1.default.log(`Creating PVC ${pvcName} (does not exist)`);
const result = yield KubernetesStorage.createPVC(pvcName, buildParameters, kubeClient, namespace);
yield KubernetesStorage.handleResult(result, kubeClient, namespace, pvcName);
});
@ -1927,8 +1924,8 @@ class KubernetesStorage {
static watchUntilPVCNotPending(kubeClient, name, namespace) {
return __awaiter(this, void 0, void 0, function* () {
try {
core.info(`watch Until PVC Not Pending ${name} ${namespace}`);
core.info(`${yield this.getPVCPhase(kubeClient, name, namespace)}`);
cloud_runner_logger_1.default.log(`watch Until PVC Not Pending ${name} ${namespace}`);
cloud_runner_logger_1.default.log(`${yield this.getPVCPhase(kubeClient, name, namespace)}`);
yield async_wait_until_1.default(() => __awaiter(this, void 0, void 0, function* () {
return (yield this.getPVCPhase(kubeClient, name, namespace)) !== 'Pending';
}), {
@ -1972,10 +1969,10 @@ class KubernetesStorage {
const name = (_a = result.body.metadata) === null || _a === void 0 ? void 0 : _a.name;
if (!name)
throw new Error('failed to create PVC');
core.info(JSON.stringify(yield kubeClient.readNamespacedPersistentVolumeClaim(name, namespace), undefined, 4));
core.info(`PVC ${name} created`);
cloud_runner_logger_1.default.log(JSON.stringify(yield kubeClient.readNamespacedPersistentVolumeClaim(name, namespace), undefined, 4));
cloud_runner_logger_1.default.log(`PVC ${name} created`);
yield this.watchUntilPVCNotPending(kubeClient, name, namespace);
core.info(`PVC ${name} is ready and not pending`);
cloud_runner_logger_1.default.log(`PVC ${name} is ready and not pending`);
core.setOutput('volume', pvcName);
});
}
@ -1990,25 +1987,6 @@ exports.default = KubernetesStorage;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
@ -2023,7 +2001,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const async_wait_until_1 = __importDefault(__webpack_require__(41299));
const core = __importStar(__webpack_require__(42186));
const cloud_runner_logger_1 = __importDefault(__webpack_require__(49899));
class KubernetesUtilities {
static findPodFromJob(kubeClient, jobName, namespace) {
return __awaiter(this, void 0, void 0, function* () {
@ -2037,7 +2015,7 @@ class KubernetesUtilities {
static watchUntilPodRunning(kubeClient, podName, namespace) {
return __awaiter(this, void 0, void 0, function* () {
let success = false;
core.info(`Watching ${podName} ${namespace}`);
cloud_runner_logger_1.default.log(`Watching ${podName} ${namespace}`);
yield async_wait_until_1.default(() => __awaiter(this, void 0, void 0, function* () {
var _a, _b;
const phase = (_b = (_a = (yield kubeClient.readNamespacedPodStatus(podName, namespace))) === null || _a === void 0 ? void 0 : _a.body.status) === null || _b === void 0 ? void 0 : _b.phase;

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -9,6 +9,7 @@ import CloudRunnerConstants from './cloud-runner-constants';
import AWSBuildRunner from './aws-build-runner';
import { CloudRunnerProviderInterface } from './cloud-runner-provider-interface';
import BuildParameters from '../build-parameters';
import CloudRunnerLogger from './cloud-runner-logger';
const crypto = require('crypto');
class AWSBuildEnvironment implements CloudRunnerProviderInterface {
@ -65,14 +66,14 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
let t2;
try {
const t1 = Date.now();
core.info(`Setup job time: ${Math.floor((t1 - t0) / 1000)}s`);
CloudRunnerLogger.log(`Setup job time: ${Math.floor((t1 - t0) / 1000)}s`);
await AWSBuildRunner.runTask(taskDef, ECS, CF, environment, buildId, commands);
t2 = Date.now();
core.info(`Run job time: ${Math.floor((t2 - t1) / 1000)}s`);
CloudRunnerLogger.log(`Run job time: ${Math.floor((t2 - t1) / 1000)}s`);
} finally {
await this.cleanupResources(CF, taskDef);
const t3 = Date.now();
if (t2 !== undefined) core.info(`Cleanup job time: ${Math.floor((t3 - t2) / 1000)}s`);
if (t2 !== undefined) CloudRunnerLogger.log(`Cleanup job time: ${Math.floor((t3 - t2) / 1000)}s`);
}
}
@ -196,7 +197,7 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
...secretsMappedToCloudFormationParameters,
],
}).promise();
core.info('Creating cloud runner job');
CloudRunnerLogger.log('Creating cloud runner job');
await CF.createStack({
StackName: cleanupTaskDefStackName,
TemplateBody: cleanupCloudFormation,
@ -224,7 +225,7 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
},
],
}).promise();
// Side effect: core.info('Creating cleanup double checker cron job...');
// Side effect: CloudRunnerLogger.log('Creating cleanup double checker cron job...');
await CF.waitFor('stackCreateComplete', { StackName: taskDefStackName }).promise();
} catch (error) {
@ -296,9 +297,9 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
};
try {
if (!stackExists) {
core.info(`${baseStackName} stack does not exist (${JSON.stringify(stacks)})`);
CloudRunnerLogger.log(`${baseStackName} stack does not exist (${JSON.stringify(stacks)})`);
await CF.createStack(createStackInput).promise();
core.info(`created stack (version: ${hash})`);
CloudRunnerLogger.log(`created stack (version: ${hash})`);
}
const CFState = await describeStack();
let stack = CFState.Stacks?.[0];
@ -312,12 +313,12 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
}
if (stackExists) {
core.info(`Base stack exists (version: ${stackVersion}, local version: ${hash})`);
CloudRunnerLogger.log(`Base stack exists (version: ${stackVersion}, local version: ${hash})`);
if (hash !== stackVersion) {
core.info(`Updating`);
CloudRunnerLogger.log(`Updating`);
await CF.updateStack(updateInput).promise();
} else {
core.info(`No update required`);
CloudRunnerLogger.log(`No update required`);
}
stack = (await describeStack()).Stacks?.[0];
if (!stack) {
@ -329,7 +330,7 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
await CF.waitFor('stackUpdateComplete', describeStackInput).promise();
}
}
core.info('base stack is ready');
CloudRunnerLogger.log('base stack is ready');
} catch (error) {
core.error(JSON.stringify(await describeStack(), undefined, 4));
throw error;
@ -343,14 +344,14 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
taskDefCloudFormation: string,
secrets: CloudRunnerSecret[],
) {
core.info(JSON.stringify(secrets, undefined, 4));
core.info(taskDefCloudFormation);
CloudRunnerLogger.log(JSON.stringify(secrets, undefined, 4));
CloudRunnerLogger.log(taskDefCloudFormation);
core.error(error);
core.info('Getting events and resources for task stack');
CloudRunnerLogger.log('Getting events and resources for task stack');
const events = (await CF.describeStackEvents({ StackName: taskDefStackName }).promise()).StackEvents;
const resources = (await CF.describeStackResources({ StackName: taskDefStackName }).promise()).StackResources;
core.info(JSON.stringify(events, undefined, 4));
core.info(JSON.stringify(resources, undefined, 4));
CloudRunnerLogger.log(JSON.stringify(events, undefined, 4));
CloudRunnerLogger.log(JSON.stringify(resources, undefined, 4));
}
readTaskCloudFormationTemplate(): string {
@ -358,7 +359,7 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
}
async cleanupResources(CF: SDK.CloudFormation, taskDef: CloudRunnerTaskDef) {
core.info('Cleanup starting');
CloudRunnerLogger.log('Cleanup starting');
await CF.deleteStack({
StackName: taskDef.taskDefStackName,
}).promise();
@ -375,10 +376,10 @@ class AWSBuildEnvironment implements CloudRunnerProviderInterface {
const stacks = (await CF.listStacks().promise()).StackSummaries?.filter((x) => x.StackStatus !== 'DELETE_COMPLETE');
core.info(`Deleted Stacks: ${taskDef.taskDefStackName}, ${taskDef.taskDefStackNameTTL}`);
core.info(`Stacks: ${JSON.stringify(stacks, undefined, 4)}`);
CloudRunnerLogger.log(`Deleted Stacks: ${taskDef.taskDefStackName}, ${taskDef.taskDefStackNameTTL}`);
CloudRunnerLogger.log(`Stacks: ${JSON.stringify(stacks, undefined, 4)}`);
core.info('Cleanup complete');
CloudRunnerLogger.log('Cleanup complete');
}
}
export default AWSBuildEnvironment;

View File

@ -3,6 +3,7 @@ import CloudRunnerEnvironmentVariable from './cloud-runner-environment-variable'
import * as core from '@actions/core';
import CloudRunnerTaskDef from './cloud-runner-task-def';
import * as zlib from 'zlib';
import CloudRunnerLogger from './cloud-runner-logger';
class AWSBuildRunner {
static async runTask(
@ -48,7 +49,7 @@ class AWSBuildRunner {
},
}).promise();
core.info('Cloud runner job is starting');
CloudRunnerLogger.log('Cloud runner job is starting');
const taskArn = task.tasks?.[0].taskArn || '';
try {
@ -56,7 +57,7 @@ class AWSBuildRunner {
} catch (error_) {
const error = error_ as Error;
await new Promise((resolve) => setTimeout(resolve, 3000));
core.info(
CloudRunnerLogger.log(
`Cloud runner job has ended ${
(await AWSBuildRunner.describeTasks(ECS, cluster, taskArn)).containers?.[0].lastStatus
}`,
@ -65,10 +66,10 @@ class AWSBuildRunner {
core.setFailed(error);
core.error(error);
}
core.info(`Cloud runner job is running`);
CloudRunnerLogger.log(`Cloud runner job is running`);
await this.streamLogsUntilTaskStops(ECS, CF, taskDef, cluster, taskArn, streamName);
const exitCode = (await AWSBuildRunner.describeTasks(ECS, cluster, taskArn)).containers?.[0].exitCode;
core.info(`Cloud runner job exit code ${exitCode}`);
CloudRunnerLogger.log(`Cloud runner job exit code ${exitCode}`);
if (exitCode !== 0) {
core.error(
`job failed with exit code ${exitCode} ${JSON.stringify(
@ -79,7 +80,7 @@ class AWSBuildRunner {
);
throw new Error(`job failed with exit code ${exitCode}`);
} else {
core.info(`Cloud runner job has finished successfully`);
CloudRunnerLogger.log(`Cloud runner job has finished successfully`);
}
}
@ -107,12 +108,12 @@ class AWSBuildRunner {
const stream = await AWSBuildRunner.getLogStream(kinesis, kinesisStreamName);
let iterator = await AWSBuildRunner.getLogIterator(kinesis, stream);
core.info(
CloudRunnerLogger.log(
`Cloud runner job status is ${(await AWSBuildRunner.describeTasks(ECS, clusterName, taskArn))?.lastStatus}`,
);
const logBaseUrl = `https://${AWS.config.region}.console.aws.amazon.com/cloudwatch/home?region=${AWS.config.region}#logsV2:log-groups/log-group/${taskDef.taskDefStackName}`;
core.info(`You can also see the logs at AWS Cloud Watch: ${logBaseUrl}`);
CloudRunnerLogger.log(`You can also see the logs at AWS Cloud Watch: ${logBaseUrl}`);
let readingLogs = true;
let timestamp: number = 0;
while (readingLogs) {
@ -147,14 +148,14 @@ class AWSBuildRunner {
private static checkStreamingShouldContinue(taskData: AWS.ECS.Task, timestamp: number, readingLogs: boolean) {
if (taskData?.lastStatus !== 'RUNNING') {
if (timestamp === 0) {
core.info('Cloud runner job stopped, streaming end of logs');
CloudRunnerLogger.log('Cloud runner job stopped, streaming end of logs');
timestamp = Date.now();
}
if (timestamp !== 0 && Date.now() - timestamp < 30000) {
core.info('Cloud runner status is not RUNNING for 30 seconds, last query for logs');
CloudRunnerLogger.log('Cloud runner status is not RUNNING for 30 seconds, last query for logs');
readingLogs = false;
}
core.info(`Status of job: ${taskData.lastStatus}`);
CloudRunnerLogger.log(`Status of job: ${taskData.lastStatus}`);
}
return { timestamp, readingLogs };
}
@ -168,14 +169,14 @@ class AWSBuildRunner {
if (json.messageType === 'DATA_MESSAGE') {
for (let logEventsIndex = 0; logEventsIndex < json.logEvents.length; logEventsIndex++) {
if (json.logEvents[logEventsIndex].message.includes(taskDef.logid)) {
core.info('End of cloud runner job logs');
CloudRunnerLogger.log('End of cloud runner job logs');
readingLogs = false;
} else {
const message = json.logEvents[logEventsIndex].message;
if (message.includes('Rebuilding Library because the asset database could not be found!')) {
core.warning('LIBRARY NOT FOUND!');
}
core.info(message);
CloudRunnerLogger.log(message);
}
}
}

View File

@ -1,6 +1,6 @@
import * as core from '@actions/core';
class CloudRunnerTimerLogger {
class CloudRunnerLogger {
private static timestamp: number;
private static globalTimestamp: number;
@ -9,6 +9,14 @@ class CloudRunnerTimerLogger {
this.globalTimestamp = this.timestamp;
}
public static log(message: string) {
core.info(message);
}
public static error(message: string) {
core.error(message);
}
public static logWithTime(message: string) {
const newTimestamp = this.createTimestamp();
core.info(
@ -28,4 +36,4 @@ class CloudRunnerTimerLogger {
return Date.now();
}
}
export default CloudRunnerTimerLogger;
export default CloudRunnerLogger;

View File

@ -8,7 +8,7 @@ import Kubernetes from './kubernetes-build-platform';
import CloudRunnerEnvironmentVariable from './cloud-runner-environment-variable';
import ImageEnvironmentFactory from '../image-environment-factory';
import YAML from 'yaml';
import CloudRunnerTimerLogger from './cloud-runner-timer-logger';
import CloudRunnerLogger from './cloud-runner-logger';
const repositoryFolder = 'repo';
const buildVolumeFolder = 'data';
const cacheFolder = 'cache';
@ -39,7 +39,7 @@ class CloudRunner {
];
private static setup(buildParameters: BuildParameters) {
CloudRunnerTimerLogger.setup();
CloudRunnerLogger.setup();
CloudRunner.buildGuid = CloudRunnerNamespace.generateBuildName(
CloudRunner.readRunNumber(),
buildParameters.platform,
@ -103,12 +103,12 @@ class CloudRunner {
private static setupBuildPlatform() {
switch (this.buildParams.cloudRunnerCluster) {
case 'aws':
core.info('Building with AWS');
CloudRunnerLogger.log('Building with AWS');
this.CloudRunnerProviderPlatform = new AWSBuildPlatform(this.buildParams);
break;
default:
case 'k8s':
core.info('Building with Kubernetes');
CloudRunnerLogger.log('Building with Kubernetes');
this.CloudRunnerProviderPlatform = new Kubernetes(this.buildParams);
break;
}
@ -247,24 +247,24 @@ class CloudRunner {
private static async runMainJob(baseImage: any) {
if (this.buildParams.customBuildSteps !== '') {
core.info(`Cloud Runner is running in standard build automation mode`);
CloudRunnerLogger.log(`Cloud Runner is running in standard build automation mode`);
await CloudRunner.standardBuildAutomation(baseImage);
} else {
core.info(`Cloud Runner is running in custom job mode`);
CloudRunnerLogger.log(`Cloud Runner is running in custom job mode`);
await CloudRunner.runCustomJob(this.buildParams.customBuildSteps);
}
}
private static async standardBuildAutomation(baseImage: any) {
CloudRunnerTimerLogger.logWithTime('Pre build steps time');
CloudRunnerLogger.logWithTime('Pre build steps time');
await this.runCustomJob(this.buildParams.preBuildSteps);
CloudRunnerTimerLogger.logWithTime('Setup time');
CloudRunnerLogger.logWithTime('Setup time');
await CloudRunner.BuildStep(baseImage);
CloudRunnerTimerLogger.logWithTime('Build time');
CloudRunnerLogger.logWithTime('Build time');
await CloudRunner.CompressionStep();
CloudRunnerTimerLogger.logWithTime('Compression time');
CloudRunnerLogger.logWithTime('Compression time');
await this.runCustomJob(this.buildParams.postBuildSteps);
CloudRunnerTimerLogger.logWithTime('Post build steps time');
CloudRunnerLogger.logWithTime('Post build steps time');
}
private static async runCustomJob(buildSteps) {
@ -291,7 +291,7 @@ class CloudRunner {
}
private static async setupStep() {
core.info('Starting step 1/4 clone and restore cache)');
CloudRunnerLogger.log('Starting step 1/4 clone and restore cache)');
await this.CloudRunnerProviderPlatform.runBuildTask(
this.buildGuid,
'alpine/git',
@ -320,7 +320,7 @@ class CloudRunner {
}
private static async BuildStep(baseImage: any) {
core.info('Starting part 2/4 (build unity project)');
CloudRunnerLogger.log('Starting part 2/4 (build unity project)');
await this.CloudRunnerProviderPlatform.runBuildTask(
this.buildGuid,
baseImage.toString(),
@ -346,7 +346,7 @@ class CloudRunner {
}
private static async CompressionStep() {
core.info('Starting step 3/4 build compression');
CloudRunnerLogger.log('Starting step 3/4 build compression');
// Cleanup
await this.CloudRunnerProviderPlatform.runBuildTask(
this.buildGuid,
@ -384,7 +384,7 @@ class CloudRunner {
],
this.defaultSecrets,
);
core.info('compression step complete');
CloudRunnerLogger.log('compression step complete');
}
private static async cleanupSharedBuildResources() {
@ -397,7 +397,7 @@ class CloudRunner {
}
private static async handleException(error: unknown) {
core.error(JSON.stringify(error, undefined, 4));
CloudRunnerLogger.error(JSON.stringify(error, undefined, 4));
core.setFailed('Remote Builder failed');
await this.CloudRunnerProviderPlatform.cleanupSharedBuildResources(
this.buildGuid,

View File

@ -11,6 +11,7 @@ import KubernetesUtilities from './kubernetes-utils';
import waitUntil from 'async-wait-until';
import KubernetesJobSpecFactory from './kubernetes-job-spec-factory';
import KubernetesServiceAccount from './kubernetes-service-account';
import CloudRunnerLogger from './cloud-runner-logger';
class Kubernetes implements CloudRunnerProviderInterface {
private kubeConfig: k8s.KubeConfig;
@ -34,7 +35,7 @@ class Kubernetes implements CloudRunnerProviderInterface {
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
this.kubeClientBatchBeta = this.kubeConfig.makeApiClient(k8s.BatchV1beta1Api);
core.info('Loaded default Kubernetes configuration for this environment');
CloudRunnerLogger.log('Loaded default Kubernetes configuration for this environment');
this.namespace = 'default';
this.buildParameters = buildParameters;
@ -95,15 +96,15 @@ class Kubernetes implements CloudRunnerProviderInterface {
);
//run
core.info('Creating build job');
CloudRunnerLogger.log('Creating build job');
await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
core.info('Job created');
CloudRunnerLogger.log('Job created');
this.setPodNameAndContainerName(
await KubernetesUtilities.findPodFromJob(this.kubeClient, this.jobName, this.namespace),
);
core.info('Watching pod until running');
CloudRunnerLogger.log('Watching pod until running');
await KubernetesUtilities.watchUntilPodRunning(this.kubeClient, this.podName, this.namespace);
core.info('Pod running, streaming logs');
CloudRunnerLogger.log('Pod running, streaming logs');
await KubernetesLogging.streamLogs(
this.kubeConfig,
this.kubeClient,
@ -111,11 +112,11 @@ class Kubernetes implements CloudRunnerProviderInterface {
this.podName,
'main',
this.namespace,
core.info,
CloudRunnerLogger.log,
);
await this.cleanupTaskResources();
} catch (error) {
core.info('Running job failed');
CloudRunnerLogger.log('Running job failed');
core.error(JSON.stringify(error, undefined, 4));
await this.cleanupTaskResources();
throw error;
@ -128,14 +129,14 @@ class Kubernetes implements CloudRunnerProviderInterface {
}
async cleanupTaskResources() {
core.info('cleaning up');
CloudRunnerLogger.log('cleaning up');
try {
await this.kubeClientBatch.deleteNamespacedJob(this.jobName, this.namespace);
await this.kubeClient.deleteNamespacedSecret(this.secretName, this.namespace);
} catch (error) {
core.info('Failed to cleanup, error:');
CloudRunnerLogger.log('Failed to cleanup, error:');
core.error(JSON.stringify(error, undefined, 4));
core.info('Abandoning cleanup, build error:');
CloudRunnerLogger.log('Abandoning cleanup, build error:');
throw error;
}
try {
@ -147,7 +148,7 @@ class Kubernetes implements CloudRunnerProviderInterface {
},
);
} catch {
core.info('failed to read the state of the job while cleaning up?');
CloudRunnerLogger.log('failed to read the state of the job while cleaning up?');
}
}

View File

@ -1,6 +1,6 @@
import { CoreV1Api, KubeConfig, Log } from '@kubernetes/client-node';
import { Writable } from 'stream';
import * as core from '@actions/core';
import CloudRunnerLogger from './cloud-runner-logger';
class KubernetesLogging {
static async streamLogs(
@ -12,7 +12,7 @@ class KubernetesLogging {
namespace: string,
logCallback: any,
) {
core.info(`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace}`);
CloudRunnerLogger.log(`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace}`);
const stream = new Writable();
let didStreamAnyLogs: boolean = false;
stream._write = (chunk, encoding, next) => {
@ -57,7 +57,7 @@ class KubernetesLogging {
} catch (error) {
throw error;
}
core.info('end of log stream');
CloudRunnerLogger.log('end of log stream');
}
}

View File

@ -2,6 +2,7 @@ import waitUntil from 'async-wait-until';
import * as core from '@actions/core';
import * as k8s from '@kubernetes/client-node';
import BuildParameters from '../build-parameters';
import CloudRunnerLogger from './cloud-runner-logger';
class KubernetesStorage {
public static async createPersistentVolumeClaim(
@ -11,21 +12,21 @@ class KubernetesStorage {
namespace: string,
) {
if (buildParameters.kubeVolume) {
core.info(buildParameters.kubeVolume);
CloudRunnerLogger.log(buildParameters.kubeVolume);
pvcName = buildParameters.kubeVolume;
return;
}
const pvcList = (await kubeClient.listNamespacedPersistentVolumeClaim(namespace)).body.items.map(
(x) => x.metadata?.name,
);
core.info(`Current PVCs in namespace ${namespace}`);
core.info(JSON.stringify(pvcList, undefined, 4));
CloudRunnerLogger.log(`Current PVCs in namespace ${namespace}`);
CloudRunnerLogger.log(JSON.stringify(pvcList, undefined, 4));
if (pvcList.includes(pvcName)) {
core.info(`pvc ${pvcName} already exists`);
CloudRunnerLogger.log(`pvc ${pvcName} already exists`);
core.setOutput('volume', pvcName);
return;
}
core.info(`Creating PVC ${pvcName} (does not exist)`);
CloudRunnerLogger.log(`Creating PVC ${pvcName} (does not exist)`);
const result = await KubernetesStorage.createPVC(pvcName, buildParameters, kubeClient, namespace);
await KubernetesStorage.handleResult(result, kubeClient, namespace, pvcName);
}
@ -42,8 +43,8 @@ class KubernetesStorage {
public static async watchUntilPVCNotPending(kubeClient: k8s.CoreV1Api, name: string, namespace: string) {
try {
core.info(`watch Until PVC Not Pending ${name} ${namespace}`);
core.info(`${await this.getPVCPhase(kubeClient, name, namespace)}`);
CloudRunnerLogger.log(`watch Until PVC Not Pending ${name} ${namespace}`);
CloudRunnerLogger.log(`${await this.getPVCPhase(kubeClient, name, namespace)}`);
await waitUntil(
async () => {
return (await this.getPVCPhase(kubeClient, name, namespace)) !== 'Pending';
@ -101,10 +102,12 @@ class KubernetesStorage {
) {
const name = result.body.metadata?.name;
if (!name) throw new Error('failed to create PVC');
core.info(JSON.stringify(await kubeClient.readNamespacedPersistentVolumeClaim(name, namespace), undefined, 4));
core.info(`PVC ${name} created`);
CloudRunnerLogger.log(
JSON.stringify(await kubeClient.readNamespacedPersistentVolumeClaim(name, namespace), undefined, 4),
);
CloudRunnerLogger.log(`PVC ${name} created`);
await this.watchUntilPVCNotPending(kubeClient, name, namespace);
core.info(`PVC ${name} is ready and not pending`);
CloudRunnerLogger.log(`PVC ${name} is ready and not pending`);
core.setOutput('volume', pvcName);
}
}

View File

@ -1,6 +1,6 @@
import { CoreV1Api } from '@kubernetes/client-node';
import waitUntil from 'async-wait-until';
import * as core from '@actions/core';
import CloudRunnerLogger from './cloud-runner-logger';
class KubernetesUtilities {
static async findPodFromJob(kubeClient: CoreV1Api, jobName: string, namespace: string) {
@ -15,7 +15,7 @@ class KubernetesUtilities {
static async watchUntilPodRunning(kubeClient: CoreV1Api, podName: string, namespace: string) {
let success: boolean = false;
core.info(`Watching ${podName} ${namespace}`);
CloudRunnerLogger.log(`Watching ${podName} ${namespace}`);
await waitUntil(
async () => {
const phase = (await kubeClient.readNamespacedPodStatus(podName, namespace))?.body.status?.phase;