Merge remote-tracking branch 'origin/main' into feature/add_support_for_licensing_server

# Conflicts:
#	dist/index.js
#	dist/index.js.map
#	src/index.ts
#	src/model/docker.ts
pull/196/head
Simen Sandvaer 2022-11-04 09:26:25 +01:00
commit 903f42b01a
11 changed files with 299 additions and 69 deletions

View File

@ -62,4 +62,5 @@ branding:
color: 'gray-dark'
runs:
using: 'node16'
main: 'dist/index.js'
main: 'dist/main.js'
post: 'dist/post.js'

156
dist/index.js generated vendored
View File

@ -6,6 +6,57 @@ require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const main_1 = __nccwpck_require__(3109);
const path_1 = __importDefault(__nccwpck_require__(1017));
const post_1 = __nccwpck_require__(95);
/*
* GitHub Action can provide multiple executable entrypoints (pre, main, post),
* but it is complicated process to generate multiple `.js` files with `ncc`.
* So we rather generate just one entrypoint, that is symlinked to multiple locations (main.js and post.js).
* Then when GitHub Action Runner executes it as `node path/to/main.js` and `node path/to/post.js`,
* it can read arguments it was executed with and decide which file to execute.
* The argv[0] is going to be a full path to `node` executable and
* the argv[1] is going to be the full path to the script.
* In case index.js would be marked executable and executed directly without the argv[1] it defaults to "main.js".
*/
function run([, name = 'main.js']) {
return __awaiter(this, void 0, void 0, function* () {
const script = path_1.default.basename(name);
switch (script) {
case 'main.js':
yield (0, main_1.run)();
break;
case 'post.js':
yield (0, post_1.run)();
break;
default:
throw new Error(`Unknown script argument: '${script}'`);
}
});
}
run(process.argv);
/***/ }),
/***/ 3109:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
@ -35,6 +86,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.run = void 0;
const core = __importStar(__nccwpck_require__(2186));
const model_1 = __nccwpck_require__(1359);
function run() {
@ -44,10 +96,9 @@ function run() {
const { workspace, actionFolder } = model_1.Action;
const { editorVersion, customImage, projectPath, customParameters, testMode, coverageOptions, artifactsPath, useHostNetwork, sshAgent, gitPrivateToken, githubToken, checkName, chownFilesTo, unityLicensingServer, } = model_1.Input.getFromUser();
const baseImage = new model_1.ImageTag({ editorVersion, customImage });
const runnerTemporaryPath = process.env.RUNNER_TEMP;
const runnerContext = model_1.Action.runnerContext();
try {
yield model_1.Docker.run(baseImage, {
actionFolder,
yield model_1.Docker.run(baseImage, Object.assign({ actionFolder,
editorVersion,
workspace,
projectPath,
@ -59,10 +110,8 @@ function run() {
sshAgent,
gitPrivateToken,
githubToken,
runnerTemporaryPath,
chownFilesTo,
unityLicensingServer,
});
unityLicensingServer }, runnerContext));
}
finally {
yield model_1.Output.setArtifactsPath(artifactsPath);
@ -80,7 +129,7 @@ function run() {
}
});
}
run();
exports.run = run;
/***/ }),
@ -120,6 +169,15 @@ const Action = {
get workspace() {
return process.env.GITHUB_WORKSPACE;
},
runnerContext() {
var _a, _b;
const runnerTemporaryPath = (_a = process.env.RUNNER_TEMP) !== null && _a !== void 0 ? _a : process.cwd();
const githubAction = (_b = process.env.GITHUB_ACTION) !== null && _b !== void 0 ? _b : process.pid.toString();
return {
runnerTemporaryPath,
githubAction,
};
},
checkCompatibility() {
const currentPlatform = process.platform;
if (!Action.supportedPlatforms.includes(currentPlatform)) {
@ -154,7 +212,30 @@ const fs_1 = __nccwpck_require__(7147);
const licensing_server_setup_1 = __importDefault(__nccwpck_require__(6089));
const exec_1 = __nccwpck_require__(1514);
const path_1 = __importDefault(__nccwpck_require__(1017));
/**
* Build a path for a docker --cidfile parameter. Docker will store the the created container.
* This path is stable for the whole execution of the action, so it can be executed with the same parameters
* multiple times and get the same result.
*/
const containerIdFilePath = parameters => {
const { runnerTemporaryPath, githubAction } = parameters;
return path_1.default.join(runnerTemporaryPath, `container_${githubAction}`);
};
const Docker = {
/**
* Remove a possible leftover container created by `Docker.run`.
*/
ensureContainerRemoval(parameters) {
return __awaiter(this, void 0, void 0, function* () {
const cidfile = containerIdFilePath(parameters);
if (!(0, fs_1.existsSync)(cidfile)) {
return;
}
const container = (0, fs_1.readFileSync)(cidfile, 'ascii').trim();
yield (0, exec_1.exec)(`docker`, ['rm', '--force', '--volumes', container], { silent: true });
(0, fs_1.rmSync)(cidfile);
});
},
run(image, parameters, silent = false) {
return __awaiter(this, void 0, void 0, function* () {
let runCommand = '';
@ -182,9 +263,11 @@ const Docker = {
const githubWorkflow = path_1.default.join(runnerTemporaryPath, '_github_workflow');
if (!(0, fs_1.existsSync)(githubWorkflow))
(0, fs_1.mkdirSync)(githubWorkflow);
const cidfile = containerIdFilePath(parameters);
const testPlatforms = (testMode === 'all' ? ['playmode', 'editmode', 'COMBINE_RESULTS'] : [testMode]).join(';');
return `docker run \
--workdir /github/workspace \
--cidfile "${cidfile}" \
--rm \
--env UNITY_LICENSE \
--env UNITY_LICENSE_FILE \
@ -235,12 +318,14 @@ const Docker = {
const githubHome = path_1.default.join(runnerTemporaryPath, '_github_home');
if (!(0, fs_1.existsSync)(githubHome))
(0, fs_1.mkdirSync)(githubHome);
const cidfile = containerIdFilePath(parameters);
const githubWorkflow = path_1.default.join(runnerTemporaryPath, '_github_workflow');
if (!(0, fs_1.existsSync)(githubWorkflow))
(0, fs_1.mkdirSync)(githubWorkflow);
const testPlatforms = (testMode === 'all' ? ['playmode', 'editmode', 'COMBINE_RESULTS'] : [testMode]).join(';');
return `docker run \
--workdir /github/workspace \
--cidfile "${cidfile}" \
--rm \
--env UNITY_LICENSE \
--env UNITY_LICENSE_FILE \
@ -1156,6 +1241,63 @@ const UnityVersionParser = {
exports["default"] = UnityVersionParser;
/***/ }),
/***/ 95:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.run = void 0;
const core = __importStar(__nccwpck_require__(2186));
const action_1 = __importDefault(__nccwpck_require__(9088));
const model_1 = __nccwpck_require__(1359);
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const parameters = action_1.default.runnerContext();
yield model_1.Docker.ensureContainerRemoval(parameters);
}
catch (error) {
core.setFailed(error.message);
}
});
}
exports.run = run;
/***/ }),
/***/ 7351:

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

1
dist/main.js vendored 120000
View File

@ -0,0 +1 @@
index.js

1
dist/post.js vendored 120000
View File

@ -0,0 +1 @@
index.js

View File

@ -8,8 +8,8 @@
"license": "MIT",
"scripts": {
"prebuild": "yarn",
"build": "tsc && ncc build lib --source-map --license licenses.txt",
"lint": "prettier --check \"src/**/*.{js,ts}\" && eslint src/**/*.ts",
"build": "tsc && ncc build lib/index.js --source-map --license licenses.txt",
"lint": "prettier --check \"src/**/*.{js,ts}\" && eslint src --ext .js,.ts --max-warnings=0",
"format": "prettier --write \"src/**/*.{js,ts}\"",
"test": "jest",
"prepare": "husky install"

View File

@ -1,62 +1,30 @@
import * as core from '@actions/core';
import { Action, Docker, ImageTag, Input, Output, ResultsCheck } from './model';
import { run as main } from './main';
import path from 'path';
import { run as post } from './post';
async function run() {
try {
Action.checkCompatibility();
/*
* GitHub Action can provide multiple executable entrypoints (pre, main, post),
* but it is complicated process to generate multiple `.js` files with `ncc`.
* So we rather generate just one entrypoint, that is symlinked to multiple locations (main.js and post.js).
* Then when GitHub Action Runner executes it as `node path/to/main.js` and `node path/to/post.js`,
* it can read arguments it was executed with and decide which file to execute.
* The argv[0] is going to be a full path to `node` executable and
* the argv[1] is going to be the full path to the script.
* In case index.js would be marked executable and executed directly without the argv[1] it defaults to "main.js".
*/
async function run([, name = 'main.js']: string[]) {
const script = path.basename(name);
const { workspace, actionFolder } = Action;
const {
editorVersion,
customImage,
projectPath,
customParameters,
testMode,
coverageOptions,
artifactsPath,
useHostNetwork,
sshAgent,
gitPrivateToken,
githubToken,
checkName,
chownFilesTo,
unityLicensingServer,
} = Input.getFromUser();
const baseImage = new ImageTag({ editorVersion, customImage });
const runnerTemporaryPath = process.env.RUNNER_TEMP;
try {
await Docker.run(baseImage, {
actionFolder,
editorVersion,
workspace,
projectPath,
customParameters,
testMode,
coverageOptions,
artifactsPath,
useHostNetwork,
sshAgent,
gitPrivateToken,
githubToken,
runnerTemporaryPath,
chownFilesTo,
unityLicensingServer,
});
} finally {
await Output.setArtifactsPath(artifactsPath);
await Output.setCoveragePath('CodeCoverage');
}
if (githubToken) {
const failedTestCount = await ResultsCheck.createCheck(artifactsPath, githubToken, checkName);
if (failedTestCount >= 1) {
core.setFailed(`Test(s) Failed! Check '${checkName}' for details.`);
}
}
} catch (error: any) {
core.setFailed(error.message);
switch (script) {
case 'main.js':
await main();
break;
case 'post.js':
await post();
break;
default:
throw new Error(`Unknown script argument: '${script}'`);
}
}
run();
run(process.argv);

60
src/main.ts 100644
View File

@ -0,0 +1,60 @@
import * as core from '@actions/core';
import { Action, Docker, ImageTag, Input, Output, ResultsCheck } from './model';
export async function run() {
try {
Action.checkCompatibility();
const { workspace, actionFolder } = Action;
const {
editorVersion,
customImage,
projectPath,
customParameters,
testMode,
coverageOptions,
artifactsPath,
useHostNetwork,
sshAgent,
gitPrivateToken,
githubToken,
checkName,
chownFilesTo,
unityLicensingServer,
} = Input.getFromUser();
const baseImage = new ImageTag({ editorVersion, customImage });
const runnerContext = Action.runnerContext();
try {
await Docker.run(baseImage, {
actionFolder,
editorVersion,
workspace,
projectPath,
customParameters,
testMode,
coverageOptions,
artifactsPath,
useHostNetwork,
sshAgent,
gitPrivateToken,
githubToken,
chownFilesTo,
unityLicensingServer,
...runnerContext,
});
} finally {
await Output.setArtifactsPath(artifactsPath);
await Output.setCoveragePath('CodeCoverage');
}
if (githubToken) {
const failedTestCount = await ResultsCheck.createCheck(artifactsPath, githubToken, checkName);
if (failedTestCount >= 1) {
core.setFailed(`Test(s) Failed! Check '${checkName}' for details.`);
}
}
} catch (error: any) {
core.setFailed(error.message);
}
}

View File

@ -1,5 +1,10 @@
import path from 'path';
export interface RunnerContext {
runnerTemporaryPath: string;
githubAction: string;
}
const Action = {
get supportedPlatforms() {
return ['linux', 'win32'];
@ -33,6 +38,16 @@ const Action = {
return process.env.GITHUB_WORKSPACE;
},
runnerContext(): RunnerContext {
const runnerTemporaryPath = process.env.RUNNER_TEMP ?? process.cwd();
const githubAction = process.env.GITHUB_ACTION ?? process.pid.toString();
return {
runnerTemporaryPath,
githubAction,
};
},
checkCompatibility() {
const currentPlatform = process.platform;
if (!Action.supportedPlatforms.includes(currentPlatform)) {

View File

@ -1,9 +1,34 @@
import { existsSync, mkdirSync } from 'fs';
import { existsSync, mkdirSync, readFileSync, rmSync } from 'fs';
import LicensingServerSetup from './licensing-server-setup';
import type { RunnerContext } from './action';
import { exec } from '@actions/exec';
import path from 'path';
/**
* Build a path for a docker --cidfile parameter. Docker will store the the created container.
* This path is stable for the whole execution of the action, so it can be executed with the same parameters
* multiple times and get the same result.
*/
const containerIdFilePath = parameters => {
const { runnerTemporaryPath, githubAction } = parameters;
return path.join(runnerTemporaryPath, `container_${githubAction}`);
};
const Docker = {
/**
* Remove a possible leftover container created by `Docker.run`.
*/
async ensureContainerRemoval(parameters: RunnerContext) {
const cidfile = containerIdFilePath(parameters);
if (!existsSync(cidfile)) {
return;
}
const container = readFileSync(cidfile, 'ascii').trim();
await exec(`docker`, ['rm', '--force', '--volumes', container], { silent: true });
rmSync(cidfile);
},
async run(image, parameters, silent = false) {
let runCommand = '';
@ -21,6 +46,7 @@ const Docker = {
default:
throw new Error(`Operation system, ${process.platform}, is not supported yet.`);
}
await exec(runCommand, undefined, { silent });
},
@ -47,12 +73,14 @@ const Docker = {
if (!existsSync(githubHome)) mkdirSync(githubHome);
const githubWorkflow = path.join(runnerTemporaryPath, '_github_workflow');
if (!existsSync(githubWorkflow)) mkdirSync(githubWorkflow);
const cidfile = containerIdFilePath(parameters);
const testPlatforms = (
testMode === 'all' ? ['playmode', 'editmode', 'COMBINE_RESULTS'] : [testMode]
).join(';');
return `docker run \
--workdir /github/workspace \
--cidfile "${cidfile}" \
--rm \
--env UNITY_LICENSE \
--env UNITY_LICENSE_FILE \
@ -122,6 +150,7 @@ const Docker = {
const githubHome = path.join(runnerTemporaryPath, '_github_home');
if (!existsSync(githubHome)) mkdirSync(githubHome);
const cidfile = containerIdFilePath(parameters);
const githubWorkflow = path.join(runnerTemporaryPath, '_github_workflow');
if (!existsSync(githubWorkflow)) mkdirSync(githubWorkflow);
const testPlatforms = (
@ -130,6 +159,7 @@ const Docker = {
return `docker run \
--workdir /github/workspace \
--cidfile "${cidfile}" \
--rm \
--env UNITY_LICENSE \
--env UNITY_LICENSE_FILE \

12
src/post.ts 100644
View File

@ -0,0 +1,12 @@
import * as core from '@actions/core';
import Action from './model/action';
import { Docker } from './model';
export async function run() {
try {
const parameters = Action.runnerContext();
await Docker.ensureContainerRemoval(parameters);
} catch (error: any) {
core.setFailed(error.message);
}
}