mirror of
https://github.com/game-ci/unity-test-runner.git
synced 2026-02-04 19:29:06 +08:00
Unity builder v4 Parity Update (#246)
- Updated activation strategy to align with builder strategy for more stable activation with retry logic - Added `containerRegistryImageVersion` and `containerRegistryRepository` for improved custom image support - Added `runAsHostUser` to fix self-hosted runner issues - Scripts folder cleanup - Added error/warning annotations for activation issues - Improved serial masking - Image environment factory addition and docker refactoring
This commit is contained in:
13
src/main.ts
13
src/main.ts
@@ -27,8 +27,17 @@ export async function run() {
|
||||
dockerMemoryLimit,
|
||||
dockerIsolationMode,
|
||||
unityLicensingServer,
|
||||
runAsHostUser,
|
||||
containerRegistryRepository,
|
||||
containerRegistryImageVersion,
|
||||
unitySerial,
|
||||
} = Input.getFromUser();
|
||||
const baseImage = new ImageTag({ editorVersion, customImage });
|
||||
const baseImage = new ImageTag({
|
||||
editorVersion,
|
||||
customImage,
|
||||
containerRegistryRepository,
|
||||
containerRegistryImageVersion,
|
||||
});
|
||||
const runnerContext = Action.runnerContext();
|
||||
|
||||
try {
|
||||
@@ -53,6 +62,8 @@ export async function run() {
|
||||
dockerMemoryLimit,
|
||||
dockerIsolationMode,
|
||||
unityLicensingServer,
|
||||
runAsHostUser,
|
||||
unitySerial,
|
||||
...runnerContext,
|
||||
});
|
||||
} finally {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import ImageEnvironmentFactory from './image-environment-factory';
|
||||
import { existsSync, mkdirSync, readFileSync, rmSync } from 'fs';
|
||||
import LicensingServerSetup from './licensing-server-setup';
|
||||
import type { RunnerContext } from './action';
|
||||
@@ -53,25 +54,15 @@ const Docker = {
|
||||
getLinuxCommand(image, parameters): string {
|
||||
const {
|
||||
actionFolder,
|
||||
editorVersion,
|
||||
workspace,
|
||||
projectPath,
|
||||
customParameters,
|
||||
testMode,
|
||||
coverageOptions,
|
||||
artifactsPath,
|
||||
useHostNetwork,
|
||||
sshAgent,
|
||||
sshPublicKeysDirectoryPath,
|
||||
packageMode,
|
||||
packageName,
|
||||
gitPrivateToken,
|
||||
githubToken,
|
||||
runnerTemporaryPath,
|
||||
chownFilesTo,
|
||||
dockerCpuLimit,
|
||||
dockerMemoryLimit,
|
||||
unityLicensingServer,
|
||||
} = parameters;
|
||||
|
||||
const githubHome = path.join(runnerTemporaryPath, '_github_home');
|
||||
@@ -84,91 +75,52 @@ const Docker = {
|
||||
).join(';');
|
||||
|
||||
return `docker run \
|
||||
--workdir /github/workspace \
|
||||
--cidfile "${cidfile}" \
|
||||
--rm \
|
||||
--env UNITY_LICENSE \
|
||||
--env UNITY_LICENSE_FILE \
|
||||
--env UNITY_EMAIL \
|
||||
--env UNITY_PASSWORD \
|
||||
--env UNITY_SERIAL \
|
||||
--env UNITY_LICENSING_SERVER="${unityLicensingServer}" \
|
||||
--env UNITY_VERSION="${editorVersion}" \
|
||||
--env PROJECT_PATH="${projectPath}" \
|
||||
--env CUSTOM_PARAMETERS="${customParameters}" \
|
||||
--env TEST_PLATFORMS="${testPlatforms}" \
|
||||
--env COVERAGE_OPTIONS="${coverageOptions}" \
|
||||
--env COVERAGE_RESULTS_PATH="CodeCoverage" \
|
||||
--env ARTIFACTS_PATH="${artifactsPath}" \
|
||||
--env PACKAGE_MODE="${packageMode}" \
|
||||
--env PACKAGE_NAME="${packageName}" \
|
||||
--env GITHUB_REF \
|
||||
--env GITHUB_SHA \
|
||||
--env GITHUB_REPOSITORY \
|
||||
--env GITHUB_ACTOR \
|
||||
--env GITHUB_WORKFLOW \
|
||||
--env GITHUB_HEAD_REF \
|
||||
--env GITHUB_BASE_REF \
|
||||
--env GITHUB_EVENT_NAME \
|
||||
--env GITHUB_WORKSPACE="/github/workspace" \
|
||||
--env GITHUB_ACTION \
|
||||
--env GITHUB_EVENT_PATH \
|
||||
--env RUNNER_OS \
|
||||
--env RUNNER_TOOL_CACHE \
|
||||
--env RUNNER_TEMP \
|
||||
--env RUNNER_WORKSPACE \
|
||||
--env GIT_PRIVATE_TOKEN="${gitPrivateToken}" \
|
||||
--env CHOWN_FILES_TO="${chownFilesTo}" \
|
||||
--env GIT_CONFIG_EXTENSIONS \
|
||||
${sshAgent ? '--env SSH_AUTH_SOCK=/ssh-agent' : ''} \
|
||||
--volume "${githubHome}:/root:z" \
|
||||
--volume "${githubWorkflow}:/github/workflow:z" \
|
||||
--volume "${workspace}:/github/workspace:z" \
|
||||
--volume "${actionFolder}/test-standalone-scripts:/UnityStandaloneScripts:z" \
|
||||
--volume "${actionFolder}/steps:/steps:z" \
|
||||
--volume "${actionFolder}/entrypoint.sh:/entrypoint.sh:z" \
|
||||
--volume "${actionFolder}/unity-config:/usr/share/unity3d/config/:z" \
|
||||
--cpus=${dockerCpuLimit} \
|
||||
--memory=${dockerMemoryLimit} \
|
||||
${sshAgent ? `--volume ${sshAgent}:/ssh-agent` : ''} \
|
||||
${
|
||||
sshAgent && !sshPublicKeysDirectoryPath
|
||||
? `--volume /home/runner/.ssh/known_hosts:/root/.ssh/known_hosts:ro`
|
||||
: ''
|
||||
} \
|
||||
${
|
||||
sshPublicKeysDirectoryPath
|
||||
? `--volume ${sshPublicKeysDirectoryPath}:/root/.ssh:ro`
|
||||
: ''
|
||||
} \
|
||||
${useHostNetwork ? '--net=host' : ''} \
|
||||
${githubToken ? '--env USE_EXIT_CODE=false' : '--env USE_EXIT_CODE=true'} \
|
||||
${image} \
|
||||
/bin/bash -c /entrypoint.sh`;
|
||||
--workdir /github/workspace \
|
||||
--cidfile "${cidfile}" \
|
||||
--rm \
|
||||
${ImageEnvironmentFactory.getEnvVarString(parameters)} \
|
||||
--env GIT_CONFIG_EXTENSIONS \
|
||||
--env TEST_PLATFORMS="${testPlatforms}" \
|
||||
--env GITHUB_WORKSPACE="/github/workspace" \
|
||||
${sshAgent ? '--env SSH_AUTH_SOCK=/ssh-agent' : ''} \
|
||||
--volume "${githubHome}:/root:z" \
|
||||
--volume "${githubWorkflow}:/github/workflow:z" \
|
||||
--volume "${workspace}:/github/workspace:z" \
|
||||
--volume "${actionFolder}/test-standalone-scripts:/UnityStandaloneScripts:z" \
|
||||
--volume "${actionFolder}/platforms/ubuntu:/steps:z" \
|
||||
--volume "${actionFolder}/unity-config:/usr/share/unity3d/config/:z" \
|
||||
--volume "${actionFolder}/BlankProject":"/BlankProject:z" \
|
||||
--cpus=${dockerCpuLimit} \
|
||||
--memory=${dockerMemoryLimit} \
|
||||
${sshAgent ? `--volume ${sshAgent}:/ssh-agent` : ''} \
|
||||
${
|
||||
sshAgent && !sshPublicKeysDirectoryPath
|
||||
? `--volume /home/runner/.ssh/known_hosts:/root/.ssh/known_hosts:ro`
|
||||
: ''
|
||||
} \
|
||||
${
|
||||
sshPublicKeysDirectoryPath
|
||||
? `--volume ${sshPublicKeysDirectoryPath}:/root/.ssh:ro`
|
||||
: ''
|
||||
} \
|
||||
${useHostNetwork ? '--net=host' : ''} \
|
||||
${githubToken ? '--env USE_EXIT_CODE=false' : '--env USE_EXIT_CODE=true'} \
|
||||
${image} \
|
||||
/bin/bash -c "/steps/entrypoint.sh`;
|
||||
},
|
||||
|
||||
getWindowsCommand(image, parameters): string {
|
||||
const {
|
||||
actionFolder,
|
||||
editorVersion,
|
||||
workspace,
|
||||
projectPath,
|
||||
customParameters,
|
||||
testMode,
|
||||
coverageOptions,
|
||||
artifactsPath,
|
||||
useHostNetwork,
|
||||
sshAgent,
|
||||
packageMode,
|
||||
packageName,
|
||||
gitPrivateToken,
|
||||
githubToken,
|
||||
runnerTemporaryPath,
|
||||
chownFilesTo,
|
||||
dockerCpuLimit,
|
||||
dockerMemoryLimit,
|
||||
dockerIsolationMode,
|
||||
unityLicensingServer,
|
||||
} = parameters;
|
||||
|
||||
const githubHome = path.join(runnerTemporaryPath, '_github_home');
|
||||
@@ -181,48 +133,19 @@ const Docker = {
|
||||
).join(';');
|
||||
|
||||
return `docker run \
|
||||
--workdir /github/workspace \
|
||||
--workdir c:/github/workspace \
|
||||
--cidfile "${cidfile}" \
|
||||
--rm \
|
||||
--env UNITY_LICENSE \
|
||||
--env UNITY_LICENSE_FILE \
|
||||
--env UNITY_EMAIL \
|
||||
--env UNITY_PASSWORD \
|
||||
--env UNITY_SERIAL \
|
||||
--env UNITY_LICENSING_SERVER="${unityLicensingServer}" \
|
||||
--env UNITY_VERSION="${editorVersion}" \
|
||||
--env PROJECT_PATH="${projectPath}" \
|
||||
--env CUSTOM_PARAMETERS="${customParameters}" \
|
||||
${ImageEnvironmentFactory.getEnvVarString(parameters)} \
|
||||
--env TEST_PLATFORMS="${testPlatforms}" \
|
||||
--env COVERAGE_OPTIONS="${coverageOptions}" \
|
||||
--env COVERAGE_RESULTS_PATH="CodeCoverage" \
|
||||
--env ARTIFACTS_PATH="${artifactsPath}" \
|
||||
--env PACKAGE_MODE="${packageMode}" \
|
||||
--env PACKAGE_NAME="${packageName}" \
|
||||
--env GITHUB_REF \
|
||||
--env GITHUB_SHA \
|
||||
--env GITHUB_REPOSITORY \
|
||||
--env GITHUB_ACTOR \
|
||||
--env GITHUB_WORKFLOW \
|
||||
--env GITHUB_HEAD_REF \
|
||||
--env GITHUB_BASE_REF \
|
||||
--env GITHUB_EVENT_NAME \
|
||||
--env GITHUB_WORKSPACE="/github/workspace" \
|
||||
--env GITHUB_ACTION \
|
||||
--env GITHUB_EVENT_PATH \
|
||||
--env RUNNER_OS \
|
||||
--env RUNNER_TOOL_CACHE \
|
||||
--env RUNNER_TEMP \
|
||||
--env RUNNER_WORKSPACE \
|
||||
--env GIT_PRIVATE_TOKEN="${gitPrivateToken}" \
|
||||
--env CHOWN_FILES_TO="${chownFilesTo}" \
|
||||
--env GITHUB_WORKSPACE="c:/github/workspace" \
|
||||
${sshAgent ? '--env SSH_AUTH_SOCK=c:/ssh-agent' : ''} \
|
||||
--volume "${actionFolder}/test-standalone-scripts":"c:/UnityStandaloneScripts" \
|
||||
--volume "${githubHome}":"c:/root" \
|
||||
--volume "${githubWorkflow}":"c:/github/workflow" \
|
||||
--volume "${workspace}":"c:/github/workspace" \
|
||||
--volume "${actionFolder}/steps":"c:/steps" \
|
||||
--volume "${actionFolder}":"c:/dist" \
|
||||
--volume "${actionFolder}/platforms/windows":"c:/steps" \
|
||||
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
||||
${sshAgent ? `--volume ${sshAgent}:c:/ssh-agent` : ''} \
|
||||
${
|
||||
sshAgent
|
||||
@@ -235,7 +158,7 @@ const Docker = {
|
||||
${useHostNetwork ? '--net=host' : ''} \
|
||||
${githubToken ? '--env USE_EXIT_CODE=false' : '--env USE_EXIT_CODE=true'} \
|
||||
${image} \
|
||||
powershell c:/dist/entrypoint.ps1`;
|
||||
powershell c:/steps/entrypoint.ps1`;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
80
src/model/image-environment-factory.ts
Normal file
80
src/model/image-environment-factory.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
class ImageEnvironmentFactory {
|
||||
public static getEnvVarString(parameters) {
|
||||
const environmentVariables = ImageEnvironmentFactory.getEnvironmentVariables(parameters);
|
||||
let string = '';
|
||||
for (const p of environmentVariables) {
|
||||
if (p.value === '' || p.value === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (p.name !== 'ANDROID_KEYSTORE_BASE64' && p.value.toString().includes(`\n`)) {
|
||||
string += `--env ${p.name} `;
|
||||
process.env[p.name] = p.value.toString();
|
||||
continue;
|
||||
}
|
||||
|
||||
string += `--env ${p.name}="${p.value}" `;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
public static getEnvironmentVariables(parameters) {
|
||||
let environmentVariables = [
|
||||
{ name: 'UNITY_EMAIL', value: process.env.UNITY_EMAIL },
|
||||
{ name: 'UNITY_PASSWORD', value: process.env.UNITY_PASSWORD },
|
||||
{ name: 'UNITY_SERIAL', value: parameters.unitySerial },
|
||||
{
|
||||
name: 'UNITY_LICENSING_SERVER',
|
||||
value: parameters.unityLicensingServer,
|
||||
},
|
||||
{ name: 'UNITY_VERSION', value: parameters.editorVersion },
|
||||
{
|
||||
name: 'USYM_UPLOAD_AUTH_TOKEN',
|
||||
value: process.env.USYM_UPLOAD_AUTH_TOKEN,
|
||||
},
|
||||
{ name: 'PROJECT_PATH', value: parameters.projectPath },
|
||||
{ name: 'COVERAGE_OPTIONS', value: parameters.coverageOptions },
|
||||
{ name: 'COVERAGE_RESULTS_PATH', value: 'CodeCoverage' },
|
||||
{ name: 'ARTIFACTS_PATH', value: parameters.artifactsPath },
|
||||
{ name: 'PACKAGE_MODE', value: parameters.packageMode },
|
||||
{ name: 'PACKAGE_NAME', value: parameters.packageName },
|
||||
{ name: 'GIT_PRIVATE_TOKEN', value: parameters.gitPrivateToken },
|
||||
{ name: 'VERSION', value: parameters.buildVersion },
|
||||
{ name: 'CUSTOM_PARAMETERS', value: parameters.customParameters },
|
||||
{ name: 'RUN_AS_HOST_USER', value: parameters.runAsHostUser },
|
||||
{ name: 'CHOWN_FILES_TO', value: parameters.chownFilesTo },
|
||||
{ name: 'GITHUB_REF', value: process.env.GITHUB_REF },
|
||||
{ name: 'GITHUB_SHA', value: process.env.GITHUB_SHA },
|
||||
{ name: 'GITHUB_REPOSITORY', value: process.env.GITHUB_REPOSITORY },
|
||||
{ name: 'GITHUB_ACTOR', value: process.env.GITHUB_ACTOR },
|
||||
{ name: 'GITHUB_WORKFLOW', value: process.env.GITHUB_WORKFLOW },
|
||||
{ name: 'GITHUB_HEAD_REF', value: process.env.GITHUB_HEAD_REF },
|
||||
{ name: 'GITHUB_BASE_REF', value: process.env.GITHUB_BASE_REF },
|
||||
{ name: 'GITHUB_EVENT_NAME', value: process.env.GITHUB_EVENT_NAME },
|
||||
{ name: 'GITHUB_ACTION', value: process.env.GITHUB_ACTION },
|
||||
{ name: 'GITHUB_EVENT_PATH', value: process.env.GITHUB_EVENT_PATH },
|
||||
{ name: 'RUNNER_OS', value: process.env.RUNNER_OS },
|
||||
{ name: 'RUNNER_TOOL_CACHE', value: process.env.RUNNER_TOOL_CACHE },
|
||||
{ name: 'RUNNER_TEMP', value: process.env.RUNNER_TEMP },
|
||||
{ name: 'RUNNER_WORKSPACE', value: process.env.RUNNER_WORKSPACE },
|
||||
];
|
||||
|
||||
for (const variable of environmentVariables) {
|
||||
if (
|
||||
environmentVariables.some(
|
||||
x => variable !== undefined && variable.name !== undefined && x.name === variable.name,
|
||||
) === undefined
|
||||
) {
|
||||
environmentVariables = environmentVariables.filter(x => x !== variable);
|
||||
}
|
||||
}
|
||||
|
||||
if (parameters.sshAgent) {
|
||||
environmentVariables.push({ name: 'SSH_AUTH_SOCK', value: '/ssh-agent' });
|
||||
}
|
||||
|
||||
return environmentVariables;
|
||||
}
|
||||
}
|
||||
|
||||
export default ImageEnvironmentFactory;
|
||||
@@ -1,17 +1,15 @@
|
||||
import ImageTag from './image-tag';
|
||||
|
||||
jest.spyOn(ImageTag, 'getImagePlatformPrefix').mockReturnValue('ubuntu');
|
||||
|
||||
describe('ImageTag', () => {
|
||||
const some = {
|
||||
editorVersion: '2099.9.f9f9',
|
||||
targetPlatform: 'Test',
|
||||
builderPlatform: '',
|
||||
containerRegistryRepository: 'unityci/editor',
|
||||
containerRegistryImageVersion: '3',
|
||||
};
|
||||
|
||||
const defaults = {
|
||||
repository: 'unityci',
|
||||
name: 'editor',
|
||||
image: 'unityci/editor',
|
||||
};
|
||||
|
||||
@@ -24,8 +22,7 @@ describe('ImageTag', () => {
|
||||
it('accepts parameters and sets the right properties', () => {
|
||||
const image = new ImageTag(some);
|
||||
|
||||
expect(image.repository).toStrictEqual('unityci');
|
||||
expect(image.name).toStrictEqual('editor');
|
||||
expect(image.repository).toStrictEqual('unityci/editor');
|
||||
expect(image.editorVersion).toStrictEqual(some.editorVersion);
|
||||
expect(image.targetPlatform).toStrictEqual(some.targetPlatform);
|
||||
expect(image.targetPlatformSuffix).toStrictEqual(some.builderPlatform);
|
||||
@@ -48,30 +45,65 @@ describe('ImageTag', () => {
|
||||
const image = new ImageTag({
|
||||
editorVersion: '2099.1.1111',
|
||||
targetPlatform: some.targetPlatform,
|
||||
containerRegistryRepository: 'unityci/editor',
|
||||
containerRegistryImageVersion: '3',
|
||||
});
|
||||
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111-3`);
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111-3`);
|
||||
break;
|
||||
case 'linux':
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111-3`);
|
||||
break;
|
||||
}
|
||||
});
|
||||
it('returns customImage if given', () => {
|
||||
const image = new ImageTag({
|
||||
editorVersion: '2099.1.1111',
|
||||
targetPlatform: some.targetPlatform,
|
||||
customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
|
||||
containerRegistryRepository: 'unityci/editor',
|
||||
containerRegistryImageVersion: '3',
|
||||
});
|
||||
|
||||
expect(image.toString()).toStrictEqual(image.customImage);
|
||||
});
|
||||
|
||||
it('returns the specific build platform', () => {
|
||||
const image = new ImageTag({ editorVersion: '2022.3.7f1', targetPlatform: 'WebGL' });
|
||||
const image = new ImageTag({
|
||||
editorVersion: '2022.3.7f1',
|
||||
targetPlatform: 'WebGL',
|
||||
containerRegistryRepository: 'unityci/editor',
|
||||
containerRegistryImageVersion: '3',
|
||||
});
|
||||
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2022.3.7f1-webgl-3`);
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2022.3.7f1-webgl-3`);
|
||||
break;
|
||||
case 'linux':
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2022.3.7f1-webgl-3`);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
it('returns no specific build platform for generic targetPlatforms', () => {
|
||||
const image = new ImageTag({ targetPlatform: 'NoTarget' });
|
||||
const image = new ImageTag({
|
||||
editorVersion: '2019.2.11f1',
|
||||
targetPlatform: 'NoTarget',
|
||||
containerRegistryRepository: 'unityci/editor',
|
||||
containerRegistryImageVersion: '3',
|
||||
});
|
||||
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2022.3.7f1-3`);
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2019.2.11f1-3`);
|
||||
break;
|
||||
case 'linux':
|
||||
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2019.2.11f1-3`);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@ import Platform from './platform';
|
||||
class ImageTag {
|
||||
public customImage?: string;
|
||||
public repository: string;
|
||||
public name: string;
|
||||
public editorVersion: string;
|
||||
public targetPlatform: string;
|
||||
public targetPlatformSuffix: string;
|
||||
@@ -15,6 +14,8 @@ class ImageTag {
|
||||
editorVersion = '2022.3.7f1',
|
||||
targetPlatform = ImageTag.getImagePlatformType(process.platform),
|
||||
customImage,
|
||||
containerRegistryRepository,
|
||||
containerRegistryImageVersion,
|
||||
} = imageProperties;
|
||||
|
||||
if (!ImageTag.versionPattern.test(editorVersion)) {
|
||||
@@ -25,13 +26,12 @@ class ImageTag {
|
||||
this.customImage = customImage;
|
||||
|
||||
// Or
|
||||
this.repository = 'unityci';
|
||||
this.name = 'editor';
|
||||
this.repository = containerRegistryRepository;
|
||||
this.editorVersion = editorVersion;
|
||||
this.targetPlatform = targetPlatform;
|
||||
this.targetPlatformSuffix = ImageTag.getTargetPlatformSuffix(targetPlatform, editorVersion);
|
||||
this.imagePlatformPrefix = ImageTag.getImagePlatformPrefix(process.platform);
|
||||
this.imageRollingVersion = 3;
|
||||
this.imageRollingVersion = Number(containerRegistryImageVersion);
|
||||
}
|
||||
|
||||
static get versionPattern() {
|
||||
@@ -146,7 +146,7 @@ class ImageTag {
|
||||
}
|
||||
|
||||
get image() {
|
||||
return `${this.repository}/${this.name}`.replace(/^\/+/, '');
|
||||
return `${this.repository}`.replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
||||
@@ -7,6 +7,19 @@ const mockedFsExistsSync = jest.spyOn(fs, 'existsSync');
|
||||
const mockedFsReadFileSync = jest.spyOn(fs, 'readFileSync');
|
||||
|
||||
describe('Input', () => {
|
||||
let originalEnvironment;
|
||||
|
||||
beforeEach(() => {
|
||||
// Store original process.env
|
||||
originalEnvironment = process.env;
|
||||
process.env['UNITY_SERIAL'] = 'F4-1234-1234-1234';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Restore original process.env
|
||||
process.env = originalEnvironment;
|
||||
});
|
||||
|
||||
describe('getFromUser', () => {
|
||||
it('does not throw', () => {
|
||||
expect(() => Input.getFromUser()).not.toThrow();
|
||||
|
||||
@@ -2,28 +2,29 @@ import UnityVersionParser from './unity-version-parser';
|
||||
import fs from 'fs';
|
||||
import { getInput } from '@actions/core';
|
||||
import os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
const Input = {
|
||||
get testModes() {
|
||||
class Input {
|
||||
static get testModes() {
|
||||
return ['all', 'playmode', 'editmode', 'standalone'];
|
||||
},
|
||||
}
|
||||
|
||||
isValidFolderName(folderName) {
|
||||
static isValidFolderName(folderName) {
|
||||
const validFolderName = new RegExp(/^(\.|\.\/)?(\.?[\w~]+([ _-]?[\w~]+)*\/?)*$/);
|
||||
|
||||
return validFolderName.test(folderName);
|
||||
},
|
||||
}
|
||||
|
||||
isValidGlobalFolderName(folderName) {
|
||||
static isValidGlobalFolderName(folderName) {
|
||||
const validFolderName = new RegExp(/^(\.|\.\/|\/)?(\.?[\w~]+([ _-]?[\w~]+)*\/?)*$/);
|
||||
|
||||
return validFolderName.test(folderName);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* When in package mode, we need to scrape the package's name from its package.json file
|
||||
*/
|
||||
getPackageNameFromPackageJson(packagePath) {
|
||||
static getPackageNameFromPackageJson(packagePath) {
|
||||
const packageJsonPath = `${packagePath}/package.json`;
|
||||
if (!fs.existsSync(packageJsonPath)) {
|
||||
throw new Error(`Invalid projectPath - Cannot find package.json at ${packageJsonPath}`);
|
||||
@@ -54,25 +55,40 @@ const Input = {
|
||||
}
|
||||
|
||||
return rawPackageName;
|
||||
},
|
||||
}
|
||||
|
||||
private static getSerialFromLicenseFile(license: string) {
|
||||
const startKey = `<DeveloperData Value="`;
|
||||
const endKey = `"/>`;
|
||||
const startIndex = license.indexOf(startKey) + startKey.length;
|
||||
if (startIndex < 0) {
|
||||
throw new Error(`License File was corrupted, unable to locate serial`);
|
||||
}
|
||||
const endIndex = license.indexOf(endKey, startIndex);
|
||||
|
||||
// Slice off the first 4 characters as they are garbage values
|
||||
return Buffer.from(license.slice(startIndex, endIndex), 'base64').toString('binary').slice(4);
|
||||
}
|
||||
|
||||
/**
|
||||
* When in package mode, we need to ensure that the Tests folder is present
|
||||
*/
|
||||
verifyTestsFolderIsPresent(packagePath) {
|
||||
static verifyTestsFolderIsPresent(packagePath) {
|
||||
if (!fs.existsSync(`${packagePath}/Tests`)) {
|
||||
throw new Error(
|
||||
`Invalid projectPath - Cannot find package tests folder at ${packagePath}/Tests`,
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getFromUser() {
|
||||
public static getFromUser() {
|
||||
// Input variables specified in workflow using "with" prop.
|
||||
const unityVersion = getInput('unityVersion') || 'auto';
|
||||
const customImage = getInput('customImage') || '';
|
||||
const rawProjectPath = getInput('projectPath') || '.';
|
||||
const unityLicensingServer = getInput('unityLicensingServer') || '';
|
||||
const unityLicense = getInput('unityLicense') || (process.env['UNITY_LICENSE'] ?? '');
|
||||
let unitySerial = process.env['UNITY_SERIAL'] ?? '';
|
||||
const customParameters = getInput('customParameters') || '';
|
||||
const testMode = (getInput('testMode') || 'all').toLowerCase();
|
||||
const coverageOptions = getInput('coverageOptions') || '';
|
||||
@@ -105,6 +121,10 @@ const Input = {
|
||||
`${Math.floor((os.totalmem() / bytesInMegabyte) * memoryMultiplier)}m`;
|
||||
const dockerIsolationMode = getInput('dockerIsolationMode') || 'default';
|
||||
|
||||
const runAsHostUser = getInput('runAsHostUser') || 'false';
|
||||
const containerRegistryRepository = getInput('containerRegistryRepository') || 'unityci/editor';
|
||||
const containerRegistryImageVersion = getInput('containerRegistryImageVersion') || '3';
|
||||
|
||||
// Validate input
|
||||
if (!this.testModes.includes(testMode)) {
|
||||
throw new Error(`Invalid testMode ${testMode}`);
|
||||
@@ -153,6 +173,28 @@ const Input = {
|
||||
this.verifyTestsFolderIsPresent(projectPath);
|
||||
}
|
||||
|
||||
if (runAsHostUser !== 'true' && runAsHostUser !== 'false') {
|
||||
throw new Error(`Invalid runAsHostUser "${runAsHostUser}"`);
|
||||
}
|
||||
|
||||
if (unityLicensingServer === '' && !unitySerial) {
|
||||
// No serial was present, so it is a personal license that we need to convert
|
||||
if (!unityLicense) {
|
||||
throw new Error(
|
||||
`Missing Unity License File and no Serial was found. If this
|
||||
is a personal license, make sure to follow the activation
|
||||
steps and set the UNITY_LICENSE GitHub secret or enter a Unity
|
||||
serial number inside the UNITY_SERIAL GitHub secret.`,
|
||||
);
|
||||
}
|
||||
unitySerial = this.getSerialFromLicenseFile(unityLicense);
|
||||
}
|
||||
|
||||
if (unitySerial !== undefined && unitySerial.length === 27) {
|
||||
core.setSecret(unitySerial);
|
||||
core.setSecret(`${unitySerial.slice(0, -4)}XXXX`);
|
||||
}
|
||||
|
||||
// Sanitise other input
|
||||
const artifactsPath = rawArtifactsPath.replace(/\/$/, '');
|
||||
const sshPublicKeysDirectoryPath = rawSshPublicKeysDirectoryPath.replace(/\/$/, '');
|
||||
@@ -182,8 +224,12 @@ const Input = {
|
||||
dockerMemoryLimit,
|
||||
dockerIsolationMode,
|
||||
unityLicensingServer,
|
||||
runAsHostUser,
|
||||
containerRegistryRepository,
|
||||
containerRegistryImageVersion,
|
||||
unitySerial,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default Input;
|
||||
|
||||
Reference in New Issue
Block a user