mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-05-31 13:56:13 -07:00
fix(testing): use async exec for parallel test group execution
Replace execSync with promisified exec so Promise.all actually runs test groups in parallel. Add native timeout support via exec options. Add 50MB maxBuffer for large Unity output. Fix ESLint violations (variable naming, padding lines, array push consolidation). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
100
dist/index.js
generated
vendored
100
dist/index.js
generated
vendored
@@ -10416,11 +10416,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.TestWorkflowService = void 0;
|
||||
const node_child_process_1 = __nccwpck_require__(17718);
|
||||
const node_util_1 = __nccwpck_require__(47261);
|
||||
const node_path_1 = __importDefault(__nccwpck_require__(49411));
|
||||
const core = __importStar(__nccwpck_require__(42186));
|
||||
const test_suite_parser_1 = __nccwpck_require__(92105);
|
||||
const taxonomy_filter_service_1 = __nccwpck_require__(9983);
|
||||
const test_result_reporter_1 = __nccwpck_require__(25147);
|
||||
const execAsync = (0, node_util_1.promisify)(node_child_process_1.exec);
|
||||
/**
|
||||
* Main entry point for the test workflow engine.
|
||||
* Orchestrates parsing of YAML suite definitions, resolving run order,
|
||||
@@ -10433,7 +10435,7 @@ class TestWorkflowService {
|
||||
* group sequentially (runs within a group execute concurrently), and
|
||||
* collects all results.
|
||||
*/
|
||||
static async executeTestSuite(suitePath, params) {
|
||||
static async executeTestSuite(suitePath, parameters) {
|
||||
core.info(`[TestWorkflow] Loading test suite from: ${suitePath}`);
|
||||
const suite = test_suite_parser_1.TestSuiteParser.parseSuiteFile(suitePath);
|
||||
core.info(`[TestWorkflow] Suite '${suite.name}' loaded with ${suite.runs.length} run(s)`);
|
||||
@@ -10449,7 +10451,7 @@ class TestWorkflowService {
|
||||
const runNames = group.map((r) => r.name).join(', ');
|
||||
core.info(`[TestWorkflow] Executing group ${groupIndex}/${groups.length}: [${runNames}]`);
|
||||
// Execute runs within a group concurrently
|
||||
const groupResults = await Promise.all(group.map((run) => TestWorkflowService.executeTestRun(run, params)));
|
||||
const groupResults = await Promise.all(group.map((run) => TestWorkflowService.executeTestRun(run, parameters)));
|
||||
allResults.push(...groupResults);
|
||||
// Check for failures -- if any run in this group failed, log a warning
|
||||
// but continue to the next group (fail-forward for maximum feedback)
|
||||
@@ -10463,8 +10465,8 @@ class TestWorkflowService {
|
||||
const summary = test_result_reporter_1.TestResultReporter.generateSummary(allResults);
|
||||
core.info(summary);
|
||||
// Write results if output path is configured
|
||||
const resultPath = params.testResultPath;
|
||||
const resultFormat = params.testResultFormat;
|
||||
const resultPath = parameters.testResultPath;
|
||||
const resultFormat = parameters.testResultFormat;
|
||||
if (resultPath) {
|
||||
test_result_reporter_1.TestResultReporter.writeResults(allResults, resultPath, resultFormat);
|
||||
core.info(`[TestWorkflow] Results written to: ${resultPath}`);
|
||||
@@ -10474,27 +10476,30 @@ class TestWorkflowService {
|
||||
/**
|
||||
* Execute a single test run definition.
|
||||
* Builds the Unity CLI arguments based on the run configuration (edit mode,
|
||||
* play mode, built client) and taxonomy filters, executes the command, and
|
||||
* parses the result output.
|
||||
* play mode, built client) and taxonomy filters, executes the command
|
||||
* asynchronously, and parses the result output.
|
||||
*
|
||||
* Uses promisified exec instead of execSync so that Promise.all can
|
||||
* actually run multiple test groups in parallel without blocking the
|
||||
* Node.js event loop.
|
||||
*/
|
||||
static async executeTestRun(run, params) {
|
||||
static async executeTestRun(run, parameters) {
|
||||
core.info(`[TestWorkflow] Starting run: '${run.name}'`);
|
||||
const args = TestWorkflowService.buildUnityArgs(run, params);
|
||||
const unityArguments = TestWorkflowService.buildUnityArgs(run, parameters);
|
||||
const timeoutMs = (run.timeout ?? 600) * 1000;
|
||||
core.info(`[TestWorkflow] Unity args: ${args}`);
|
||||
core.info(`[TestWorkflow] Unity args: ${unityArguments}`);
|
||||
const startTime = Date.now();
|
||||
try {
|
||||
const resultDir = node_path_1.default.join(params.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = node_path_1.default.join(resultDir, 'results.xml');
|
||||
const resultDirectory = node_path_1.default.join(parameters.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = node_path_1.default.join(resultDirectory, 'results.xml');
|
||||
// Build the full Unity command
|
||||
const unityPath = TestWorkflowService.resolveUnityPath(params);
|
||||
const command = `"${unityPath}" ${args} -testResults "${resultFile}"`;
|
||||
const unityPath = TestWorkflowService.resolveUnityPath(parameters);
|
||||
const command = `"${unityPath}" ${unityArguments} -testResults "${resultFile}"`;
|
||||
core.info(`[TestWorkflow] Executing: ${command}`);
|
||||
(0, node_child_process_1.execSync)(command, {
|
||||
await execAsync(command, {
|
||||
timeout: timeoutMs,
|
||||
stdio: 'pipe',
|
||||
encoding: 'utf8',
|
||||
cwd: params.projectPath || process.cwd(),
|
||||
maxBuffer: 50 * 1024 * 1024,
|
||||
cwd: parameters.projectPath || process.cwd(),
|
||||
});
|
||||
const duration = (Date.now() - startTime) / 1000;
|
||||
// Parse the result file
|
||||
@@ -10519,16 +10524,18 @@ class TestWorkflowService {
|
||||
}
|
||||
catch (error) {
|
||||
const duration = (Date.now() - startTime) / 1000;
|
||||
const isTimeout = error.killed || error.signal === 'SIGTERM';
|
||||
// The promisified exec sets error.killed when the process is terminated
|
||||
// due to timeout, and error.signal will be 'SIGTERM'
|
||||
const isTimeout = error.killed === true || error.signal === 'SIGTERM';
|
||||
if (isTimeout) {
|
||||
core.error(`[TestWorkflow] Run '${run.name}' timed out after ${run.timeout}s`);
|
||||
core.error(`[TestWorkflow] Run '${run.name}' timed out after ${run.timeout ?? 600}s`);
|
||||
}
|
||||
else {
|
||||
core.error(`[TestWorkflow] Run '${run.name}' failed: ${error.message}`);
|
||||
}
|
||||
// Try to parse partial results even on failure
|
||||
const resultDir = node_path_1.default.join(params.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = node_path_1.default.join(resultDir, 'results.xml');
|
||||
const resultDirectory = node_path_1.default.join(parameters.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = node_path_1.default.join(resultDirectory, 'results.xml');
|
||||
try {
|
||||
const result = test_result_reporter_1.TestResultReporter.parseJUnitResults(resultFile);
|
||||
result.runName = run.name;
|
||||
@@ -10547,7 +10554,7 @@ class TestWorkflowService {
|
||||
testName: isTimeout ? 'Timeout' : 'ExecutionError',
|
||||
className: run.name,
|
||||
message: isTimeout
|
||||
? `Test run timed out after ${run.timeout}s`
|
||||
? `Test run timed out after ${run.timeout ?? 600}s`
|
||||
: error.message ?? 'Unknown execution error',
|
||||
stackTrace: error.stderr ?? undefined,
|
||||
},
|
||||
@@ -10559,65 +10566,56 @@ class TestWorkflowService {
|
||||
/**
|
||||
* Build Unity CLI arguments for a test run based on its configuration.
|
||||
*/
|
||||
static buildUnityArgs(run, params) {
|
||||
const args = [];
|
||||
// Batch mode and no-graphics for CI
|
||||
args.push('-batchmode');
|
||||
args.push('-nographics');
|
||||
static buildUnityArgs(run, parameters) {
|
||||
const unityArguments = ['-batchmode', '-nographics'];
|
||||
// Project path
|
||||
if (params.projectPath) {
|
||||
args.push(`-projectPath "${params.projectPath}"`);
|
||||
if (parameters.projectPath) {
|
||||
unityArguments.push(`-projectPath "${parameters.projectPath}"`);
|
||||
}
|
||||
// Test mode
|
||||
if (run.builtClient && run.builtClientPath) {
|
||||
// Built client testing: run tests against a built player
|
||||
args.push('-runTests');
|
||||
args.push(`-testPlatform StandalonePlayer`);
|
||||
args.push(`-assemblyNames Assembly-CSharp-Tests`);
|
||||
args.push(`-builtPlayerPath "${run.builtClientPath}"`);
|
||||
unityArguments.push('-runTests', `-testPlatform StandalonePlayer`, `-assemblyNames Assembly-CSharp-Tests`, `-builtPlayerPath "${run.builtClientPath}"`);
|
||||
}
|
||||
else if (run.editMode && run.playMode) {
|
||||
// Both modes: run EditMode first, then PlayMode will require a separate invocation
|
||||
// For combined mode, use EditMode (the service handles sequencing)
|
||||
args.push('-runTests');
|
||||
args.push('-testPlatform EditMode');
|
||||
unityArguments.push('-runTests', '-testPlatform EditMode');
|
||||
}
|
||||
else if (run.playMode) {
|
||||
args.push('-runTests');
|
||||
args.push('-testPlatform PlayMode');
|
||||
unityArguments.push('-runTests', '-testPlatform PlayMode');
|
||||
}
|
||||
else if (run.editMode) {
|
||||
args.push('-runTests');
|
||||
args.push('-testPlatform EditMode');
|
||||
unityArguments.push('-runTests', '-testPlatform EditMode');
|
||||
}
|
||||
// Apply taxonomy filters
|
||||
if (run.filters && Object.keys(run.filters).length > 0) {
|
||||
const filterArgs = taxonomy_filter_service_1.TaxonomyFilterService.buildFilterArgs(run.filters);
|
||||
if (filterArgs) {
|
||||
args.push(filterArgs);
|
||||
const filterArguments = taxonomy_filter_service_1.TaxonomyFilterService.buildFilterArgs(run.filters);
|
||||
if (filterArguments) {
|
||||
unityArguments.push(filterArguments);
|
||||
}
|
||||
}
|
||||
// Target platform
|
||||
if (params.targetPlatform) {
|
||||
args.push(`-buildTarget ${params.targetPlatform}`);
|
||||
if (parameters.targetPlatform) {
|
||||
unityArguments.push(`-buildTarget ${parameters.targetPlatform}`);
|
||||
}
|
||||
return args.join(' ');
|
||||
return unityArguments.join(' ');
|
||||
}
|
||||
/**
|
||||
* Resolve the path to the Unity editor executable.
|
||||
*/
|
||||
static resolveUnityPath(params) {
|
||||
static resolveUnityPath(parameters) {
|
||||
// In CI, Unity path is typically set via environment or the docker container
|
||||
const envUnityPath = process.env.UNITY_PATH ?? process.env.UNITY_EDITOR;
|
||||
if (envUnityPath) {
|
||||
return envUnityPath;
|
||||
const environmentUnityPath = process.env.UNITY_PATH ?? process.env.UNITY_EDITOR;
|
||||
if (environmentUnityPath) {
|
||||
return environmentUnityPath;
|
||||
}
|
||||
// Default paths by platform
|
||||
if (process.platform === 'win32') {
|
||||
return `C:/Program Files/Unity/Hub/Editor/${params.editorVersion}/Editor/Unity.exe`;
|
||||
return `C:/Program Files/Unity/Hub/Editor/${parameters.editorVersion}/Editor/Unity.exe`;
|
||||
}
|
||||
if (process.platform === 'darwin') {
|
||||
return `/Applications/Unity/Hub/Editor/${params.editorVersion}/Unity.app/Contents/MacOS/Unity`;
|
||||
return `/Applications/Unity/Hub/Editor/${parameters.editorVersion}/Unity.app/Contents/MacOS/Unity`;
|
||||
}
|
||||
// Linux default (Docker container path)
|
||||
return '/opt/unity/Editor/Unity';
|
||||
|
||||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
||||
import { execSync } from 'node:child_process';
|
||||
import { exec } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import path from 'node:path';
|
||||
import * as core from '@actions/core';
|
||||
import BuildParameters from '../../../build-parameters';
|
||||
@@ -7,6 +8,8 @@ import { TaxonomyFilterService } from './taxonomy-filter-service';
|
||||
import { TestResultReporter } from './test-result-reporter';
|
||||
import { TestRunDefinition, TestResult } from './test-workflow-types';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
/**
|
||||
* Main entry point for the test workflow engine.
|
||||
* Orchestrates parsing of YAML suite definitions, resolving run order,
|
||||
@@ -19,7 +22,7 @@ export class TestWorkflowService {
|
||||
* group sequentially (runs within a group execute concurrently), and
|
||||
* collects all results.
|
||||
*/
|
||||
static async executeTestSuite(suitePath: string, params: BuildParameters): Promise<TestResult[]> {
|
||||
static async executeTestSuite(suitePath: string, parameters: BuildParameters): Promise<TestResult[]> {
|
||||
core.info(`[TestWorkflow] Loading test suite from: ${suitePath}`);
|
||||
|
||||
const suite = TestSuiteParser.parseSuiteFile(suitePath);
|
||||
@@ -41,7 +44,7 @@ export class TestWorkflowService {
|
||||
core.info(`[TestWorkflow] Executing group ${groupIndex}/${groups.length}: [${runNames}]`);
|
||||
|
||||
// Execute runs within a group concurrently
|
||||
const groupResults = await Promise.all(group.map((run) => TestWorkflowService.executeTestRun(run, params)));
|
||||
const groupResults = await Promise.all(group.map((run) => TestWorkflowService.executeTestRun(run, parameters)));
|
||||
|
||||
allResults.push(...groupResults);
|
||||
|
||||
@@ -59,8 +62,8 @@ export class TestWorkflowService {
|
||||
core.info(summary);
|
||||
|
||||
// Write results if output path is configured
|
||||
const resultPath = params.testResultPath;
|
||||
const resultFormat = params.testResultFormat;
|
||||
const resultPath = parameters.testResultPath;
|
||||
const resultFormat = parameters.testResultFormat;
|
||||
if (resultPath) {
|
||||
TestResultReporter.writeResults(allResults, resultPath, resultFormat as 'junit' | 'json' | 'both');
|
||||
core.info(`[TestWorkflow] Results written to: ${resultPath}`);
|
||||
@@ -72,34 +75,37 @@ export class TestWorkflowService {
|
||||
/**
|
||||
* Execute a single test run definition.
|
||||
* Builds the Unity CLI arguments based on the run configuration (edit mode,
|
||||
* play mode, built client) and taxonomy filters, executes the command, and
|
||||
* parses the result output.
|
||||
* play mode, built client) and taxonomy filters, executes the command
|
||||
* asynchronously, and parses the result output.
|
||||
*
|
||||
* Uses promisified exec instead of execSync so that Promise.all can
|
||||
* actually run multiple test groups in parallel without blocking the
|
||||
* Node.js event loop.
|
||||
*/
|
||||
static async executeTestRun(run: TestRunDefinition, params: BuildParameters): Promise<TestResult> {
|
||||
static async executeTestRun(run: TestRunDefinition, parameters: BuildParameters): Promise<TestResult> {
|
||||
core.info(`[TestWorkflow] Starting run: '${run.name}'`);
|
||||
|
||||
const args = TestWorkflowService.buildUnityArgs(run, params);
|
||||
const unityArguments = TestWorkflowService.buildUnityArgs(run, parameters);
|
||||
const timeoutMs = (run.timeout ?? 600) * 1000;
|
||||
|
||||
core.info(`[TestWorkflow] Unity args: ${args}`);
|
||||
core.info(`[TestWorkflow] Unity args: ${unityArguments}`);
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const resultDir = path.join(params.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = path.join(resultDir, 'results.xml');
|
||||
const resultDirectory = path.join(parameters.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = path.join(resultDirectory, 'results.xml');
|
||||
|
||||
// Build the full Unity command
|
||||
const unityPath = TestWorkflowService.resolveUnityPath(params);
|
||||
const command = `"${unityPath}" ${args} -testResults "${resultFile}"`;
|
||||
const unityPath = TestWorkflowService.resolveUnityPath(parameters);
|
||||
const command = `"${unityPath}" ${unityArguments} -testResults "${resultFile}"`;
|
||||
|
||||
core.info(`[TestWorkflow] Executing: ${command}`);
|
||||
|
||||
execSync(command, {
|
||||
await execAsync(command, {
|
||||
timeout: timeoutMs,
|
||||
stdio: 'pipe',
|
||||
encoding: 'utf8',
|
||||
cwd: params.projectPath || process.cwd(),
|
||||
maxBuffer: 50 * 1024 * 1024, // 50 MB to handle large Unity output
|
||||
cwd: parameters.projectPath || process.cwd(),
|
||||
});
|
||||
|
||||
const duration = (Date.now() - startTime) / 1000;
|
||||
@@ -109,10 +115,12 @@ export class TestWorkflowService {
|
||||
const result = TestResultReporter.parseJUnitResults(resultFile);
|
||||
result.runName = run.name;
|
||||
result.duration = duration;
|
||||
|
||||
return result;
|
||||
} catch {
|
||||
// Result file may not exist if Unity exited early
|
||||
core.warning(`[TestWorkflow] Could not parse results for run '${run.name}' -- result file may be missing`);
|
||||
|
||||
return {
|
||||
runName: run.name,
|
||||
passed: 0,
|
||||
@@ -124,22 +132,26 @@ export class TestWorkflowService {
|
||||
}
|
||||
} catch (error: any) {
|
||||
const duration = (Date.now() - startTime) / 1000;
|
||||
const isTimeout = error.killed || error.signal === 'SIGTERM';
|
||||
|
||||
// The promisified exec sets error.killed when the process is terminated
|
||||
// due to timeout, and error.signal will be 'SIGTERM'
|
||||
const isTimeout = error.killed === true || error.signal === 'SIGTERM';
|
||||
|
||||
if (isTimeout) {
|
||||
core.error(`[TestWorkflow] Run '${run.name}' timed out after ${run.timeout}s`);
|
||||
core.error(`[TestWorkflow] Run '${run.name}' timed out after ${run.timeout ?? 600}s`);
|
||||
} else {
|
||||
core.error(`[TestWorkflow] Run '${run.name}' failed: ${error.message}`);
|
||||
}
|
||||
|
||||
// Try to parse partial results even on failure
|
||||
const resultDir = path.join(params.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = path.join(resultDir, 'results.xml');
|
||||
const resultDirectory = path.join(parameters.testResultPath ?? './test-results', run.name);
|
||||
const resultFile = path.join(resultDirectory, 'results.xml');
|
||||
|
||||
try {
|
||||
const result = TestResultReporter.parseJUnitResults(resultFile);
|
||||
result.runName = run.name;
|
||||
result.duration = duration;
|
||||
|
||||
return result;
|
||||
} catch {
|
||||
return {
|
||||
@@ -153,7 +165,7 @@ export class TestWorkflowService {
|
||||
testName: isTimeout ? 'Timeout' : 'ExecutionError',
|
||||
className: run.name,
|
||||
message: isTimeout
|
||||
? `Test run timed out after ${run.timeout}s`
|
||||
? `Test run timed out after ${run.timeout ?? 600}s`
|
||||
: error.message ?? 'Unknown execution error',
|
||||
stackTrace: error.stderr ?? undefined,
|
||||
},
|
||||
@@ -166,70 +178,66 @@ export class TestWorkflowService {
|
||||
/**
|
||||
* Build Unity CLI arguments for a test run based on its configuration.
|
||||
*/
|
||||
static buildUnityArgs(run: TestRunDefinition, params: BuildParameters): string {
|
||||
const args: string[] = [];
|
||||
|
||||
// Batch mode and no-graphics for CI
|
||||
args.push('-batchmode');
|
||||
args.push('-nographics');
|
||||
static buildUnityArgs(run: TestRunDefinition, parameters: BuildParameters): string {
|
||||
const unityArguments: string[] = ['-batchmode', '-nographics'];
|
||||
|
||||
// Project path
|
||||
if (params.projectPath) {
|
||||
args.push(`-projectPath "${params.projectPath}"`);
|
||||
if (parameters.projectPath) {
|
||||
unityArguments.push(`-projectPath "${parameters.projectPath}"`);
|
||||
}
|
||||
|
||||
// Test mode
|
||||
if (run.builtClient && run.builtClientPath) {
|
||||
// Built client testing: run tests against a built player
|
||||
args.push('-runTests');
|
||||
args.push(`-testPlatform StandalonePlayer`);
|
||||
args.push(`-assemblyNames Assembly-CSharp-Tests`);
|
||||
args.push(`-builtPlayerPath "${run.builtClientPath}"`);
|
||||
unityArguments.push(
|
||||
'-runTests',
|
||||
`-testPlatform StandalonePlayer`,
|
||||
`-assemblyNames Assembly-CSharp-Tests`,
|
||||
`-builtPlayerPath "${run.builtClientPath}"`,
|
||||
);
|
||||
} else if (run.editMode && run.playMode) {
|
||||
// Both modes: run EditMode first, then PlayMode will require a separate invocation
|
||||
// For combined mode, use EditMode (the service handles sequencing)
|
||||
args.push('-runTests');
|
||||
args.push('-testPlatform EditMode');
|
||||
unityArguments.push('-runTests', '-testPlatform EditMode');
|
||||
} else if (run.playMode) {
|
||||
args.push('-runTests');
|
||||
args.push('-testPlatform PlayMode');
|
||||
unityArguments.push('-runTests', '-testPlatform PlayMode');
|
||||
} else if (run.editMode) {
|
||||
args.push('-runTests');
|
||||
args.push('-testPlatform EditMode');
|
||||
unityArguments.push('-runTests', '-testPlatform EditMode');
|
||||
}
|
||||
|
||||
// Apply taxonomy filters
|
||||
if (run.filters && Object.keys(run.filters).length > 0) {
|
||||
const filterArgs = TaxonomyFilterService.buildFilterArgs(run.filters);
|
||||
if (filterArgs) {
|
||||
args.push(filterArgs);
|
||||
const filterArguments = TaxonomyFilterService.buildFilterArgs(run.filters);
|
||||
if (filterArguments) {
|
||||
unityArguments.push(filterArguments);
|
||||
}
|
||||
}
|
||||
|
||||
// Target platform
|
||||
if (params.targetPlatform) {
|
||||
args.push(`-buildTarget ${params.targetPlatform}`);
|
||||
if (parameters.targetPlatform) {
|
||||
unityArguments.push(`-buildTarget ${parameters.targetPlatform}`);
|
||||
}
|
||||
|
||||
return args.join(' ');
|
||||
return unityArguments.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the path to the Unity editor executable.
|
||||
*/
|
||||
private static resolveUnityPath(params: BuildParameters): string {
|
||||
private static resolveUnityPath(parameters: BuildParameters): string {
|
||||
// In CI, Unity path is typically set via environment or the docker container
|
||||
const envUnityPath = process.env.UNITY_PATH ?? process.env.UNITY_EDITOR;
|
||||
if (envUnityPath) {
|
||||
return envUnityPath;
|
||||
const environmentUnityPath = process.env.UNITY_PATH ?? process.env.UNITY_EDITOR;
|
||||
if (environmentUnityPath) {
|
||||
return environmentUnityPath;
|
||||
}
|
||||
|
||||
// Default paths by platform
|
||||
if (process.platform === 'win32') {
|
||||
return `C:/Program Files/Unity/Hub/Editor/${params.editorVersion}/Editor/Unity.exe`;
|
||||
return `C:/Program Files/Unity/Hub/Editor/${parameters.editorVersion}/Editor/Unity.exe`;
|
||||
}
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
return `/Applications/Unity/Hub/Editor/${params.editorVersion}/Unity.app/Contents/MacOS/Unity`;
|
||||
return `/Applications/Unity/Hub/Editor/${parameters.editorVersion}/Unity.app/Contents/MacOS/Unity`;
|
||||
}
|
||||
|
||||
// Linux default (Docker container path)
|
||||
|
||||
Reference in New Issue
Block a user