pull/265/head
Frostebite 2021-05-28 20:27:39 +01:00
parent 6dc4d12ac5
commit 0ae8dc9a20
4 changed files with 127 additions and 164 deletions

141
dist/index.js vendored
View File

@ -50,7 +50,7 @@ function run() {
switch (buildParameters.remoteBuildCluster) { switch (buildParameters.remoteBuildCluster) {
case 'k8s': case 'k8s':
core.info('Building with Kubernetes'); core.info('Building with Kubernetes');
yield model_1.Kubernetes.runBuildJob(buildParameters, baseImage); yield model_1.Kubernetes.run(buildParameters, baseImage);
break; break;
case 'aws': case 'aws':
core.info('Building with AWS'); core.info('Building with AWS');
@ -735,7 +735,7 @@ const core = __importStar(__webpack_require__(42186));
const base64 = __webpack_require__(85848); const base64 = __webpack_require__(85848);
const pollInterval = 10000; const pollInterval = 10000;
class Kubernetes { class Kubernetes {
static runBuildJob(buildParameters, baseImage) { static run(buildParameters, baseImage) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
core.info('Starting up k8s'); core.info('Starting up k8s');
const kc = new k8s.KubeConfig(); const kc = new k8s.KubeConfig();
@ -766,12 +766,8 @@ class Kubernetes {
yield Kubernetes.createSecret(); yield Kubernetes.createSecret();
yield Kubernetes.createPersistentVolumeClaim(); yield Kubernetes.createPersistentVolumeClaim();
// start // start
yield Kubernetes.scheduleBuildJob(); yield Kubernetes.runCloneJob();
// watch yield Kubernetes.runBuildJob();
yield Kubernetes.watchPersistentVolumeClaimUntilReady();
yield Kubernetes.watchBuildJobUntilFinished();
// cleanup
yield Kubernetes.cleanup();
core.setOutput('volume', pvcName); core.setOutput('volume', pvcName);
}); });
} }
@ -820,20 +816,7 @@ class Kubernetes {
core.info('Persistent Volume created, waiting for ready state...'); core.info('Persistent Volume created, waiting for ready state...');
}); });
} }
static watchPersistentVolumeClaimUntilReady() { static runJob(command, image) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
const queryResult = yield this.kubeClient.readNamespacedPersistentVolumeClaim(this.pvcName, this.namespace);
if (((_a = queryResult.body.status) === null || _a === void 0 ? void 0 : _a.phase) === 'Pending') {
yield Kubernetes.watchPersistentVolumeClaimUntilReady();
}
else {
core.info('Persistent Volume ready for claims');
}
});
}
static scheduleBuildJob() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
core.info('Creating build job'); core.info('Creating build job');
const job = new k8s.V1Job(); const job = new k8s.V1Job();
@ -862,62 +845,11 @@ class Kubernetes {
}, },
}, },
], ],
initContainers: [
{
name: 'clone',
image: 'alpine/git',
command: [
'/bin/sh',
'-c',
`apk update;
apk add git-lfs;
export GITHUB_TOKEN=$(cat /credentials/GITHUB_TOKEN);
cd /data;
git clone https://github.com/${process.env.GITHUB_REPOSITORY}.git repo;
git clone https://github.com/webbertakken/unity-builder.git builder;
cd repo;
git checkout $GITHUB_SHA;
ls`,
],
volumeMounts: [
{
name: 'data',
mountPath: '/data',
},
{
name: 'credentials',
mountPath: '/credentials',
readOnly: true,
},
],
env: [
{
name: 'GITHUB_SHA',
value: this.buildId,
},
],
},
],
containers: [ containers: [
{ {
name: 'main', name: 'main',
image: `${this.baseImage.toString()}`, image,
command: [ command: ['bin/bash', '-c', command],
'bin/bash',
'-c',
`ls
for f in ./credentials/*; do export $(basename $f)="$(cat $f)"; done
ls /data
ls /data/builder
ls /data/builder/dist
cp -r /data/builder/dist/default-build-script /UnityBuilderAction
cp -r /data/builder/dist/entrypoint.sh /entrypoint.sh
cp -r /data/builder/dist/steps /steps
chmod -R +x /entrypoint.sh
chmod -R +x /steps
/entrypoint.sh
`,
],
resources: { resources: {
requests: { requests: {
memory: this.buildParameters.remoteBuildMemory, memory: this.buildParameters.remoteBuildMemory,
@ -925,6 +857,10 @@ class Kubernetes {
}, },
}, },
env: [ env: [
{
name: 'GITHUB_SHA',
value: this.buildId,
},
{ {
name: 'GITHUB_WORKSPACE', name: 'GITHUB_WORKSPACE',
value: '/data/repo', value: '/data/repo',
@ -1007,6 +943,53 @@ class Kubernetes {
job.spec.backoffLimit = 1; job.spec.backoffLimit = 1;
yield this.kubeClientBatch.createNamespacedJob(this.namespace, job); yield this.kubeClientBatch.createNamespacedJob(this.namespace, job);
core.info('Job created'); core.info('Job created');
// watch
yield Kubernetes.watchPersistentVolumeClaimUntilReady();
yield Kubernetes.watchBuildJobUntilFinished();
// cleanup
yield Kubernetes.cleanup();
});
}
static runCloneJob() {
return __awaiter(this, void 0, void 0, function* () {
yield Kubernetes.runJob(`apk update;
apk add git-lfs;
export GITHUB_TOKEN=$(cat /credentials/GITHUB_TOKEN);
cd /data;
git clone https://github.com/${process.env.GITHUB_REPOSITORY}.git repo;
git clone https://github.com/webbertakken/unity-builder.git builder;
cd repo;
git checkout $GITHUB_SHA;
ls`, 'alpine/git');
});
}
static runBuildJob() {
return __awaiter(this, void 0, void 0, function* () {
yield this.runJob(`ls
for f in ./credentials/*; do export $(basename $f)="$(cat $f)"; done
ls /data
ls /data/builder
ls /data/builder/dist
cp -r /data/builder/dist/default-build-script /UnityBuilderAction
cp -r /data/builder/dist/entrypoint.sh /entrypoint.sh
cp -r /data/builder/dist/steps /steps
chmod -R +x /entrypoint.sh
chmod -R +x /steps
/entrypoint.sh
`, this.baseImage.toString());
});
}
static watchPersistentVolumeClaimUntilReady() {
var _a;
return __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve) => setTimeout(resolve, pollInterval));
const queryResult = yield this.kubeClient.readNamespacedPersistentVolumeClaim(this.pvcName, this.namespace);
if (((_a = queryResult.body.status) === null || _a === void 0 ? void 0 : _a.phase) === 'Pending') {
yield Kubernetes.watchPersistentVolumeClaimUntilReady();
}
else {
core.info('Persistent Volume ready for claims');
}
}); });
} }
static watchPodUntilReadyAndRead(statusFilter) { static watchPodUntilReadyAndRead(statusFilter) {
@ -1035,12 +1018,12 @@ class Kubernetes {
}); });
} }
static watchBuildJobUntilFinished() { static watchBuildJobUntilFinished() {
var _a, _b, _c, _d; var _a, _b;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
const pod = (yield Kubernetes.watchPodUntilReadyAndRead('Pending')) || {}; const pod = (yield Kubernetes.watchPodUntilReadyAndRead('Pending')) || {};
core.info(`Watching build job ${(_a = pod.metadata) === null || _a === void 0 ? void 0 : _a.name} ${JSON.stringify((_c = (_b = pod.status) === null || _b === void 0 ? void 0 : _b.containerStatuses) === null || _c === void 0 ? void 0 : _c[0].state, undefined, 4)}`); core.info(`Watching build job ${(_a = pod.metadata) === null || _a === void 0 ? void 0 : _a.name}`);
yield Kubernetes.streamLogs(((_d = pod.metadata) === null || _d === void 0 ? void 0 : _d.name) || '', this.namespace); yield Kubernetes.streamLogs(((_b = pod.metadata) === null || _b === void 0 ? void 0 : _b.name) || '', this.namespace);
} }
catch (error) { catch (error) {
core.error('Failed while watching build job'); core.error('Failed while watching build job');
@ -1053,7 +1036,7 @@ class Kubernetes {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
let running = true; let running = true;
let logQueryTime = 0; let logQueryTime = 999;
let mostRecentLine = ''; let mostRecentLine = '';
while (running) { while (running) {
const pod = yield this.kubeClient.readNamespacedPod(name, namespace); const pod = yield this.kubeClient.readNamespacedPod(name, namespace);

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ async function run() {
switch (buildParameters.remoteBuildCluster) { switch (buildParameters.remoteBuildCluster) {
case 'k8s': case 'k8s':
core.info('Building with Kubernetes'); core.info('Building with Kubernetes');
await Kubernetes.runBuildJob(buildParameters, baseImage); await Kubernetes.run(buildParameters, baseImage);
break; break;
case 'aws': case 'aws':

View File

@ -17,7 +17,7 @@ class Kubernetes {
private static jobName: string; private static jobName: string;
private static namespace: string; private static namespace: string;
static async runBuildJob(buildParameters: BuildParameters, baseImage) { static async run(buildParameters: BuildParameters, baseImage) {
core.info('Starting up k8s'); core.info('Starting up k8s');
const kc = new k8s.KubeConfig(); const kc = new k8s.KubeConfig();
kc.loadFromDefault(); kc.loadFromDefault();
@ -52,14 +52,8 @@ class Kubernetes {
await Kubernetes.createPersistentVolumeClaim(); await Kubernetes.createPersistentVolumeClaim();
// start // start
await Kubernetes.scheduleBuildJob(); await Kubernetes.runCloneJob();
await Kubernetes.runBuildJob();
// watch
await Kubernetes.watchPersistentVolumeClaimUntilReady();
await Kubernetes.watchBuildJobUntilFinished();
// cleanup
await Kubernetes.cleanup();
core.setOutput('volume', pvcName); core.setOutput('volume', pvcName);
} }
@ -109,18 +103,7 @@ class Kubernetes {
core.info('Persistent Volume created, waiting for ready state...'); core.info('Persistent Volume created, waiting for ready state...');
} }
static async watchPersistentVolumeClaimUntilReady() { static async runJob(command: string, image: string) {
await new Promise((resolve) => setTimeout(resolve, pollInterval));
const queryResult = await this.kubeClient.readNamespacedPersistentVolumeClaim(this.pvcName, this.namespace);
if (queryResult.body.status?.phase === 'Pending') {
await Kubernetes.watchPersistentVolumeClaimUntilReady();
} else {
core.info('Persistent Volume ready for claims');
}
}
static async scheduleBuildJob() {
core.info('Creating build job'); core.info('Creating build job');
const job = new k8s.V1Job(); const job = new k8s.V1Job();
job.apiVersion = 'batch/v1'; job.apiVersion = 'batch/v1';
@ -148,62 +131,11 @@ class Kubernetes {
}, },
}, },
], ],
initContainers: [
{
name: 'clone',
image: 'alpine/git',
command: [
'/bin/sh',
'-c',
`apk update;
apk add git-lfs;
export GITHUB_TOKEN=$(cat /credentials/GITHUB_TOKEN);
cd /data;
git clone https://github.com/${process.env.GITHUB_REPOSITORY}.git repo;
git clone https://github.com/webbertakken/unity-builder.git builder;
cd repo;
git checkout $GITHUB_SHA;
ls`,
],
volumeMounts: [
{
name: 'data',
mountPath: '/data',
},
{
name: 'credentials',
mountPath: '/credentials',
readOnly: true,
},
],
env: [
{
name: 'GITHUB_SHA',
value: this.buildId,
},
],
},
],
containers: [ containers: [
{ {
name: 'main', name: 'main',
image: `${this.baseImage.toString()}`, image,
command: [ command: ['bin/bash', '-c', command],
'bin/bash',
'-c',
`ls
for f in ./credentials/*; do export $(basename $f)="$(cat $f)"; done
ls /data
ls /data/builder
ls /data/builder/dist
cp -r /data/builder/dist/default-build-script /UnityBuilderAction
cp -r /data/builder/dist/entrypoint.sh /entrypoint.sh
cp -r /data/builder/dist/steps /steps
chmod -R +x /entrypoint.sh
chmod -R +x /steps
/entrypoint.sh
`,
],
resources: { resources: {
requests: { requests: {
memory: this.buildParameters.remoteBuildMemory, memory: this.buildParameters.remoteBuildMemory,
@ -211,6 +143,10 @@ class Kubernetes {
}, },
}, },
env: [ env: [
{
name: 'GITHUB_SHA',
value: this.buildId,
},
{ {
name: 'GITHUB_WORKSPACE', name: 'GITHUB_WORKSPACE',
value: '/data/repo', value: '/data/repo',
@ -293,6 +229,57 @@ class Kubernetes {
job.spec.backoffLimit = 1; job.spec.backoffLimit = 1;
await this.kubeClientBatch.createNamespacedJob(this.namespace, job); await this.kubeClientBatch.createNamespacedJob(this.namespace, job);
core.info('Job created'); core.info('Job created');
// watch
await Kubernetes.watchPersistentVolumeClaimUntilReady();
await Kubernetes.watchBuildJobUntilFinished();
// cleanup
await Kubernetes.cleanup();
}
static async runCloneJob() {
await Kubernetes.runJob(
`apk update;
apk add git-lfs;
export GITHUB_TOKEN=$(cat /credentials/GITHUB_TOKEN);
cd /data;
git clone https://github.com/${process.env.GITHUB_REPOSITORY}.git repo;
git clone https://github.com/webbertakken/unity-builder.git builder;
cd repo;
git checkout $GITHUB_SHA;
ls`,
'alpine/git',
);
}
static async runBuildJob() {
await this.runJob(
`ls
for f in ./credentials/*; do export $(basename $f)="$(cat $f)"; done
ls /data
ls /data/builder
ls /data/builder/dist
cp -r /data/builder/dist/default-build-script /UnityBuilderAction
cp -r /data/builder/dist/entrypoint.sh /entrypoint.sh
cp -r /data/builder/dist/steps /steps
chmod -R +x /entrypoint.sh
chmod -R +x /steps
/entrypoint.sh
`,
this.baseImage.toString(),
);
}
static async watchPersistentVolumeClaimUntilReady() {
await new Promise((resolve) => setTimeout(resolve, pollInterval));
const queryResult = await this.kubeClient.readNamespacedPersistentVolumeClaim(this.pvcName, this.namespace);
if (queryResult.body.status?.phase === 'Pending') {
await Kubernetes.watchPersistentVolumeClaimUntilReady();
} else {
core.info('Persistent Volume ready for claims');
}
} }
static async watchPodUntilReadyAndRead(statusFilter: string) { static async watchPodUntilReadyAndRead(statusFilter: string) {
@ -321,14 +308,7 @@ class Kubernetes {
static async watchBuildJobUntilFinished() { static async watchBuildJobUntilFinished() {
try { try {
const pod = (await Kubernetes.watchPodUntilReadyAndRead('Pending')) || {}; const pod = (await Kubernetes.watchPodUntilReadyAndRead('Pending')) || {};
core.info(`Watching build job ${pod.metadata?.name}`);
core.info(
`Watching build job ${pod.metadata?.name} ${JSON.stringify(
pod.status?.containerStatuses?.[0].state,
undefined,
4,
)}`,
);
await Kubernetes.streamLogs(pod.metadata?.name || '', this.namespace); await Kubernetes.streamLogs(pod.metadata?.name || '', this.namespace);
} catch (error) { } catch (error) {
core.error('Failed while watching build job'); core.error('Failed while watching build job');
@ -339,7 +319,7 @@ class Kubernetes {
static async streamLogs(name: string, namespace: string) { static async streamLogs(name: string, namespace: string) {
try { try {
let running = true; let running = true;
let logQueryTime: number = 0; let logQueryTime: number = 999;
let mostRecentLine: string = ''; let mostRecentLine: string = '';
while (running) { while (running) {
const pod = await this.kubeClient.readNamespacedPod(name, namespace); const pod = await this.kubeClient.readNamespacedPod(name, namespace);