Compare commits

..

3 Commits

Author SHA1 Message Date
frostebite
fb2485c287 chore: bump production dependencies (minor/patch)
- @actions/cache ^4.0.0 → ^4.1.0
- @actions/github ^6.0.0 → ^6.0.1
- commander ^9.0.0 → ^9.5.0
- nanoid ^3.3.1 → ^3.3.12
- reflect-metadata ^0.1.13 → ^0.2.2
- semver ^7.5.2 → ^7.7.4
- yaml ^2.2.2 → ^2.8.4

All minor/patch bumps. Major bumps (@actions/core 3.x, nanoid 5.x ESM)
deferred to a separate PR.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 22:26:07 +01:00
frostebite
9d20e0b607 Merge branch 'main' of https://github.com/game-ci/unity-builder 2026-05-06 22:01:22 +01:00
frostebite
2321712bb4 fix: remove concurrency block from reusable workflow to prevent deadlock
When integrity-check.yml calls validate-orchestrator-integration.yml via
workflow_call, both workflows resolve github.workflow to the same name
("Integrity"), creating identical concurrency groups. GitHub detects this
as a deadlock and cancels the run.

Fix: remove concurrency from the reusable workflow entirely — the caller
already manages concurrency for the group.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 17:18:12 +01:00
13 changed files with 233 additions and 146 deletions

View File

