mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-05-31 13:56:13 -07:00
Merges latest commits from PR #777 (git hooks fix + 129 new tests). Resolved merge conflicts: - dist/index.js, dist/index.js.map: rebuilt from merged source - src/model/input.ts: fixed 3 missing closing braces from merge - src/model/orchestrator/options/orchestrator-options.ts: fixed 1 missing closing brace from merge
201 lines
8.4 KiB
TypeScript
201 lines
8.4 KiB
TypeScript
import * as core from '@actions/core';
|
|
import path from 'node:path';
|
|
import { Action, BuildParameters, Cache, Orchestrator, Docker, ImageTag, Output } from './model';
|
|
import { Cli } from './model/cli/cli';
|
|
import MacBuilder from './model/mac-builder';
|
|
import PlatformSetup from './model/platform-setup';
|
|
import { BuildReliabilityService } from './model/orchestrator/services/reliability';
|
|
|
|
async function runMain() {
|
|
try {
|
|
if (Cli.InitCliMode()) {
|
|
await Cli.RunCli();
|
|
|
|
return;
|
|
}
|
|
Action.checkCompatibility();
|
|
Cache.verify();
|
|
|
|
// Always configure git environment for CI reliability
|
|
BuildReliabilityService.configureGitEnvironment();
|
|
|
|
const { workspace, actionFolder } = Action;
|
|
|
|
const buildParameters = await BuildParameters.create();
|
|
const baseImage = new ImageTag(buildParameters);
|
|
|
|
// Pre-build reliability checks
|
|
if (buildParameters.gitIntegrityCheck) {
|
|
core.info('Running git integrity checks...');
|
|
|
|
const isHealthy = BuildReliabilityService.checkGitIntegrity(workspace);
|
|
BuildReliabilityService.cleanStaleLockFiles(workspace);
|
|
BuildReliabilityService.validateSubmoduleBackingStores(workspace);
|
|
|
|
if (buildParameters.cleanReservedFilenames) {
|
|
BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
|
}
|
|
|
|
if (!isHealthy && buildParameters.gitAutoRecover) {
|
|
core.info('Git corruption detected, attempting automatic recovery...');
|
|
const recovered = BuildReliabilityService.recoverCorruptedRepo(workspace);
|
|
if (!recovered) {
|
|
core.warning('Automatic recovery failed. Build may encounter issues.');
|
|
}
|
|
}
|
|
} else if (buildParameters.cleanReservedFilenames) {
|
|
// cleanReservedFilenames can run independently of gitIntegrityCheck
|
|
BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
|
}
|
|
|
|
let exitCode = -1;
|
|
|
|
if (buildParameters.providerStrategy === 'local') {
|
|
core.info('Building locally');
|
|
|
|
// Child workspace isolation - restore cached workspace before any other setup
|
|
let childWorkspaceConfig: any;
|
|
if (buildParameters.childWorkspacesEnabled && buildParameters.childWorkspaceName) {
|
|
const { ChildWorkspaceService } = await import('./model/orchestrator/services/cache/child-workspace-service');
|
|
const cacheRoot =
|
|
buildParameters.childWorkspaceCacheRoot ||
|
|
path.join(buildParameters.runnerTempPath || process.env.RUNNER_TEMP || '', 'game-ci-workspaces');
|
|
childWorkspaceConfig = ChildWorkspaceService.buildConfig({
|
|
childWorkspacesEnabled: buildParameters.childWorkspacesEnabled,
|
|
childWorkspaceName: buildParameters.childWorkspaceName,
|
|
childWorkspaceCacheRoot: cacheRoot,
|
|
childWorkspacePreserveGit: buildParameters.childWorkspacePreserveGit,
|
|
childWorkspaceSeparateLibrary: buildParameters.childWorkspaceSeparateLibrary,
|
|
});
|
|
const projectFullPath = path.join(workspace, buildParameters.projectPath);
|
|
const restored = ChildWorkspaceService.initializeWorkspace(projectFullPath, childWorkspaceConfig);
|
|
core.info(
|
|
`Child workspace "${buildParameters.childWorkspaceName}": ${
|
|
restored ? 'restored from cache' : 'starting fresh'
|
|
}`,
|
|
);
|
|
|
|
// Log workspace size for resource tracking
|
|
const size = ChildWorkspaceService.getWorkspaceSize(projectFullPath);
|
|
core.info(`Child workspace size after restore: ${size}`);
|
|
}
|
|
|
|
// Submodule profile initialization
|
|
if (buildParameters.submoduleProfilePath) {
|
|
const { SubmoduleProfileService } = await import(
|
|
'./model/orchestrator/services/submodule/submodule-profile-service'
|
|
);
|
|
core.info('Initializing submodules from profile...');
|
|
const plan = await SubmoduleProfileService.createInitPlan(
|
|
buildParameters.submoduleProfilePath,
|
|
buildParameters.submoduleVariantPath,
|
|
workspace,
|
|
);
|
|
await SubmoduleProfileService.execute(
|
|
plan,
|
|
workspace,
|
|
buildParameters.submoduleToken || buildParameters.gitPrivateToken,
|
|
);
|
|
}
|
|
|
|
// Configure custom LFS transfer agent
|
|
if (buildParameters.lfsTransferAgent) {
|
|
const { LfsAgentService } = await import('./model/orchestrator/services/lfs/lfs-agent-service');
|
|
core.info('Configuring custom LFS transfer agent...');
|
|
await LfsAgentService.configure(
|
|
buildParameters.lfsTransferAgent,
|
|
buildParameters.lfsTransferAgentArgs,
|
|
buildParameters.lfsStoragePaths ? buildParameters.lfsStoragePaths.split(';') : [],
|
|
workspace,
|
|
);
|
|
}
|
|
|
|
// Local build caching - restore
|
|
let cacheRoot = '';
|
|
let cacheKey = '';
|
|
if (buildParameters.localCacheEnabled) {
|
|
const { LocalCacheService } = await import('./model/orchestrator/services/cache/local-cache-service');
|
|
cacheRoot = LocalCacheService.resolveCacheRoot(buildParameters);
|
|
cacheKey = LocalCacheService.generateCacheKey(
|
|
buildParameters.targetPlatform,
|
|
buildParameters.editorVersion,
|
|
buildParameters.branch || '',
|
|
);
|
|
if (buildParameters.localCacheLfs) {
|
|
await LocalCacheService.restoreLfsCache(workspace, cacheRoot, cacheKey);
|
|
}
|
|
if (buildParameters.localCacheLibrary) {
|
|
const projectFullPath = path.join(workspace, buildParameters.projectPath);
|
|
await LocalCacheService.restoreLibraryCache(projectFullPath, cacheRoot, cacheKey);
|
|
}
|
|
}
|
|
|
|
// Git hooks — opt-in only. When disabled (default), do not touch hooks at all.
|
|
if (buildParameters.gitHooksEnabled) {
|
|
const { GitHooksService } = await import('./model/orchestrator/services/hooks/git-hooks-service');
|
|
await GitHooksService.installHooks(workspace);
|
|
if (buildParameters.gitHooksSkipList) {
|
|
const environment = GitHooksService.configureSkipList(buildParameters.gitHooksSkipList.split(','));
|
|
Object.assign(process.env, environment);
|
|
}
|
|
}
|
|
|
|
await PlatformSetup.setup(buildParameters, actionFolder);
|
|
exitCode =
|
|
process.platform === 'darwin'
|
|
? await MacBuilder.run(actionFolder)
|
|
: await Docker.run(baseImage.toString(), {
|
|
workspace,
|
|
actionFolder,
|
|
...buildParameters,
|
|
});
|
|
|
|
// Local build caching - save
|
|
if (buildParameters.localCacheEnabled) {
|
|
const { LocalCacheService } = await import('./model/orchestrator/services/cache/local-cache-service');
|
|
if (buildParameters.localCacheLibrary) {
|
|
const projectFullPath = path.join(workspace, buildParameters.projectPath);
|
|
await LocalCacheService.saveLibraryCache(projectFullPath, cacheRoot, cacheKey);
|
|
}
|
|
if (buildParameters.localCacheLfs) {
|
|
await LocalCacheService.saveLfsCache(workspace, cacheRoot, cacheKey);
|
|
}
|
|
}
|
|
|
|
// Child workspace isolation - save workspace for next run
|
|
if (childWorkspaceConfig && childWorkspaceConfig.enabled) {
|
|
const { ChildWorkspaceService } = await import('./model/orchestrator/services/cache/child-workspace-service');
|
|
const projectFullPath = path.join(workspace, buildParameters.projectPath);
|
|
const preSaveSize = ChildWorkspaceService.getWorkspaceSize(projectFullPath);
|
|
core.info(`Child workspace size before save: ${preSaveSize}`);
|
|
|
|
ChildWorkspaceService.saveWorkspace(projectFullPath, childWorkspaceConfig);
|
|
core.info(`Child workspace "${buildParameters.childWorkspaceName}" saved to cache`);
|
|
}
|
|
} else {
|
|
await Orchestrator.run(buildParameters, baseImage.toString());
|
|
exitCode = 0;
|
|
}
|
|
|
|
// Post-build: archive and enforce retention
|
|
if (buildParameters.buildArchiveEnabled && exitCode === 0) {
|
|
core.info('Archiving build output...');
|
|
BuildReliabilityService.archiveBuildOutput(buildParameters.buildPath, buildParameters.buildArchivePath);
|
|
BuildReliabilityService.enforceRetention(buildParameters.buildArchivePath, buildParameters.buildArchiveRetention);
|
|
}
|
|
|
|
// Set output
|
|
await Output.setBuildVersion(buildParameters.buildVersion);
|
|
await Output.setAndroidVersionCode(buildParameters.androidVersionCode);
|
|
await Output.setEngineExitCode(exitCode);
|
|
|
|
if (exitCode !== 0) {
|
|
core.setFailed(`Build failed with exit code ${exitCode}`);
|
|
}
|
|
} catch (error) {
|
|
core.setFailed((error as Error).message);
|
|
}
|
|
}
|
|
|
|
runMain();
|