Refactor to typescript (convert extensions, minor fixes)

pull/226/head
Webber Takken 2021-03-08 01:05:42 +01:00
parent 6d3fde10d7
commit ec740fbfd5
40 changed files with 80 additions and 143 deletions

View File

@ -14,9 +14,9 @@ describe('Action', () => {
});
it('returns the root folder of the action', () => {
const { rootFolder, name } = Action;
const { rootFolder, canonicalName } = Action;
expect(path.basename(rootFolder)).toStrictEqual(name);
expect(path.basename(rootFolder)).toStrictEqual(canonicalName);
expect(fs.existsSync(rootFolder)).toStrictEqual(true);
});

View File

@ -13,7 +13,7 @@ class Action {
return path.basename(__dirname) === 'model';
}
static get name() {
static get canonicalName() {
return 'unity-builder';
}

View File

@ -19,8 +19,7 @@ export default class AndroidVersioning {
// The greatest value Google Plays allows is 2100000000.
// Allow for 3 patch digits, 3 minor digits and 3 major digits.
const versionCode =
parsedVersion.major * 1000000 + parsedVersion.minor * 1000 + parsedVersion.patch;
const versionCode = parsedVersion.major * 1000000 + parsedVersion.minor * 1000 + parsedVersion.patch;
if (versionCode >= 1000000000) {
throw new Error(

View File

@ -4,9 +4,7 @@ import BuildParameters from './build-parameters';
import Input from './input';
import Platform from './platform';
const determineVersion = jest
.spyOn(Versioning, 'determineVersion')
.mockImplementation(() => '1.3.37');
const determineVersion = jest.spyOn(Versioning, 'determineVersion').mockImplementation(() => '1.3.37');
const determineUnityVersion = jest
.spyOn(UnityVersioning, 'determineUnityVersion')
@ -43,33 +41,25 @@ describe('BuildParameters', () => {
it('returns the android version code from version by default', async () => {
const mockValue = '';
jest.spyOn(Input, 'androidVersionCode', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ androidVersionCode: 1003037 }),
);
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ androidVersionCode: 1003037 }));
});
it('returns the platform', async () => {
const mockValue = 'somePlatform';
jest.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ platform: mockValue }),
);
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ platform: mockValue }));
});
it('returns the project path', async () => {
const mockValue = 'path/to/project';
jest.spyOn(Input, 'projectPath', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ projectPath: mockValue }),
);
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ projectPath: mockValue }));
});
it('returns the build name', async () => {
const mockValue = 'someBuildName';
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ buildName: mockValue }),
);
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildName: mockValue }));
});
it('returns the build path', async () => {
@ -86,9 +76,7 @@ describe('BuildParameters', () => {
it('returns the build file', async () => {
const mockValue = 'someBuildName';
jest.spyOn(Input, 'buildName', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ buildFile: mockValue }),
);
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildFile: mockValue }));
});
test.each([Platform.types.StandaloneWindows, Platform.types.StandaloneWindows64])(
@ -123,9 +111,7 @@ describe('BuildParameters', () => {
it('returns the build method', async () => {
const mockValue = 'Namespace.ClassName.BuildMethod';
jest.spyOn(Input, 'buildMethod', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ buildMethod: mockValue }),
);
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ buildMethod: mockValue }));
});
it('returns the android keystore name', async () => {
@ -171,9 +157,7 @@ describe('BuildParameters', () => {
it('returns the custom parameters', async () => {
const mockValue = '-profile SomeProfile -someBoolean -someValue exampleValue';
jest.spyOn(Input, 'customParameters', 'get').mockReturnValue(mockValue);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ customParameters: mockValue }),
);
await expect(BuildParameters.create()).resolves.toEqual(expect.objectContaining({ customParameters: mockValue }));
});
});
});

View File

