Refactoring Remote Builder to route to aws or k8s
parent
49d581a167
commit
0149cf79f2
|
|
@ -854,17 +854,20 @@ const core = __importStar(__webpack_require__(42186));
|
|||
const remote_builder_constants_1 = __importDefault(__webpack_require__(92560));
|
||||
const aws_build_runner_1 = __importDefault(__webpack_require__(11201));
|
||||
class AWSBuildEnvironment {
|
||||
static runBuild(buildId, stackName, image, commands, mountdir, workingdir, environment, secrets) {
|
||||
run() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
runBuild(buildId, stackName, image, commands, mountdir, workingdir, environment, secrets) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const ECS = new SDK.ECS();
|
||||
const CF = new SDK.CloudFormation();
|
||||
const entrypoint = ['/bin/sh'];
|
||||
const taskDef = yield this.setupCloudFormations(CF, buildId, stackName, image, entrypoint, commands, mountdir, workingdir, secrets);
|
||||
const taskDef = yield AWSBuildEnvironment.setupCloudFormations(CF, buildId, stackName, image, entrypoint, commands, mountdir, workingdir, secrets);
|
||||
try {
|
||||
yield aws_build_runner_1.default.runTask(taskDef, ECS, CF, environment, buildId);
|
||||
}
|
||||
finally {
|
||||
yield this.cleanupResources(CF, taskDef);
|
||||
yield AWSBuildEnvironment.cleanupResources(CF, taskDef);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -1278,6 +1281,50 @@ class Kubernetes {
|
|||
this.baseImage = baseImage;
|
||||
this.setUniqueBuildId();
|
||||
}
|
||||
runBuild(buildId, stackName, image, commands, mountdir, workingdir, environment, secrets) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const defaultSecretsArray = [
|
||||
{
|
||||
ParameterKey: 'GithubToken',
|
||||
EnvironmentVariable: 'GITHUB_TOKEN',
|
||||
ParameterValue: this.buildParameters.githubToken,
|
||||
},
|
||||
{
|
||||
ParameterKey: 'UNITY_LICENSE',
|
||||
EnvironmentVariable: 'UNITY_LICENSE',
|
||||
ParameterValue: process.env.UNITY_LICENSE || '',
|
||||
},
|
||||
{
|
||||
ParameterKey: 'ANDROID_KEYSTORE_BASE64',
|
||||
EnvironmentVariable: 'ANDROID_KEYSTORE_BASE64',
|
||||
ParameterValue: this.buildParameters.androidKeystoreBase64,
|
||||
},
|
||||
{
|
||||
ParameterKey: 'ANDROID_KEYSTORE_PASS',
|
||||
EnvironmentVariable: 'ANDROID_KEYSTORE_PASS',
|
||||
ParameterValue: this.buildParameters.androidKeystorePass,
|
||||
},
|
||||
{
|
||||
ParameterKey: 'ANDROID_KEYALIAS_PASS',
|
||||
EnvironmentVariable: 'ANDROID_KEYALIAS_PASS',
|
||||
ParameterValue: this.buildParameters.androidKeyaliasPass,
|
||||
},
|
||||
];
|
||||
defaultSecretsArray.push(...secrets);
|
||||
try {
|
||||
// setup
|
||||
yield this.createSecret(defaultSecretsArray);
|
||||
yield kubernetes_storage_1.default.createPersistentVolumeClaim(this.buildParameters, this.pvcName, this.kubeClient, this.namespace);
|
||||
// run
|
||||
yield this.runJob(commands, image);
|
||||
yield this.cleanup();
|
||||
}
|
||||
catch (error) {
|
||||
core.error(JSON.stringify(error.response, undefined, 4));
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
setUniqueBuildId() {
|
||||
const buildId = Kubernetes.uuidv4();
|
||||
const pvcName = `unity-builder-pvc-${buildId}`;
|
||||
|
|
@ -1676,6 +1723,11 @@ class KubernetesStorage {
|
|||
yield async_wait_until_1.default(() => __awaiter(this, void 0, void 0, function* () { return (yield this.getPVCPhase(kubeClient, name, namespace)) !== 'Pending'; }), {
|
||||
timeout: 500000,
|
||||
});
|
||||
core.info(JSON.stringify((yield kubeClient.readNamespacedPersistentVolumeClaimStatus(name, namespace)).body, undefined, 4));
|
||||
const pvc = (yield kubeClient.readNamespacedPersistentVolumeClaim(name, namespace)).body;
|
||||
core.info(JSON.stringify(pvc, undefined, 4));
|
||||
core.info(JSON.stringify((yield kubeClient.readNamespacedPersistentVolumeClaim(name, namespace)).body, undefined, 4));
|
||||
core.info(JSON.stringify((yield kubeClient.replaceNamespacedPersistentVolumeClaimStatus(name, namespace, pvc)).body, undefined, 4));
|
||||
});
|
||||
}
|
||||
static createPersistentVolumeClaim(buildParameters, pvcName, kubeClient, namespace) {
|
||||
|
|
@ -1702,8 +1754,6 @@ class KubernetesStorage {
|
|||
};
|
||||
yield kubeClient.createNamespacedPersistentVolumeClaim(namespace, pvc);
|
||||
core.info(`Persistent Volume created, ${yield KubernetesStorage.getPVCPhase(kubeClient, pvcName, namespace)}`);
|
||||
yield this.watchPersistentVolumeClaimUntilBoundToContainer(kubeClient, pvcName, namespace);
|
||||
core.info(JSON.stringify((yield kubeClient.readNamespacedPersistentVolumeClaimStatus(pvcName, namespace)).body, undefined, 4));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1788,6 +1838,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|||
const aws_build_platform_1 = __importDefault(__webpack_require__(70187));
|
||||
const core = __importStar(__webpack_require__(42186));
|
||||
const remote_builder_namespace_1 = __importDefault(__webpack_require__(96003));
|
||||
const kubernetes_build_platform_1 = __importDefault(__webpack_require__(81730));
|
||||
const repositoryDirectoryName = 'repo';
|
||||
const efsDirectoryName = 'data';
|
||||
const cacheDirectoryName = 'cache';
|
||||
|
|
@ -1796,6 +1847,15 @@ class RemoteBuilder {
|
|||
var _a;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
switch (buildParameters.remoteBuildCluster) {
|
||||
case 'aws':
|
||||
this.RemoteBuilderProviderPlatform = new aws_build_platform_1.default();
|
||||
break;
|
||||
case 'k8s':
|
||||
default:
|
||||
this.RemoteBuilderProviderPlatform = new kubernetes_build_platform_1.default(buildParameters, baseImage);
|
||||
break;
|
||||
}
|
||||
this.SteamDeploy = process.env.STEAM_DEPLOY !== undefined || false;
|
||||
const buildUid = remote_builder_namespace_1.default.generateBuildName(process.env.GITHUB_RUN_NUMBER, buildParameters.platform);
|
||||
const defaultBranchName = ((_a = process.env.GITHUB_REF) === null || _a === void 0 ? void 0 : _a.split('/').filter((x) => {
|
||||
|
|
@ -1828,7 +1888,7 @@ class RemoteBuilder {
|
|||
static SetupStep(buildUid, buildParameters, branchName, defaultSecretsArray) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Starting step 1/4 clone and restore cache)');
|
||||
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'alpine/git', [
|
||||
yield this.RemoteBuilderProviderPlatform.runBuild(buildUid, buildParameters.awsStackName, 'alpine/git', [
|
||||
'-c',
|
||||
`apk update;
|
||||
apk add unzip;
|
||||
|
|
@ -1940,7 +2000,7 @@ class RemoteBuilder {
|
|||
ParameterValue: buildParameters.androidKeyaliasPass,
|
||||
});
|
||||
core.info('Starting part 2/4 (build unity project)');
|
||||
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, baseImage.toString(), [
|
||||
yield this.RemoteBuilderProviderPlatform.runBuild(buildUid, buildParameters.awsStackName, baseImage.toString(), [
|
||||
'-c',
|
||||
`
|
||||
cp -r /${efsDirectoryName}/${buildUid}/builder/dist/default-build-script/ /UnityBuilderAction;
|
||||
|
|
@ -2010,7 +2070,7 @@ class RemoteBuilder {
|
|||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Starting step 3/4 build compression');
|
||||
// Cleanup
|
||||
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'alpine', [
|
||||
yield this.RemoteBuilderProviderPlatform.runBuild(buildUid, buildParameters.awsStackName, 'alpine', [
|
||||
'-c',
|
||||
`
|
||||
apk update
|
||||
|
|
@ -2037,7 +2097,7 @@ class RemoteBuilder {
|
|||
static UploadArtifacts(buildUid, buildParameters, branchName, defaultSecretsArray) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Starting step 4/4 upload build to s3');
|
||||
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'amazon/aws-cli', [
|
||||
yield this.RemoteBuilderProviderPlatform.runBuild(buildUid, buildParameters.awsStackName, 'amazon/aws-cli', [
|
||||
'-c',
|
||||
`
|
||||
aws s3 cp ${buildUid}/build-${buildUid}.zip s3://game-ci-storage/
|
||||
|
|
@ -2072,7 +2132,7 @@ class RemoteBuilder {
|
|||
static DeployToSteam(buildUid, buildParameters, defaultSecretsArray) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info('Starting steam deployment');
|
||||
yield aws_build_platform_1.default.runBuild(buildUid, buildParameters.awsStackName, 'cm2network/steamcmd:root', [
|
||||
yield this.RemoteBuilderProviderPlatform.runBuild(buildUid, buildParameters.awsStackName, 'cm2network/steamcmd:root', [
|
||||
'-c',
|
||||
`
|
||||
ls
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -7,9 +7,13 @@ import * as core from '@actions/core';
|
|||
import RemoteBuilderTaskDef from './remote-builder-task-def';
|
||||
import RemoteBuilderConstants from './remote-builder-constants';
|
||||
import AWSBuildRunner from './aws-build-runner';
|
||||
import { RemoteBuilderProviderInterface } from './remote-builder-provider-interface';
|
||||
|
||||
class AWSBuildEnvironment {
|
||||
static async runBuild(
|
||||
class AWSBuildEnvironment implements RemoteBuilderProviderInterface {
|
||||
run(): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
async runBuild(
|
||||
buildId: string,
|
||||
stackName: string,
|
||||
image: string,
|
||||
|
|
@ -18,12 +22,12 @@ class AWSBuildEnvironment {
|
|||
workingdir: string,
|
||||
environment: RemoteBuilderEnvironmentVariable[],
|
||||
secrets: RemoteBuilderSecret[],
|
||||
) {
|
||||
): Promise<void> {
|
||||
const ECS = new SDK.ECS();
|
||||
const CF = new SDK.CloudFormation();
|
||||
const entrypoint = ['/bin/sh'];
|
||||
|
||||
const taskDef = await this.setupCloudFormations(
|
||||
const taskDef = await AWSBuildEnvironment.setupCloudFormations(
|
||||
CF,
|
||||
buildId,
|
||||
stackName,
|
||||
|
|
@ -37,7 +41,7 @@ class AWSBuildEnvironment {
|
|||
try {
|
||||
await AWSBuildRunner.runTask(taskDef, ECS, CF, environment, buildId);
|
||||
} finally {
|
||||
await this.cleanupResources(CF, taskDef);
|
||||
await AWSBuildEnvironment.cleanupResources(CF, taskDef);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { RemoteBuilderProviderInterface } from './remote-builder-provider-interf
|
|||
import RemoteBuilderSecret from './remote-builder-secret';
|
||||
import { waitUntil } from 'async-wait-until';
|
||||
import KubernetesStorage from './kubernetes-storage';
|
||||
import RemoteBuilderEnvironmentVariable from './remote-builder-environment-variable';
|
||||
|
||||
const base64 = require('base-64');
|
||||
|
||||
|
|
@ -41,6 +42,63 @@ class Kubernetes implements RemoteBuilderProviderInterface {
|
|||
|
||||
this.setUniqueBuildId();
|
||||
}
|
||||
async runBuild(
|
||||
buildId: string,
|
||||
stackName: string,
|
||||
image: string,
|
||||
commands: string[],
|
||||
mountdir: string,
|
||||
workingdir: string,
|
||||
environment: RemoteBuilderEnvironmentVariable[],
|
||||
secrets: RemoteBuilderSecret[],
|
||||
): Promise<void> {
|
||||
const defaultSecretsArray: RemoteBuilderSecret[] = [
|
||||
{
|
||||
ParameterKey: 'GithubToken',
|
||||
EnvironmentVariable: 'GITHUB_TOKEN',
|
||||
ParameterValue: this.buildParameters.githubToken,
|
||||
},
|
||||
{
|
||||
ParameterKey: 'UNITY_LICENSE',
|
||||
EnvironmentVariable: 'UNITY_LICENSE',
|
||||
ParameterValue: process.env.UNITY_LICENSE || '',
|
||||
},
|
||||
{
|
||||
ParameterKey: 'ANDROID_KEYSTORE_BASE64',
|
||||
EnvironmentVariable: 'ANDROID_KEYSTORE_BASE64',
|
||||
ParameterValue: this.buildParameters.androidKeystoreBase64,
|
||||
},
|
||||
{
|
||||
ParameterKey: 'ANDROID_KEYSTORE_PASS',
|
||||
EnvironmentVariable: 'ANDROID_KEYSTORE_PASS',
|
||||
ParameterValue: this.buildParameters.androidKeystorePass,
|
||||
},
|
||||
{
|
||||
ParameterKey: 'ANDROID_KEYALIAS_PASS',
|
||||
EnvironmentVariable: 'ANDROID_KEYALIAS_PASS',
|
||||
ParameterValue: this.buildParameters.androidKeyaliasPass,
|
||||
},
|
||||
];
|
||||
defaultSecretsArray.push(...secrets);
|
||||
try {
|
||||
// setup
|
||||
await this.createSecret(defaultSecretsArray);
|
||||
await KubernetesStorage.createPersistentVolumeClaim(
|
||||
this.buildParameters,
|
||||
this.pvcName,
|
||||
this.kubeClient,
|
||||
this.namespace,
|
||||
);
|
||||
|
||||
// run
|
||||
await this.runJob(commands, image);
|
||||
|
||||
await this.cleanup();
|
||||
} catch (error) {
|
||||
core.error(JSON.stringify(error.response, undefined, 4));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
setUniqueBuildId() {
|
||||
const buildId = Kubernetes.uuidv4();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,26 @@ class KubernetesStorage {
|
|||
await waitUntil(async () => (await this.getPVCPhase(kubeClient, name, namespace)) !== 'Pending', {
|
||||
timeout: 500000,
|
||||
});
|
||||
|
||||
core.info(
|
||||
JSON.stringify((await kubeClient.readNamespacedPersistentVolumeClaimStatus(name, namespace)).body, undefined, 4),
|
||||
);
|
||||
|
||||
const pvc = (await kubeClient.readNamespacedPersistentVolumeClaim(name, namespace)).body;
|
||||
|
||||
core.info(JSON.stringify(pvc, undefined, 4));
|
||||
|
||||
core.info(
|
||||
JSON.stringify((await kubeClient.readNamespacedPersistentVolumeClaim(name, namespace)).body, undefined, 4),
|
||||
);
|
||||
|
||||
core.info(
|
||||
JSON.stringify(
|
||||
(await kubeClient.replaceNamespacedPersistentVolumeClaimStatus(name, namespace, pvc)).body,
|
||||
undefined,
|
||||
4,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public static async createPersistentVolumeClaim(
|
||||
|
|
@ -45,14 +65,6 @@ class KubernetesStorage {
|
|||
};
|
||||
await kubeClient.createNamespacedPersistentVolumeClaim(namespace, pvc);
|
||||
core.info(`Persistent Volume created, ${await KubernetesStorage.getPVCPhase(kubeClient, pvcName, namespace)}`);
|
||||
await this.watchPersistentVolumeClaimUntilBoundToContainer(kubeClient, pvcName, namespace);
|
||||
core.info(
|
||||
JSON.stringify(
|
||||
(await kubeClient.readNamespacedPersistentVolumeClaimStatus(pvcName, namespace)).body,
|
||||
undefined,
|
||||
4,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,24 @@
|
|||
import RemoteBuilderEnvironmentVariable from './remote-builder-environment-variable';
|
||||
import RemoteBuilderSecret from './remote-builder-secret';
|
||||
|
||||
export interface RemoteBuilderProviderInterface {
|
||||
run(): Promise<void>;
|
||||
runBuild(
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
buildId: string,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
stackName: string,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
image: string,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
commands: string[],
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
mountdir: string,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
workingdir: string,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
environment: RemoteBuilderEnvironmentVariable[],
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
secrets: RemoteBuilderSecret[],
|
||||
): Promise<void>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,26 @@ import * as core from '@actions/core';
|
|||
import { BuildParameters } from '..';
|
||||
import RemoteBuilderNamespace from './remote-builder-namespace';
|
||||
import RemoteBuilderSecret from './remote-builder-secret';
|
||||
import { RemoteBuilderProviderInterface } from './remote-builder-provider-interface';
|
||||
import Kubernetes from './kubernetes-build-platform';
|
||||
const repositoryDirectoryName = 'repo';
|
||||
const efsDirectoryName = 'data';
|
||||
const cacheDirectoryName = 'cache';
|
||||
|
||||
class RemoteBuilder {
|
||||
static SteamDeploy: boolean = false;
|
||||
static RemoteBuilderProviderPlatform: RemoteBuilderProviderInterface;
|
||||
static async build(buildParameters: BuildParameters, baseImage) {
|
||||
try {
|
||||
switch (buildParameters.remoteBuildCluster) {
|
||||
case 'aws':
|
||||
this.RemoteBuilderProviderPlatform = new AWSBuildPlatform();
|
||||
break;
|
||||
case 'k8s':
|
||||
default:
|
||||
this.RemoteBuilderProviderPlatform = new Kubernetes(buildParameters, baseImage);
|
||||
break;
|
||||
}
|
||||
this.SteamDeploy = process.env.STEAM_DEPLOY !== undefined || false;
|
||||
const buildUid = RemoteBuilderNamespace.generateBuildName(
|
||||
process.env.GITHUB_RUN_NUMBER,
|
||||
|
|
@ -53,7 +65,7 @@ class RemoteBuilder {
|
|||
defaultSecretsArray: RemoteBuilderSecret[],
|
||||
) {
|
||||
core.info('Starting step 1/4 clone and restore cache)');
|
||||
await AWSBuildPlatform.runBuild(
|
||||
await this.RemoteBuilderProviderPlatform.runBuild(
|
||||
buildUid,
|
||||
buildParameters.awsStackName,
|
||||
'alpine/git',
|
||||
|
|
@ -188,7 +200,7 @@ class RemoteBuilder {
|
|||
ParameterValue: buildParameters.androidKeyaliasPass,
|
||||
});
|
||||
core.info('Starting part 2/4 (build unity project)');
|
||||
await AWSBuildPlatform.runBuild(
|
||||
await this.RemoteBuilderProviderPlatform.runBuild(
|
||||
buildUid,
|
||||
buildParameters.awsStackName,
|
||||
baseImage.toString(),
|
||||
|
|
@ -271,7 +283,7 @@ class RemoteBuilder {
|
|||
) {
|
||||
core.info('Starting step 3/4 build compression');
|
||||
// Cleanup
|
||||
await AWSBuildPlatform.runBuild(
|
||||
await this.RemoteBuilderProviderPlatform.runBuild(
|
||||
buildUid,
|
||||
buildParameters.awsStackName,
|
||||
'alpine',
|
||||
|
|
@ -311,7 +323,7 @@ class RemoteBuilder {
|
|||
defaultSecretsArray: RemoteBuilderSecret[],
|
||||
) {
|
||||
core.info('Starting step 4/4 upload build to s3');
|
||||
await AWSBuildPlatform.runBuild(
|
||||
await this.RemoteBuilderProviderPlatform.runBuild(
|
||||
buildUid,
|
||||
buildParameters.awsStackName,
|
||||
'amazon/aws-cli',
|
||||
|
|
@ -358,7 +370,7 @@ class RemoteBuilder {
|
|||
defaultSecretsArray: RemoteBuilderSecret[],
|
||||
) {
|
||||
core.info('Starting steam deployment');
|
||||
await AWSBuildPlatform.runBuild(
|
||||
await this.RemoteBuilderProviderPlatform.runBuild(
|
||||
buildUid,
|
||||
buildParameters.awsStackName,
|
||||
'cm2network/steamcmd:root',
|
||||
|
|
|
|||
Loading…
Reference in New Issue