mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-06-16 21:16:47 -07:00
feat(cache): add child workspace isolation for multi-product CI builds (#777)
Implement two-level workspace isolation pattern for enterprise-scale CI: - Atomic O(1) workspace restore via filesystem move (no tar/download/extract) - Separate Library caching for independent restore - .git preservation for delta operations - Stale workspace cleanup with configurable retention policies - 5 new action inputs: childWorkspacesEnabled, childWorkspaceName, childWorkspaceCacheRoot, childWorkspacePreserveGit, childWorkspaceSeparateLibrary - 28 unit tests covering all service methods This enables enterprise CI where workspaces are 50GB+ and traditional caching via actions/cache is impractical. On NTFS, workspace restore is O(1) via atomic rename when source and destination are on the same volume. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+40
-2
@@ -25,6 +25,33 @@ async function runMain() {
|
||||
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(
|
||||
@@ -80,8 +107,8 @@ async function runMain() {
|
||||
const { GitHooksService } = await import('./model/orchestrator/services/hooks/git-hooks-service');
|
||||
await GitHooksService.installHooks(workspace);
|
||||
if (buildParameters.gitHooksSkipList) {
|
||||
const env = GitHooksService.configureSkipList(buildParameters.gitHooksSkipList.split(','));
|
||||
Object.assign(process.env, env);
|
||||
const environment = GitHooksService.configureSkipList(buildParameters.gitHooksSkipList.split(','));
|
||||
Object.assign(process.env, environment);
|
||||
}
|
||||
} else {
|
||||
const { GitHooksService } = await import('./model/orchestrator/services/hooks/git-hooks-service');
|
||||
@@ -109,6 +136,17 @@ async function runMain() {
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user