mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-06-11 00:13:56 -07:00
f77696efae
* Correct aws logs link * Correct aws logs link * better aws cli commands and better cleanup for aws * better aws cli commands and better cleanup for aws * improved garbage collection cli options * Only allow ephemeral runners when using cloud runner integration tests flag to avoid unexpected hangup * Only allow ephemeral runners when using cloud runner integration tests flag to avoid unexpected hangup * fix issue #393 * Extract follow log stream service * consolidate into one pipeline file * consolidate into one pipeline file
111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import { CoreV1Api, KubeConfig, Log } from '@kubernetes/client-node';
|
|
import { Writable } from 'stream';
|
|
import CloudRunnerLogger from '../../services/cloud-runner-logger';
|
|
import * as core from '@actions/core';
|
|
import { CloudRunnerStatics } from '../../cloud-runner-statics';
|
|
import waitUntil from 'async-wait-until';
|
|
import { FollowLogStreamService } from '../../services/follow-log-stream-service';
|
|
|
|
class KubernetesTaskRunner {
|
|
static async runTask(
|
|
kubeConfig: KubeConfig,
|
|
kubeClient: CoreV1Api,
|
|
jobName: string,
|
|
podName: string,
|
|
containerName: string,
|
|
namespace: string,
|
|
) {
|
|
CloudRunnerLogger.log(`Streaming logs from pod: ${podName} container: ${containerName} namespace: ${namespace}`);
|
|
const stream = new Writable();
|
|
let output = '';
|
|
let didStreamAnyLogs: boolean = false;
|
|
let shouldReadLogs = true;
|
|
let shouldCleanup = true;
|
|
stream._write = (chunk, encoding, next) => {
|
|
didStreamAnyLogs = true;
|
|
let message = chunk.toString().trimRight(`\n`);
|
|
message = `[${CloudRunnerStatics.logPrefix}] ${message}`;
|
|
({ shouldReadLogs, shouldCleanup, output } = FollowLogStreamService.handleIteration(
|
|
message,
|
|
shouldReadLogs,
|
|
shouldCleanup,
|
|
output,
|
|
));
|
|
next();
|
|
};
|
|
const logOptions = {
|
|
follow: true,
|
|
pretty: false,
|
|
previous: false,
|
|
};
|
|
try {
|
|
const resultError = await new Promise((resolve) =>
|
|
new Log(kubeConfig).log(namespace, podName, containerName, stream, resolve, logOptions),
|
|
);
|
|
stream.destroy();
|
|
if (resultError) {
|
|
throw resultError;
|
|
}
|
|
if (!didStreamAnyLogs) {
|
|
core.error('Failed to stream any logs, listing namespace events, check for an error with the container');
|
|
core.error(
|
|
JSON.stringify(
|
|
{
|
|
events: (await kubeClient.listNamespacedEvent(namespace)).body.items
|
|
.filter((x) => {
|
|
return x.involvedObject.name === podName || x.involvedObject.name === jobName;
|
|
})
|
|
.map((x) => {
|
|
return {
|
|
type: x.involvedObject.kind,
|
|
name: x.involvedObject.name,
|
|
message: x.message,
|
|
};
|
|
}),
|
|
},
|
|
undefined,
|
|
4,
|
|
),
|
|
);
|
|
throw new Error(`No logs streamed from k8s`);
|
|
}
|
|
} catch (error) {
|
|
if (stream) {
|
|
stream.destroy();
|
|
}
|
|
throw error;
|
|
}
|
|
CloudRunnerLogger.log('end of log stream');
|
|
|
|
return output;
|
|
}
|
|
|
|
static async watchUntilPodRunning(kubeClient: CoreV1Api, podName: string, namespace: string) {
|
|
let success: boolean = false;
|
|
CloudRunnerLogger.log(`Watching ${podName} ${namespace}`);
|
|
await waitUntil(
|
|
async () => {
|
|
const status = await kubeClient.readNamespacedPodStatus(podName, namespace);
|
|
const phase = status?.body.status?.phase;
|
|
success = phase === 'Running';
|
|
CloudRunnerLogger.log(
|
|
`${status.body.status?.phase} ${status.body.status?.conditions?.[0].reason || ''} ${
|
|
status.body.status?.conditions?.[0].message || ''
|
|
}`,
|
|
);
|
|
if (success || phase !== 'Pending') return true;
|
|
|
|
return false;
|
|
},
|
|
{
|
|
timeout: 2000000,
|
|
intervalBetweenAttempts: 15000,
|
|
},
|
|
);
|
|
|
|
return success;
|
|
}
|
|
}
|
|
|
|
export default KubernetesTaskRunner;
|