@@ -95,7 +95,7 @@ jobs:
- name: Run plugin interface unit tests
run: |
echo "Running orchestrator-plugin unit tests..."
npx vitest run orchestrator-plugin --reporter=verbose
npx jest orchestrator-plugin --verbose --detectOpenHandles --forceExit
- name: Build and pack orchestrator
working-directory: orchestrator-standalone
@@ -167,10 +167,6 @@ jobs:
continue-on-error: true
id: orch-branch
- name: Clean corrupted checkout
if: steps.orch-branch.outcome == 'failure'
run: rm -rf .git || true
- name: Fallback to orchestrator main branch
if: steps.orch-branch.outcome == 'failure'
uses: actions/checkout@v4
@@ -324,20 +320,9 @@ jobs:
- name: Run orchestrator unit tests (fast, no infra)
timeout-minutes: 2
run: >-
yarn vitest run
"orchestrator-guid"
"orchestrator-folders"
"task-parameter-serializer"
"follow-log-stream-service"
"runner-availability-service"
"provider-url-parser"
"provider-loader"
"provider-git-manager"
"orchestrator-image"
"orchestrator-hooks"
"orchestrator-github-checks"
"middleware-service"
--reporter=verbose --no-file-parallelism
yarn run test
--testPathPattern="orchestrator-guid|orchestrator-folders|task-parameter-serializer|follow-log-stream-service|runner-availability-service|provider-url-parser|provider-loader|provider-git-manager|orchestrator-image|orchestrator-hooks|orchestrator-github-checks|middleware-service"
--verbose --detectOpenHandles --forceExit --runInBand
# --- K8s cluster setup ---
- name: Clean up disk space before K8s tests
@@ -387,7 +372,7 @@ jobs:
# --- K8s Test 1: orchestrator-image ---
- name: Run orchestrator-image test (K8s)
timeout-minutes: 10
run: yarn run test "orchestrator-image" --no-file-parallelism
run: yarn run test "orchestrator-image" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -411,7 +396,7 @@ jobs:
# --- K8s Test 2: orchestrator-kubernetes ---
- name: Run orchestrator-kubernetes test
timeout-minutes: 30
run: yarn run test "orchestrator-kubernetes" --no-file-parallelism
run: yarn run test "orchestrator-kubernetes" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -443,7 +428,7 @@ jobs:
# --- K8s Test 3: orchestrator-s3-steps ---
- name: Run orchestrator-s3-steps test (K8s)
timeout-minutes: 30
run: yarn run test "orchestrator-s3-steps" --no-file-parallelism
run: yarn run test "orchestrator-s3-steps" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -476,7 +461,7 @@ jobs:
- name: Run orchestrator-end2end-caching test (K8s)
timeout-minutes: 60
continue-on-error: true
run: yarn run test "orchestrator-end2end-caching" --no-file-parallelism
run: yarn run test "orchestrator-end2end-caching" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -515,7 +500,7 @@ jobs:
- name: Run orchestrator-end2end-retaining test (K8s)
timeout-minutes: 60
continue-on-error: true
run: yarn run test "orchestrator-end2end-retaining" --no-file-parallelism
run: yarn run test "orchestrator-end2end-retaining" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -575,10 +560,6 @@ jobs:
continue-on-error: true
id: orch-branch
- name: Clean corrupted checkout
if: steps.orch-branch.outcome == 'failure'
run: rm -rf .git || true
- name: Fallback to orchestrator main branch
if: steps.orch-branch.outcome == 'failure'
uses: actions/checkout@v4
@@ -669,7 +650,7 @@ jobs:
# --- AWS Test 1: orchestrator-image ---
- name: Run orchestrator-image test (AWS)
timeout-minutes: 10
run: yarn run test "orchestrator-image" --no-file-parallelism
run: yarn run test "orchestrator-image" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -687,7 +668,7 @@ jobs:
# --- AWS Test 2: orchestrator-environment ---
- name: Run orchestrator-environment test (AWS)
timeout-minutes: 30
run: yarn run test "orchestrator-environment" --no-file-parallelism
run: yarn run test "orchestrator-environment" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -705,7 +686,7 @@ jobs:
# --- AWS Test 3: orchestrator-s3-steps ---
- name: Run orchestrator-s3-steps test (AWS)
timeout-minutes: 30
run: yarn run test "orchestrator-s3-steps" --no-file-parallelism
run: yarn run test "orchestrator-s3-steps" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -723,7 +704,7 @@ jobs:
# --- AWS Test 4: orchestrator-hooks ---
- name: Run orchestrator-hooks test (AWS)
timeout-minutes: 30
run: yarn run test "orchestrator-hooks" --no-file-parallelism
run: yarn run test "orchestrator-hooks" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -741,7 +722,7 @@ jobs:
# --- AWS Test 5: orchestrator-caching ---
- name: Run orchestrator-caching test (AWS)
timeout-minutes: 60
run: yarn run test "orchestrator-caching" --no-file-parallelism
run: yarn run test "orchestrator-caching" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -759,7 +740,7 @@ jobs:
# --- AWS Test 6: orchestrator-locking-core ---
- name: Run orchestrator-locking-core test (AWS)
timeout-minutes: 60
run: yarn run test "orchestrator-locking-core" --no-file-parallelism
run: yarn run test "orchestrator-locking-core" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -777,7 +758,7 @@ jobs:
# --- AWS Test 7: orchestrator-locking-get-locked ---
- name: Run orchestrator-locking-get-locked test (AWS)
timeout-minutes: 60
run: yarn run test "orchestrator-locking-get-locked" --no-file-parallelism
run: yarn run test "orchestrator-locking-get-locked" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -801,7 +782,7 @@ jobs:
- name: Run orchestrator-end2end-caching test (AWS)
timeout-minutes: 60
continue-on-error: true
run: yarn run test "orchestrator-end2end-caching" --no-file-parallelism
run: yarn run test "orchestrator-end2end-caching" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -820,7 +801,7 @@ jobs:
- name: Run orchestrator-end2end-retaining test (AWS)
timeout-minutes: 60
continue-on-error: true
run: yarn run test "orchestrator-end2end-retaining" --no-file-parallelism
run: yarn run test "orchestrator-end2end-retaining" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -839,7 +820,7 @@ jobs:
- name: Run orchestrator-end2end-locking test (AWS)
timeout-minutes: 60
continue-on-error: true
run: yarn run test "orchestrator-end2end-locking" --no-file-parallelism
run: yarn run test "orchestrator-end2end-locking" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -884,10 +865,6 @@ jobs:
continue-on-error: true
id: orch-branch
- name: Clean corrupted checkout
if: steps.orch-branch.outcome == 'failure'
run: rm -rf .git || true
- name: Fallback to orchestrator main branch
if: steps.orch-branch.outcome == 'failure'
uses: actions/checkout@v4
@@ -977,7 +954,7 @@ jobs:
# --- Local Docker Test 1: orchestrator-image ---
- name: Run orchestrator-image test (local-docker)
timeout-minutes: 10
run: yarn run test "orchestrator-image" --no-file-parallelism
run: yarn run test "orchestrator-image" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -995,7 +972,7 @@ jobs:
# --- Local Docker Test 2: orchestrator-hooks ---
- name: Run orchestrator-hooks test (local-docker)
timeout-minutes: 30
run: yarn run test "orchestrator-hooks" --no-file-parallelism
run: yarn run test "orchestrator-hooks" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1013,7 +990,7 @@ jobs:
# --- Local Docker Test 3: orchestrator-local-persistence ---
- name: Run orchestrator-local-persistence test (local-docker)
timeout-minutes: 30
run: yarn run test "orchestrator-local-persistence" --no-file-parallelism
run: yarn run test "orchestrator-local-persistence" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1031,7 +1008,7 @@ jobs:
# --- Local Docker Test 4: orchestrator-caching ---
- name: Run orchestrator-caching test (local-docker)
timeout-minutes: 30
run: yarn run test "orchestrator-caching" --no-file-parallelism
run: yarn run test "orchestrator-caching" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1049,7 +1026,7 @@ jobs:
# --- Local Docker Test 5: orchestrator-github-checks ---
- name: Run orchestrator-github-checks test (local-docker)
timeout-minutes: 30
run: yarn run test "orchestrator-github-checks" --no-file-parallelism
run: yarn run test "orchestrator-github-checks" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1067,7 +1044,7 @@ jobs:
# --- Local Docker Test 6: orchestrator-locking-core (with S3) ---
- name: Run orchestrator-locking-core test (local-docker + S3)
timeout-minutes: 30
run: yarn run test "orchestrator-locking-core" --no-file-parallelism
run: yarn run test "orchestrator-locking-core" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1085,7 +1062,7 @@ jobs:
# --- Local Docker Test 7: orchestrator-locking-get-locked (with S3) ---
- name: Run orchestrator-locking-get-locked test (local-docker + S3)
timeout-minutes: 30
run: yarn run test "orchestrator-locking-get-locked" --no-file-parallelism
run: yarn run test "orchestrator-locking-get-locked" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1103,7 +1080,7 @@ jobs:
# --- Local Docker Test 8: orchestrator-s3-steps (with S3) ---
- name: Run orchestrator-s3-steps test (local-docker + S3)
timeout-minutes: 30
run: yarn run test "orchestrator-s3-steps" --no-file-parallelism
run: yarn run test "orchestrator-s3-steps" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1122,7 +1099,7 @@ jobs:
- name: Run orchestrator-end2end-caching test (local-docker + S3)
timeout-minutes: 60
continue-on-error: true
run: yarn run test "orchestrator-end2end-caching" --no-file-parallelism
run: yarn run test "orchestrator-end2end-caching" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
@@ -1167,10 +1144,6 @@ jobs:
continue-on-error: true
id: orch-branch
- name: Clean corrupted checkout
if: steps.orch-branch.outcome == 'failure'
run: rm -rf .git || true
- name: Fallback to orchestrator main branch
if: steps.orch-branch.outcome == 'failure'
uses: actions/checkout@v4
@@ -1247,7 +1220,7 @@ jobs:
# --- Rclone Test ---
- name: Run orchestrator-rclone-steps test
timeout-minutes: 30
run: yarn run test "orchestrator-rclone-steps" --no-file-parallelism
run: yarn run test "orchestrator-rclone-steps" --detectOpenHandles --forceExit --runInBand
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}

