Make action a thin wrapper around game-ci/unity-engine-core

Delegates build logic to the extracted implementation in
game-ci/unity-engine-core instead of maintaining a local copy, per
game-ci/roadmap#11 workstream 2 (Option A) — third and final engine
repo to make this move, after unity-activate and unity-test-runner.
src/model/* removed; build/test coverage (including the index.ts
orchestration integration tests) now lives in the destination repo.

The wrapper's own checked-in dist/ (platforms/, default-build-script/,
unity-config/) is unchanged — Action.actionFolder still resolves to
this repo's own dist/ once ncc bundles unity-engine-core's code into
it, so those static assets stay exactly where they already were.
This commit is contained in:
frostebite
2026-08-13 02:53:52 +01:00
parent d829bfc901
commit 9dbfdd0717
71 changed files with 2730 additions and 19994 deletions
+4 -80
View File
@@ -1,85 +1,9 @@
import * as core from '@actions/core';
import { Action, BuildParameters, Cache, Docker, ImageTag, Output } from './model';
import MacBuilder from './model/mac-builder';
import PlatformSetup from './model/platform-setup';
import { Plugin, loadPlugin } from './model/plugin';
// Thin wrapper: the actual build logic lives in game-ci/unity-engine-core.
// See game-ci/roadmap#11 (workstream 2) for the "thin wrapper" migration this is part of.
import { runMain } from '@game-ci/unity-engine-core/dist/unity-builder';
// Exported so tests can drive the lifecycle directly without depending on
// vitest's module re-loading (which changed in vitest 4).
export async function runMain() {
try {
Action.checkCompatibility();
Cache.verify();
export { runMain };
const { workspace, actionFolder } = Action;
const buildParameters = await BuildParameters.create();
const baseImage = new ImageTag(buildParameters);
// Load optional plugin. The default implementation is @game-ci/orchestrator.
const plugin = await loadPlugin();
await plugin?.initialize(buildParameters, workspace);
let exitCode = -1;
if (plugin?.canHandleBuild()) {
// Plugin handles the build entirely (remote providers, hot runner, test workflows)
const result = await plugin.handleBuild(baseImage.toString());
exitCode = result.fallbackToLocal
? await runLocalBuild(buildParameters, baseImage, workspace, actionFolder, plugin)
: result.exitCode;
} else if (buildParameters.providerStrategy === 'local') {
exitCode = await runLocalBuild(buildParameters, baseImage, workspace, actionFolder, plugin);
} else {
throw new Error(
`Provider strategy "${buildParameters.providerStrategy}" requires @game-ci/orchestrator. ` +
'Install it via the game-ci/orchestrator action, or use providerStrategy=local.',
);
}
// Set core outputs
await Output.setBuildVersion(buildParameters.buildVersion);
await Output.setAndroidVersionCode(buildParameters.androidVersionCode);
await Output.setEngineExitCode(exitCode);
// Plugin handles post-build (artifacts, archiving, retention)
await plugin?.handlePostBuild(exitCode);
if (exitCode !== 0) {
core.setFailed(`Build failed with exit code ${exitCode}`);
}
} catch (error) {
core.setFailed((error as Error).message);
}
}
async function runLocalBuild(
buildParameters: BuildParameters,
baseImage: ImageTag,
workspace: string,
actionFolder: string,
plugin?: Plugin,
): Promise<number> {
await plugin?.beforeLocalBuild(workspace);
await PlatformSetup.setup(buildParameters, actionFolder);
const exitCode =
process.platform === 'darwin'
? await MacBuilder.run(actionFolder)
: await Docker.run(baseImage.toString(), {
workspace,
actionFolder,
...buildParameters,
});
await plugin?.afterLocalBuild(workspace, exitCode);
return exitCode;
}
// Auto-run when this module is the entry point. Tests import the file via
// `await import('./index')` purely to register the mock factories and then
// call `runMain()` directly.
if (process.env.NODE_ENV !== 'test') {
runMain();
}