Log stream attempt #2

pull/273/head
Frostebite 2021-06-06 03:01:49 +01:00
parent 926e500b89
commit 464e5f0caa
3 changed files with 120 additions and 175 deletions

222
dist/index.js vendored
View File

@ -729,7 +729,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
// @ts-ignore
const k8s = __importStar(__webpack_require__(89679));
const core = __importStar(__webpack_require__(42186));
const base64 = __webpack_require__(85848);
@ -743,11 +742,6 @@ class Kubernetes {
const k8sApi = kc.makeApiClient(k8s.CoreV1Api);
const k8sBatchApi = kc.makeApiClient(k8s.BatchV1Api);
core.info('loaded from default');
// const kubeconfig = new KubeConfig();
// kubeconfig.loadFromString(base64.decode(buildParameters.kubeConfig));
// const backend = new Request({ kubeconfig });
// const kubeClient = new Client(backend);
// await kubeClient.loadSpec();
const buildId = Kubernetes.uuidv4();
const pvcName = `unity-builder-pvc-${buildId}`;
const secretName = `build-credentials-${buildId}`;
@ -1028,12 +1022,12 @@ class Kubernetes {
});
}
static watchBuildJobUntilFinished() {
var _a, _b;
var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function* () {
try {
const pod = yield Kubernetes.watchPodUntilRunningAndRead();
core.info(`Watching build job ${(_a = pod === null || pod === void 0 ? void 0 : pod.metadata) === null || _a === void 0 ? void 0 : _a.name}`);
yield Kubernetes.streamLogs(((_b = pod === null || pod === void 0 ? void 0 : pod.metadata) === null || _b === void 0 ? void 0 : _b.name) || '', this.namespace);
yield Kubernetes.streamLogs(((_b = pod === null || pod === void 0 ? void 0 : pod.metadata) === null || _b === void 0 ? void 0 : _b.name) || '', this.namespace, ((_d = (_c = pod === null || pod === void 0 ? void 0 : pod.status) === null || _c === void 0 ? void 0 : _c.containerStatuses) === null || _d === void 0 ? void 0 : _d[0].name) || '');
}
catch (error) {
core.error('Failed while watching build job');
@ -1041,45 +1035,21 @@ class Kubernetes {
}
});
}
static streamLogs(name, namespace) {
var _a, _b;
static streamLogs(name, namespace, container) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
try {
let running = true;
let mostRecentLogTime = 999;
let mostRecentLine = '';
while (running) {
const pod = yield this.kubeClient.readNamespacedPod(name, namespace);
running = ((_a = pod.body.status) === null || _a === void 0 ? void 0 : _a.phase) === 'Running';
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
core.info('Polling logs...');
let logs;
try {
logs = yield this.kubeClient.readNamespacedPodLog(name, namespace, undefined, undefined, undefined, undefined, undefined, undefined, mostRecentLogTime, undefined, true);
}
catch (error) {
core.info(error);
if (error.message === 'HTTP request failed') {
core.info('!warning - K8S HTTP FAILED');
continue;
}
}
const arrayOfLines = (_b = logs === null || logs === void 0 ? void 0 : logs.body.match(/[^\n\r]+/g)) === null || _b === void 0 ? void 0 : _b.reverse();
if (arrayOfLines) {
for (const element of arrayOfLines) {
const [time, ...line] = element.split(' ');
const lineString = line.join(' ');
const lineDate = Date.parse(time);
if (mostRecentLine !== lineString || lineDate > mostRecentLogTime) {
core.info(lineString);
mostRecentLogTime = lineDate;
mostRecentLine = lineString;
}
else {
break;
}
}
}
const logs = yield this.kubeClient.readNamespacedPodLog(name, namespace, container, true, undefined, undefined, undefined, undefined, undefined, undefined, true);
logs.response.on('data', (data) => {
core.info('LOGS RECEIVED');
core.info(data);
});
}
}
catch (error) {
@ -1745,60 +1715,60 @@ class RemoteBuilder {
core.info('Starting step 1/4 clone and restore cache)');
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'alpine/git', [
'-c',
`apk update;
apk add unzip;
apk add git-lfs;
apk add jq;
# Get source repo for project to be built and game-ci repo for utilties
git clone https://${buildParameters.githubToken}@github.com/${process.env.GITHUB_REPOSITORY}.git ${buildUid}/${repositoryDirectoryName} -q
git clone https://${buildParameters.githubToken}@github.com/game-ci/unity-builder.git ${buildUid}/builder -q
git clone https://${buildParameters.githubToken}@github.com/game-ci/steam-deploy.git ${buildUid}/steam -q
cd /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/
git checkout $GITHUB_SHA
cd /${efsDirectoryName}/
# Look for usable cache
if [ ! -d ${cacheDirectoryName} ]; then
mkdir ${cacheDirectoryName}
fi
cd ${cacheDirectoryName}
if [ ! -d "${branchName}" ]; then
mkdir "${branchName}"
fi
cd "${branchName}"
echo ''
echo "Cached Libraries for ${branchName} from previous builds:"
ls
echo ''
ls "/${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}"
libDir="/${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}/Library"
if [ -d "$libDir" ]; then
rm -r "$libDir"
echo "Setup .gitignore to ignore Library folder and remove it from builds"
fi
echo 'Checking cache'
# Restore cache
latest=$(ls -t | head -1)
if [ ! -z "$latest" ]; then
echo "Library cache exists from build $latest from ${branchName}"
echo 'Creating empty Library folder for cache'
mkdir $libDir
unzip -q $latest -d $libDir
# purge cache
${process.env.PURGE_REMOTE_BUILDER_CACHE === undefined ? '#' : ''} rm -r $libDir
else
echo 'Cache does not exist'
fi
# Print out important directories
echo ''
echo 'Repo:'
ls /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/
echo ''
echo 'Project:'
ls /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}
echo ''
echo 'Library:'
ls /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}/Library/
echo ''
`apk update;
apk add unzip;
apk add git-lfs;
apk add jq;
# Get source repo for project to be built and game-ci repo for utilties
git clone https://${buildParameters.githubToken}@github.com/${process.env.GITHUB_REPOSITORY}.git ${buildUid}/${repositoryDirectoryName} -q
git clone https://${buildParameters.githubToken}@github.com/game-ci/unity-builder.git ${buildUid}/builder -q
git clone https://${buildParameters.githubToken}@github.com/game-ci/steam-deploy.git ${buildUid}/steam -q
cd /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/
git checkout $GITHUB_SHA
cd /${efsDirectoryName}/
# Look for usable cache
if [ ! -d ${cacheDirectoryName} ]; then
mkdir ${cacheDirectoryName}
fi
cd ${cacheDirectoryName}
if [ ! -d "${branchName}" ]; then
mkdir "${branchName}"
fi
cd "${branchName}"
echo ''
echo "Cached Libraries for ${branchName} from previous builds:"
ls
echo ''
ls "/${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}"
libDir="/${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}/Library"
if [ -d "$libDir" ]; then
rm -r "$libDir"
echo "Setup .gitignore to ignore Library folder and remove it from builds"
fi
echo 'Checking cache'
# Restore cache
latest=$(ls -t | head -1)
if [ ! -z "$latest" ]; then
echo "Library cache exists from build $latest from ${branchName}"
echo 'Creating empty Library folder for cache'
mkdir $libDir
unzip -q $latest -d $libDir
# purge cache
${process.env.PURGE_REMOTE_BUILDER_CACHE === undefined ? '#' : ''} rm -r $libDir
else
echo 'Cache does not exist'
fi
# Print out important directories
echo ''
echo 'Repo:'
ls /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/
echo ''
echo 'Project:'
ls /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}
echo ''
echo 'Library:'
ls /${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}/Library/
echo ''
`,
], `/${efsDirectoryName}`, `/${efsDirectoryName}/`, [
{
@ -1857,13 +1827,13 @@ class RemoteBuilder {
core.info('Starting part 2/4 (build unity project)');
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, baseImage.toString(), [
'-c',
`
cp -r /${efsDirectoryName}/${buildUid}/builder/dist/default-build-script/ /UnityBuilderAction;
cp -r /${efsDirectoryName}/${buildUid}/builder/dist/entrypoint.sh /entrypoint.sh;
cp -r /${efsDirectoryName}/${buildUid}/builder/dist/steps/ /steps;
chmod -R +x /entrypoint.sh;
chmod -R +x /steps;
/entrypoint.sh;
`
cp -r /${efsDirectoryName}/${buildUid}/builder/dist/default-build-script/ /UnityBuilderAction;
cp -r /${efsDirectoryName}/${buildUid}/builder/dist/entrypoint.sh /entrypoint.sh;
cp -r /${efsDirectoryName}/${buildUid}/builder/dist/steps/ /steps;
chmod -R +x /entrypoint.sh;
chmod -R +x /steps;
/entrypoint.sh;
`,
], `/${efsDirectoryName}`, `/${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/`, [
{
@ -1927,18 +1897,18 @@ class RemoteBuilder {
// Cleanup
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'alpine', [
'-c',
`
apk update
apk add zip
cd Library
zip -r lib-${buildUid}.zip .*
mv lib-${buildUid}.zip /${efsDirectoryName}/${cacheDirectoryName}/${branchName}/lib-${buildUid}.zip
cd ../../
ls
echo ' '
ls ${buildParameters.buildPath}
zip -r build-${buildUid}.zip ${buildParameters.buildPath}/*
mv build-${buildUid}.zip /${efsDirectoryName}/${buildUid}/build-${buildUid}.zip
`
apk update
apk add zip
cd Library
zip -r lib-${buildUid}.zip .*
mv lib-${buildUid}.zip /${efsDirectoryName}/${cacheDirectoryName}/${branchName}/lib-${buildUid}.zip
cd ../../
ls
echo ' '
ls ${buildParameters.buildPath}
zip -r build-${buildUid}.zip ${buildParameters.buildPath}/*
mv build-${buildUid}.zip /${efsDirectoryName}/${buildUid}/build-${buildUid}.zip
`,
], `/${efsDirectoryName}`, `/${efsDirectoryName}/${buildUid}/${repositoryDirectoryName}/${buildParameters.projectPath}`, [
{
@ -1954,11 +1924,11 @@ class RemoteBuilder {
core.info('Starting step 4/4 upload build to s3');
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'amazon/aws-cli', [
'-c',
`
aws s3 cp ${buildUid}/build-${buildUid}.zip s3://game-ci-storage/
# no need to upload Library cache for now
# aws s3 cp /${efsDirectoryName}/${cacheDirectoryName}/${branchName}/lib-${buildUid}.zip s3://game-ci-storage/
${this.SteamDeploy ? '#' : ''} rm -r ${buildUid}
`
aws s3 cp ${buildUid}/build-${buildUid}.zip s3://game-ci-storage/
# no need to upload Library cache for now
# aws s3 cp /${efsDirectoryName}/${cacheDirectoryName}/${branchName}/lib-${buildUid}.zip s3://game-ci-storage/
${this.SteamDeploy ? '#' : ''} rm -r ${buildUid}
`,
], `/${efsDirectoryName}`, `/${efsDirectoryName}/`, [
{
@ -1989,15 +1959,15 @@ class RemoteBuilder {
core.info('Starting steam deployment');
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'cm2network/steamcmd:root', [
'-c',
`
ls
ls /
cp -r /${efsDirectoryName}/${buildUid}/steam/action/entrypoint.sh /entrypoint.sh;
cp -r /${efsDirectoryName}/${buildUid}/steam/action/steps/ /steps;
chmod -R +x /entrypoint.sh;
chmod -R +x /steps;
/entrypoint.sh;
rm -r /${efsDirectoryName}/${buildUid}
`
ls
ls /
cp -r /${efsDirectoryName}/${buildUid}/steam/action/entrypoint.sh /entrypoint.sh;
cp -r /${efsDirectoryName}/${buildUid}/steam/action/steps/ /steps;
chmod -R +x /entrypoint.sh;
chmod -R +x /steps;
/entrypoint.sh;
rm -r /${efsDirectoryName}/${buildUid}
`,
], `/${efsDirectoryName}`, `/${efsDirectoryName}/${buildUid}/steam/action/`, [
{

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,3 @@
// @ts-ignore
import * as k8s from '@kubernetes/client-node';
import { BuildParameters } from '.';
import * as core from '@actions/core';
@ -25,12 +24,6 @@ class Kubernetes {
const k8sBatchApi = kc.makeApiClient(k8s.BatchV1Api);
core.info('loaded from default');
// const kubeconfig = new KubeConfig();
// kubeconfig.loadFromString(base64.decode(buildParameters.kubeConfig));
// const backend = new Request({ kubeconfig });
// const kubeClient = new Client(backend);
// await kubeClient.loadSpec();
const buildId = Kubernetes.uuidv4();
const pvcName = `unity-builder-pvc-${buildId}`;
const secretName = `build-credentials-${buildId}`;
@ -317,60 +310,42 @@ class Kubernetes {
try {
const pod = await Kubernetes.watchPodUntilRunningAndRead();
core.info(`Watching build job ${pod?.metadata?.name}`);
await Kubernetes.streamLogs(pod?.metadata?.name || '', this.namespace);
await Kubernetes.streamLogs(
pod?.metadata?.name || '',
this.namespace,
pod?.status?.containerStatuses?.[0].name || '',
);
} catch (error) {
core.error('Failed while watching build job');
throw error;
}
}
static async streamLogs(name: string, namespace: string) {
static async streamLogs(name: string, namespace: string, container: string) {
try {
let running = true;
let mostRecentLogTime: number = 999;
let mostRecentLine: string = '';
while (running) {
const pod = await this.kubeClient.readNamespacedPod(name, namespace);
running = pod.body.status?.phase === 'Running';
await new Promise((resolve) => setTimeout(resolve, pollInterval));
core.info('Polling logs...');
let logs;
try {
logs = await this.kubeClient.readNamespacedPodLog(
name,
namespace,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
mostRecentLogTime,
undefined,
true,
);
} catch (error) {
core.info(error);
if (error.message === 'HTTP request failed') {
core.info('!warning - K8S HTTP FAILED');
continue;
}
}
const arrayOfLines = logs?.body.match(/[^\n\r]+/g)?.reverse();
if (arrayOfLines) {
for (const element of arrayOfLines) {
const [time, ...line] = element.split(' ');
const lineString: string = line.join(' ');
const lineDate: number = Date.parse(time);
if (mostRecentLine !== lineString || lineDate > mostRecentLogTime) {
core.info(lineString);
mostRecentLogTime = lineDate;
mostRecentLine = lineString;
} else {
break;
}
}
}
const logs = await this.kubeClient.readNamespacedPodLog(
name,
namespace,
container,
true,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
true,
);
logs.response.on('data', (data) => {
core.info('LOGS RECEIVED');
core.info(data);
});
}
} catch (error) {
core.error(JSON.stringify(error, undefined, 4));