View File

@@ -178,11 +178,6 @@ inputs:
default: 'false'
required: false
description: 'Skip the activation/deactivation of Unity. This assumes Unity is already activated.'
linux64RemoveExecutableExtension:
default: 'false'
required: false
description:
'When building for StandaloneLinux64, remove the default file extension of `.x86_64`. Set to true to restore the extensionless behavior from v4.'
outputs:
volume:
@@ -200,5 +195,5 @@ branding:
icon: 'box'
color: 'gray-dark'
runs:
using: 'node24'
using: 'node20'
main: 'dist/index.js'

View File

@@ -36,8 +36,11 @@
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/github": "^6.0.1",
"commander": "^9.5.0",
"commander-ts": "^0.2.0",
"md5": "^2.3.0",
"nanoid": "^3.3.12",
"reflect-metadata": "^0.2.2",
"semver": "^7.7.4",
"ts-md5": "^1.3.1",
"unity-changeset": "^3.1.0",

View File

@@ -66,6 +66,12 @@ vi.mock('./model', () => ({
},
}));
vi.mock('./model/cli/cli', () => ({
Cli: {
InitCliMode: vi.fn().mockReturnValue(false),
},
}));
vi.mock('./model/mac-builder', () => ({
__esModule: true,
default: {

View File

@@ -1,5 +1,6 @@
import * as core from '@actions/core';
import { Action, BuildParameters, Cache, Docker, ImageTag, Output } from './model';
import { Cli } from './model/cli/cli';
import MacBuilder from './model/mac-builder';
import PlatformSetup from './model/platform-setup';
import { Plugin, loadPlugin } from './model/plugin';
@@ -8,6 +9,11 @@ import { Plugin, loadPlugin } from './model/plugin';
// vitest's module re-loading (which changed in vitest 4).
export async function runMain() {
try {
if (Cli.InitCliMode()) {
await Cli.RunCli();
return;
}
Action.checkCompatibility();
Cache.verify();

View File

@@ -117,21 +117,18 @@ describe('BuildParameters', () => {
});
test.each`
targetPlatform | expectedExtension | androidExportType | linux64RemoveExecutableExtension
${Platform.types.Android} | ${'.apk'} | ${'androidPackage'} | ${false}
${Platform.types.Android} | ${'.aab'} | ${'androidAppBundle'} | ${true}
${Platform.types.Android} | ${''} | ${'androidStudioProject'} | ${false}
${Platform.types.StandaloneWindows} | ${'.exe'} | ${'n/a'} | ${true}
${Platform.types.StandaloneWindows64} | ${'.exe'} | ${'n/a'} | ${false}
${Platform.types.StandaloneLinux64} | ${'.x86_64'} | ${'n/a'} | ${false}
${Platform.types.StandaloneLinux64} | ${''} | ${'n/a'} | ${true}
targetPlatform | expectedExtension | androidExportType
${Platform.types.Android} | ${'.apk'} | ${'androidPackage'}
${Platform.types.Android} | ${'.aab'} | ${'androidAppBundle'}
${Platform.types.Android} | ${''} | ${'androidStudioProject'}
${Platform.types.StandaloneWindows} | ${'.exe'} | ${'n/a'}
${Platform.types.StandaloneWindows64} | ${'.exe'} | ${'n/a'}
`(
'appends $expectedExtension for $targetPlatform with linux64RemoveExecutableExtension=$linux64RemoveExecutableExtension',
async ({ targetPlatform, expectedExtension, androidExportType, linux64RemoveExecutableExtension }) => {
'appends $expectedExtension for $targetPlatform with androidExportType $androidExportType',
async ({ targetPlatform, expectedExtension, androidExportType }) => {
vi.spyOn(Input, 'targetPlatform', 'get').mockReturnValue(targetPlatform);
vi.spyOn(Input, 'buildName', 'get').mockReturnValue(targetPlatform);
vi.spyOn(Input, 'androidExportType', 'get').mockReturnValue(androidExportType);
vi.spyOn(Input, 'linux64RemoveExecutableExtension', 'get').mockReturnValue(linux64RemoveExecutableExtension);
await expect(BuildParameters.create()).resolves.toEqual(
expect.objectContaining({ buildFile: `${targetPlatform}${expectedExtension}` }),
);

View File

@@ -6,7 +6,7 @@ import UnityVersioning from './unity-versioning';
import Versioning from './versioning';
import { GitRepoReader } from './input-readers/git-repo';
import { GithubCliReader } from './input-readers/github-cli';
import { PluginOptions } from './plugin-options';
import { Cli } from './cli/cli';
import GitHub from './github';
import * as core from '@actions/core';
@@ -73,7 +73,6 @@ class BuildParameters {
Input.buildName,
Input.targetPlatform,
Input.androidExportType,
Input.linux64RemoveExecutableExtension,
);
const editorVersion = UnityVersioning.determineUnityVersion(
Input.projectPath,
@@ -129,7 +128,7 @@ class BuildParameters {
}
const providerStrategy =
Input.getInput('providerStrategy') || (PluginOptions.isPluginMode ? 'aws' : 'local');
Input.getInput('providerStrategy') || (Cli.isCliMode ? 'aws' : 'local');
return {
editorVersion,
@@ -182,19 +181,14 @@ class BuildParameters {
'0123456789abcdefghijklmnopqrstuvwxyz',
4,
)()}`,
isCliMode: PluginOptions.isPluginMode,
isCliMode: Cli.isCliMode,
cacheUnityInstallationOnMac: Input.cacheUnityInstallationOnMac,
unityHubVersionOnMac: Input.unityHubVersionOnMac,
dockerWorkspacePath: Input.dockerWorkspacePath,
};
}
static parseBuildFile(
filename: string,
platform: string,
androidExportType: string,
linux64RemoveExecutableExtension: boolean,
): string {
static parseBuildFile(filename: string, platform: string, androidExportType: string): string {
if (Platform.isWindows(platform)) {
return `${filename}.exe`;
}
@@ -214,10 +208,6 @@ class BuildParameters {
}
}
if (platform === Platform.types.StandaloneLinux64 && !linux64RemoveExecutableExtension) {
return `${filename}.x86_64`;
}
return filename;
}

View File

@@ -0,0 +1,45 @@
export class CliFunctionsRepository {
private static targets: any[] = [];
public static PushCliFunction(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor,
key: string,
description: string,
) {
CliFunctionsRepository.targets.push({
target,
propertyKey,
descriptor,
key,
description,
});
}
public static GetCliFunctions(key: any) {
const results = CliFunctionsRepository.targets.find((x) => x.key === key);
if (results === undefined || results.length === 0) {
throw new Error(`no CLI mode found for ${key}`);
}
return results;
}
public static GetAllCliModes() {
return CliFunctionsRepository.targets.map((x) => {
return {
key: x.key,
description: x.description,
};
});
}
// eslint-disable-next-line no-unused-vars
public static PushCliFunctionSource(cliFunction: any) {}
}
export function CliFunction(key: string, description: string) {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
CliFunctionsRepository.PushCliFunction(target, propertyKey, descriptor, key, description);
};
}

100
src/model/cli/cli.ts Normal file
View File

@@ -0,0 +1,100 @@
import { Command } from 'commander-ts';
import { Input } from '..';
import * as core from '@actions/core';
import { ActionYamlReader } from '../input-readers/action-yaml';
import { CliFunction, CliFunctionsRepository } from './cli-functions-repository';
import { OptionValues } from 'commander';
import { InputKey } from '../input';
export class Cli {
public static options: OptionValues | undefined;
static get isCliMode() {
return Cli.options !== undefined && Cli.options.mode !== undefined && Cli.options.mode !== '';
}
public static query(key: string, alternativeKey: string) {
if (Cli.options && Cli.options[key] !== undefined) {
return Cli.options[key];
}
if (Cli.options && alternativeKey && Cli.options[alternativeKey] !== undefined) {
return Cli.options[alternativeKey];
}
return;
}
public static InitCliMode() {
const program = new Command();
program.version('0.0.1');
const actionYamlReader: ActionYamlReader = new ActionYamlReader();
const properties = Object.getOwnPropertyNames(Input).filter(
(p) => p !== 'length' && p !== 'prototype' && p !== 'name',
);
for (const element of properties) {
program.option(`--${element} <${element}>`, actionYamlReader.GetActionYamlValue(element));
}
program.option(
'-m, --mode <mode>',
CliFunctionsRepository.GetAllCliModes()
.map((x) => `${x.key} (${x.description})`)
.join(` | `),
);
program.option(
'--populateOverride <populateOverride>',
'should use override query to pull input false by default',
);
program.option('--cachePushFrom <cachePushFrom>', 'cache push from source folder');
program.option('--cachePushTo <cachePushTo>', 'cache push to caching folder');
program.option('--artifactName <artifactName>', 'caching artifact name');
program.option('--select <select>', 'select a particular resource');
program.option('--logFile <logFile>', 'output to log file (log stream only)');
program.option('--profilePath <profilePath>', 'path to submodule profile YAML');
program.option('--variantPath <variantPath>', 'path to submodule variant YAML');
program.option('--agentPath <agentPath>', 'path to custom LFS transfer agent');
program.option('--agentArgs <agentArgs>', 'arguments for custom LFS transfer agent');
program.option(
'--storagePaths <storagePaths>',
'semicolon-separated storage paths for LFS agent',
);
program.parse(process.argv);
Cli.options = program.opts();
return Cli.isCliMode;
}
static async RunCli(): Promise<void> {
const results = CliFunctionsRepository.GetCliFunctions(Cli.options?.mode);
if (!results) {
throw new Error(
`Unknown CLI mode: ${Cli.options?.mode}. Orchestrator CLI features require @game-ci/orchestrator.`,
);
}
core.info(`Entrypoint: ${results.key}`);
Cli.options!.versioning = 'None';
return await results.target[results.propertyKey](Cli.options);
}
@CliFunction(`print-input`, `prints all input`)
private static logInput() {
core.info(`\n`);
core.info(`INPUT:`);
const properties = Object.getOwnPropertyNames(Input).filter(
(p) => p !== 'length' && p !== 'prototype' && p !== 'name',
);
for (const element of properties) {
if (
element in Input &&
Input[element as InputKey] !== undefined &&
Input[element as InputKey] !== '' &&
typeof Input[element as InputKey] !== `function` &&
element !== 'length' &&
element !== 'cliOptions' &&
element !== 'prototype'
) {
core.info(`${element} ${Input[element as InputKey]}`);
}
}
core.info(`\n`);
}
}

View File

@@ -353,22 +353,4 @@ describe('Input', () => {
expect(spy).toHaveBeenCalledTimes(1);
});
});
describe('linux64RemoveExecutableExtension', () => {
it('returns the default value', () => {
expect(Input.linux64RemoveExecutableExtension).toStrictEqual(false);
});
it('returns true when string true is passed', () => {
const spy = vi.spyOn(core, 'getInput').mockReturnValue('true');
expect(Input.linux64RemoveExecutableExtension).toStrictEqual(true);
expect(spy).toHaveBeenCalledTimes(1);
});
it('returns false when string false is passed', () => {
const spy = vi.spyOn(core, 'getInput').mockReturnValue('false');
expect(Input.linux64RemoveExecutableExtension).toStrictEqual(false);
expect(spy).toHaveBeenCalledTimes(1);
});
});
});

View File

@@ -1,6 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import { PluginOptions } from './plugin-options';
import { Cli } from './cli/cli';
import Platform from './platform';
import GitHub from './github';
import os from 'node:os';
@@ -28,8 +28,8 @@ class Input {
const alternativeQuery = Input.ToEnvVarFormat(query);
// Query input sources
if (PluginOptions.query(query, alternativeQuery)) {
return PluginOptions.query(query, alternativeQuery);
if (Cli.query(query, alternativeQuery)) {
return Cli.query(query, alternativeQuery);
}
if (process.env[query] !== undefined) {
@@ -284,12 +284,6 @@ class Input {
return Input.getInput('skipActivation')?.toLowerCase() ?? 'false';
}
static get linux64RemoveExecutableExtension(): boolean {
const input = Input.getInput('linux64RemoveExecutableExtension') ?? 'false';
return input === 'true';
}
public static ToEnvVarFormat(input: string) {
if (input.toUpperCase() === input) {
return input;

View File

@@ -1,32 +0,0 @@
/**
* Shared options bridge between unity-builder and plugins (e.g. @game-ci/orchestrator).
*
* Plugins set PluginOptions.options to pass configuration into BuildParameters
* and Input. When options are set, isPluginMode is true and query() reads
* from the options map instead of @actions/core.getInput().
*/
export class PluginOptions {
public static options: Record<string, any> | undefined;
static get isPluginMode() {
return Boolean(PluginOptions.options?.mode);
}
public static query(key: string, alternativeKey: string) {
if (PluginOptions.options && PluginOptions.options[key] !== undefined) {
return PluginOptions.options[key];
}
if (
PluginOptions.options &&
alternativeKey &&
PluginOptions.options[alternativeKey] !== undefined
) {
return PluginOptions.options[alternativeKey];
}
return;
}
}
// Backwards-compatible alias — the orchestrator still imports { Cli }
export { PluginOptions as Cli };

View File

@@ -2302,6 +2302,17 @@ __metadata:
languageName: node
linkType: hard
"commander-ts@npm:^0.2.0":
version: 0.2.0
resolution: "commander-ts@npm:0.2.0"
dependencies:
commander: "npm:^7.2.0"
peerDependencies:
reflect-metadata: ^0.1.13
checksum: 10/b57582d0eb98e7bce0a05bfe7c44b8ed01a0f77a05358ec9d35ef6406ac6b3031590fa49e1bff58649ae511bb18a576b01151cb94de9c12c7f0be7f865ca494f
languageName: node
linkType: hard
"commander@npm:^10.0.1":
version: 10.0.1
resolution: "commander@npm:10.0.1"
@@ -2330,6 +2341,13 @@ __metadata:
languageName: node
linkType: hard
"commander@npm:^9.5.0":
version: 9.5.0
resolution: "commander@npm:9.5.0"
checksum: 10/41c49b3d0f94a1fbeb0463c85b13f15aa15a9e0b4d5e10a49c0a1d58d4489b549d62262b052ae0aa6cfda53299bee487bfe337825df15e342114dde543f82906
languageName: node
linkType: hard
"common-path-prefix@npm:^3.0.0":
version: 3.0.0
resolution: "common-path-prefix@npm:3.0.0"
@@ -4196,6 +4214,13 @@ __metadata:
languageName: node
linkType: hard
"reflect-metadata@npm:^0.2.2":
version: 0.2.2
resolution: "reflect-metadata@npm:0.2.2"
checksum: 10/1c93f9ac790fea1c852fde80c91b2760420069f4862f28e6fae0c00c6937a56508716b0ed2419ab02869dd488d123c4ab92d062ae84e8739ea7417fae10c4745
languageName: node
linkType: hard
"regexp-tree@npm:^0.1.27":
version: 0.1.27
resolution: "regexp-tree@npm:0.1.27"
@@ -4791,6 +4816,8 @@ __metadata:
"@typescript/native-preview": "npm:^7.0.0-dev.20260505.1"
"@vercel/ncc": "npm:^0.36.1"
"@vitest/coverage-istanbul": "npm:^4.1.5"
commander: "npm:^9.5.0"
commander-ts: "npm:^0.2.0"
cross-env: "npm:^7.0.3"
eslint: "npm:^10.3.0"
eslint-plugin-unicorn: "npm:^64.0.0"
@@ -4802,6 +4829,7 @@ __metadata:
node-fetch: "npm:2"
oxfmt: "npm:^0.48.0"
oxlint: "npm:^1.63.0"
reflect-metadata: "npm:^0.2.2"
semver: "npm:^7.7.4"
ts-md5: "npm:^1.3.1"
ts-node: "npm:10.8.1"