@ -6,26 +6,13 @@ import Versioning from './versioning';
class BuildParameters {
static async create() {
const buildFile = this.parseBuildFile(
Input.buildName,
Input.targetPlatform,
Input.androidAppBundle,
);
const buildFile = this.parseBuildFile(Input.buildName, Input.targetPlatform, Input.androidAppBundle);
const unityVersion = UnityVersioning.determineUnityVersion(
Input.projectPath,
Input.unityVersion,
);
const unityVersion = UnityVersioning.determineUnityVersion(Input.projectPath, Input.unityVersion);
const buildVersion = await Versioning.determineVersion(
Input.versioningStrategy,
Input.specifiedVersion,
);
const buildVersion = await Versioning.determineVersion(Input.versioningStrategy, Input.specifiedVersion);
const androidVersionCode = AndroidVersioning.determineVersionCode(
buildVersion,
Input.androidVersionCode,
);
const androidVersionCode = AndroidVersioning.determineVersionCode(buildVersion, Input.androidVersionCode);
return {
version: unityVersion,

View File

@ -2,14 +2,15 @@ import { trimEnd, trimStart } from 'lodash-es';
import Platform from './platform';
class ImageTag {
private repository: string;
private name: string;
private version: string;
private platform: any;
private builderPlatform: string;
private customImage: any;
constructor(imageProperties) {
const {
repository = 'unityci',
name = 'editor',
version = '2019.2.11f1',
platform,
customImage,
} = imageProperties;
const { repository = 'unityci', name = 'editor', version = '2019.2.11f1', platform, customImage } = imageProperties;
if (!ImageTag.versionPattern.test(version)) {
throw new Error(`Invalid version "${version}".`);
@ -17,7 +18,12 @@ class ImageTag {
const builderPlatform = ImageTag.getTargetPlatformToImageSuffixMap(platform, version);
Object.assign(this, { repository, name, version, platform, builderPlatform, customImage });
this.repository = repository;
this.name = name;
this.version = version;
this.platform = platform;
this.builderPlatform = builderPlatform;
this.customImage = customImage;
}
static get versionPattern() {
@ -39,17 +45,7 @@ class ImageTag {
}
static getTargetPlatformToImageSuffixMap(platform, version) {
const {
generic,
webgl,
mac,
windows,
linux,
linuxIl2cpp,
android,
ios,
facebook,
} = ImageTag.imageSuffixes;
const { generic, webgl, mac, windows, linux, linuxIl2cpp, android, ios, facebook } = ImageTag.imageSuffixes;
const [major, minor] = version.split('.').map((digit) => Number(digit));
// @see: https://docs.unity3d.com/ScriptReference/BuildTarget.html

View File

@ -1,17 +0,0 @@
import * as Index from '.';
describe('Index', () => {
test.each([
'Action',
'BuildParameters',
'Cache',
'Docker',
'ImageTag',
'Input',
'Platform',
'Project',
'Unity',
])('exports %s', (exportedModule) => {
expect(Index[exportedModule]).toBeEitherAFunctionOrAnObject();
});
});

View File

@ -0,0 +1,10 @@
import * as Index from '.';
describe('Index', () => {
test.each(['Action', 'BuildParameters', 'Cache', 'Docker', 'ImageTag', 'Input', 'Platform', 'Project', 'Unity'])(
'exports %s',
(exportedModule) => {
expect(Index[exportedModule]).toBeEitherAFunctionOrAnObject();
},
);
});

View File

@ -1,3 +1,4 @@
// @ts-ignore
import { Client, KubeConfig } from 'kubernetes-client';
import Request from 'kubernetes-client/backends/request';
@ -7,6 +8,15 @@ const base64 = require('base-64');
const pollInterval = 10000;
class Kubernetes {
private static kubeClient: any;
private static buildId: string;
private static buildParameters: any;
private static baseImage: any;
private static pvcName: string;
private static secretName: string;
private static jobName: string;
private static namespace: string;
static async runBuildJob(buildParameters, baseImage) {
const kubeconfig = new KubeConfig();
kubeconfig.loadFromString(base64.decode(buildParameters.kubeConfig));
@ -20,16 +30,14 @@ class Kubernetes {
const jobName = `unity-builder-job-${buildId}`;
const namespace = 'default';
Object.assign(this, {
kubeClient,
buildId,
buildParameters,
baseImage,
pvcName,
secretName,
jobName,
namespace,
});
this.kubeClient = kubeClient;
this.buildId = buildId;
this.buildParameters = buildParameters;
this.baseImage = baseImage;
this.pvcName = pvcName;
this.secretName = secretName;
this.jobName = jobName;
this.namespace = namespace;
await Kubernetes.createSecret();
await Kubernetes.createPersistentVolumeClaim();
@ -81,9 +89,7 @@ class Kubernetes {
},
},
};
await this.kubeClient.api.v1
.namespaces(this.namespace)
.persistentvolumeclaims.post({ body: pvcManifest });
await this.kubeClient.api.v1.namespaces(this.namespace).persistentvolumeclaims.post({ body: pvcManifest });
core.info('Persistent Volume created, waiting for ready state...');
await Kubernetes.watchPersistentVolumeClaimUntilReady();
core.info('Persistent Volume ready for claims');

View File

@ -36,9 +36,7 @@ describe('Versioning', () => {
describe('branch', () => {
it('returns headRef when set', () => {
const headReference = jest
.spyOn(Versioning, 'headRef', 'get')
.mockReturnValue('feature-branch-1');
const headReference = jest.spyOn(Versioning, 'headRef', 'get').mockReturnValue('feature-branch-1');
expect(Versioning.branch).toStrictEqual('feature-branch-1');
expect(headReference).toHaveBeenCalledTimes(1);
@ -46,21 +44,15 @@ describe('Versioning', () => {
it('returns part of Ref when set', () => {
jest.spyOn(Versioning, 'headRef', 'get').mockReturnValue(undefined);
const reference = jest
.spyOn(Versioning, 'ref', 'get')
.mockReturnValue('refs/heads/feature-branch-2');
const reference = jest.spyOn(Versioning, 'ref', 'get').mockReturnValue('refs/heads/feature-branch-2');
expect(Versioning.branch).toStrictEqual('feature-branch-2');
expect(reference).toHaveBeenCalledTimes(2);
});
it('prefers headRef over ref when set', () => {
const headReference = jest
.spyOn(Versioning, 'headRef', 'get')
.mockReturnValue('feature-branch-1');
const reference = jest
.spyOn(Versioning, 'ref', 'get')
.mockReturnValue('refs/heads/feature-2');
const headReference = jest.spyOn(Versioning, 'headRef', 'get').mockReturnValue('feature-branch-1');
const reference = jest.spyOn(Versioning, 'ref', 'get').mockReturnValue('refs/heads/feature-2');
expect(Versioning.branch).toStrictEqual('feature-branch-1');
expect(headReference).toHaveBeenCalledTimes(1);
@ -135,29 +127,21 @@ describe('Versioning', () => {
},
);
test.each([undefined, 'v0', 'v0.1', 'v0.1.2', 'v0.1-2', 'v0.1-2-g'])(
'does not like %s',
(description) => {
expect(Versioning.descriptionRegex1.test(description)).toBeFalsy();
// Also never expect without the v to work for any of these cases.
expect(Versioning.descriptionRegex1.test(description?.substr(1))).toBeFalsy();
},
);
test.each([undefined, 'v0', 'v0.1', 'v0.1.2', 'v0.1-2', 'v0.1-2-g'])('does not like %s', (description) => {
expect(Versioning.descriptionRegex1.test(description)).toBeFalsy();
// Also never expect without the v to work for any of these cases.
expect(Versioning.descriptionRegex1.test(description?.substr(1))).toBeFalsy();
});
});
describe('determineVersion', () => {
test.each([undefined, 0, 'somethingRandom'])(
'throws for invalid strategy %s',
async (strategy) => {
await expect(Versioning.determineVersion(strategy)).rejects.toThrowErrorMatchingSnapshot();
},
);
test.each([undefined, 0, 'somethingRandom'])('throws for invalid strategy %s', async (strategy) => {
await expect(Versioning.determineVersion(strategy)).rejects.toThrowErrorMatchingSnapshot();
});
describe('opt out strategy', () => {
it("returns 'none'", async () => {
await expect(Versioning.determineVersion('None', 'v1.0')).resolves.toMatchInlineSnapshot(
`"none"`,
);
await expect(Versioning.determineVersion('None', 'v1.0')).resolves.toMatchInlineSnapshot(`"none"`);
});
});
@ -165,18 +149,14 @@ describe('Versioning', () => {
test.each([undefined, 0, 'v0.1', '1', 'CamelCase', 'dashed-version'])(
'returns the inputVersion for %s',
async (inputVersion) => {
await expect(Versioning.determineVersion('Custom', inputVersion)).resolves.toStrictEqual(
inputVersion,
);
await expect(Versioning.determineVersion('Custom', inputVersion)).resolves.toStrictEqual(inputVersion);
},
);
});
describe('semantic strategy', () => {
it('refers to generateSemanticVersion', async () => {
const generateSemanticVersion = jest
.spyOn(Versioning, 'generateSemanticVersion')
.mockResolvedValue('1.3.37');
const generateSemanticVersion = jest.spyOn(Versioning, 'generateSemanticVersion').mockResolvedValue('1.3.37');
await expect(Versioning.determineVersion('Semantic')).resolves.toStrictEqual('1.3.37');
expect(generateSemanticVersion).toHaveBeenCalledTimes(1);
@ -185,9 +165,7 @@ describe('Versioning', () => {
describe('tag strategy', () => {
it('refers to generateTagVersion', async () => {
const generateTagVersion = jest
.spyOn(Versioning, 'generateTagVersion')
.mockResolvedValue('0.1');
const generateTagVersion = jest.spyOn(Versioning, 'generateTagVersion').mockResolvedValue('0.1');
await expect(Versioning.determineVersion('Tag')).resolves.toStrictEqual('0.1');
expect(generateTagVersion).toHaveBeenCalledTimes(1);
@ -198,9 +176,7 @@ describe('Versioning', () => {
it('throws a not implemented exception', async () => {
const strategy = 'Test';
jest.spyOn(Versioning, 'strategies', 'get').mockReturnValue({ [strategy]: strategy });
await expect(Versioning.determineVersion(strategy)).rejects.toThrowError(
NotImplementedException,
);
await expect(Versioning.determineVersion(strategy)).rejects.toThrowError(NotImplementedException);
});
});
});
@ -261,10 +237,7 @@ describe('Versioning', () => {
it('falls back to the second strategy when the first fails', async () => {
jest.spyOn(core, 'warning').mockImplementation(() => {});
const gitFetch = jest
.spyOn(System, 'run')
.mockResolvedValue(undefined)
.mockRejectedValueOnce(undefined);
const gitFetch = jest.spyOn(System, 'run').mockResolvedValue(undefined).mockRejectedValueOnce(undefined);
await expect(Versioning.fetch()).resolves.not.toThrow();
expect(gitFetch).toHaveBeenCalledTimes(2);

View File

@ -82,9 +82,7 @@ export default class Versioning {
static async determineVersion(strategy, inputVersion) {
// Validate input
if (!Object.hasOwnProperty.call(this.strategies, strategy)) {
throw new ValidationError(
`Versioning strategy should be one of ${Object.values(this.strategies).join(', ')}.`,
);
throw new ValidationError(`Versioning strategy should be one of ${Object.values(this.strategies).join(', ')}.`);
}
let version;
@ -167,6 +165,7 @@ export default class Versioning {
const description = await this.getVersionDescription();
try {
// @ts-ignore
const [match, tag, commits, hash] = this.descriptionRegex1.exec(description);
return {