mirror of
https://github.com/game-ci/unity-builder.git
synced 2026-06-17 21:46:48 -07:00
ci: add orchestrator compatibility validation workflow
Runs on PRs that touch orchestrator source or bridge files. Validates: - Orchestrator source files are in sync with standalone repo - Bridge file exports exist in both repos - Orchestrator tests pass in both unity-builder and standalone contexts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
|||||||
|
name: Validate Orchestrator Compatibility
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, 'release/**', 'feature/**']
|
||||||
|
paths:
|
||||||
|
- 'src/model/orchestrator/**'
|
||||||
|
- 'src/model/build-parameters.ts'
|
||||||
|
- 'src/model/input.ts'
|
||||||
|
- 'src/model/github.ts'
|
||||||
|
- 'src/model/docker.ts'
|
||||||
|
- 'src/model/cli/cli.ts'
|
||||||
|
- 'src/model/cli/cli-functions-repository.ts'
|
||||||
|
- 'src/model/input-readers/**'
|
||||||
|
- 'src/model/shared-types.ts'
|
||||||
|
- 'src/model/image-tag.ts'
|
||||||
|
- 'src/model/action.ts'
|
||||||
|
pull_request:
|
||||||
|
branches: [main, 'release/**']
|
||||||
|
paths:
|
||||||
|
- 'src/model/orchestrator/**'
|
||||||
|
- 'src/model/build-parameters.ts'
|
||||||
|
- 'src/model/input.ts'
|
||||||
|
- 'src/model/github.ts'
|
||||||
|
- 'src/model/docker.ts'
|
||||||
|
- 'src/model/cli/cli.ts'
|
||||||
|
- 'src/model/cli/cli-functions-repository.ts'
|
||||||
|
- 'src/model/input-readers/**'
|
||||||
|
- 'src/model/shared-types.ts'
|
||||||
|
- 'src/model/image-tag.ts'
|
||||||
|
- 'src/model/action.ts'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate-orchestrator:
|
||||||
|
name: Orchestrator Compatibility Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout unity-builder
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Checkout orchestrator repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: game-ci/orchestrator
|
||||||
|
path: orchestrator-standalone
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install unity-builder dependencies
|
||||||
|
run: yarn install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Verify orchestrator source is in sync
|
||||||
|
run: |
|
||||||
|
echo "Comparing orchestrator source files..."
|
||||||
|
# Compare orchestrator source between unity-builder and standalone repo
|
||||||
|
# Exclude interfaces.ts which only exists in standalone
|
||||||
|
DIFF_OUTPUT=$(diff -rq src/model/orchestrator/ orchestrator-standalone/src/model/orchestrator/ --exclude="interfaces.ts" 2>&1 || true)
|
||||||
|
if [ -n "$DIFF_OUTPUT" ]; then
|
||||||
|
echo "::warning::Orchestrator source has diverged from standalone repo:"
|
||||||
|
echo "$DIFF_OUTPUT"
|
||||||
|
echo ""
|
||||||
|
echo "Files that differ:"
|
||||||
|
diff -rq src/model/orchestrator/ orchestrator-standalone/src/model/orchestrator/ --exclude="interfaces.ts" | head -20 || true
|
||||||
|
else
|
||||||
|
echo "✓ All orchestrator source files are in sync"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Verify bridge file compatibility
|
||||||
|
run: |
|
||||||
|
echo "Checking that bridge file exports match unity-builder exports..."
|
||||||
|
# Verify key exports exist in both repos
|
||||||
|
for file in build-parameters input github docker action image-tag; do
|
||||||
|
if [ -f "orchestrator-standalone/src/model/${file}.ts" ]; then
|
||||||
|
echo "✓ Bridge file exists: src/model/${file}.ts"
|
||||||
|
else
|
||||||
|
echo "::error::Missing bridge file in orchestrator: src/model/${file}.ts"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Run orchestrator tests in unity-builder context
|
||||||
|
run: |
|
||||||
|
echo "Running orchestrator unit tests..."
|
||||||
|
npx jest --no-cache --testPathPattern="src/model/orchestrator/" --passWithNoTests 2>&1 | tail -5
|
||||||
|
|
||||||
|
- name: Run orchestrator tests in standalone context
|
||||||
|
working-directory: orchestrator-standalone
|
||||||
|
run: |
|
||||||
|
yarn install --frozen-lockfile
|
||||||
|
echo "Running orchestrator standalone tests..."
|
||||||
|
npx jest --no-cache 2>&1 | tail -5
|
||||||
+163
-58
@@ -39,13 +39,7 @@ const model_1 = __nccwpck_require__(41359);
|
|||||||
const cli_1 = __nccwpck_require__(55651);
|
const cli_1 = __nccwpck_require__(55651);
|
||||||
const mac_builder_1 = __importDefault(__nccwpck_require__(39364));
|
const mac_builder_1 = __importDefault(__nccwpck_require__(39364));
|
||||||
const platform_setup_1 = __importDefault(__nccwpck_require__(64423));
|
const platform_setup_1 = __importDefault(__nccwpck_require__(64423));
|
||||||
const reliability_1 = __nccwpck_require__(9842);
|
const orchestrator_plugin_1 = __nccwpck_require__(2075);
|
||||||
const test_workflow_1 = __nccwpck_require__(22377);
|
|
||||||
const hot_runner_1 = __nccwpck_require__(74283);
|
|
||||||
const output_service_1 = __nccwpck_require__(18795);
|
|
||||||
const output_type_registry_1 = __nccwpck_require__(58012);
|
|
||||||
const artifact_upload_handler_1 = __nccwpck_require__(49063);
|
|
||||||
const sync_1 = __nccwpck_require__(98729);
|
|
||||||
async function runMain() {
|
async function runMain() {
|
||||||
try {
|
try {
|
||||||
if (cli_1.Cli.InitCliMode()) {
|
if (cli_1.Cli.InitCliMode()) {
|
||||||
@@ -54,16 +48,20 @@ async function runMain() {
|
|||||||
}
|
}
|
||||||
model_1.Action.checkCompatibility();
|
model_1.Action.checkCompatibility();
|
||||||
model_1.Cache.verify();
|
model_1.Cache.verify();
|
||||||
|
const enterprise = await (0, orchestrator_plugin_1.loadEnterpriseServices)();
|
||||||
// Always configure git environment for CI reliability
|
// Always configure git environment for CI reliability
|
||||||
reliability_1.BuildReliabilityService.configureGitEnvironment();
|
enterprise?.BuildReliabilityService.configureGitEnvironment();
|
||||||
const { workspace, actionFolder } = model_1.Action;
|
const { workspace, actionFolder } = model_1.Action;
|
||||||
const buildParameters = await model_1.BuildParameters.create();
|
const buildParameters = await model_1.BuildParameters.create();
|
||||||
// If a test suite path is provided, use the test workflow engine
|
// If a test suite path is provided, use the test workflow engine
|
||||||
// instead of the standard build execution path
|
// instead of the standard build execution path
|
||||||
if (buildParameters.testSuitePath) {
|
if (buildParameters.testSuitePath) {
|
||||||
core.info('[TestWorkflow] Test suite path detected, using test workflow engine');
|
core.info('[TestWorkflow] Test suite path detected, using test workflow engine');
|
||||||
const results = await test_workflow_1.TestWorkflowService.executeTestSuite(buildParameters.testSuitePath, buildParameters);
|
const results = await enterprise?.TestWorkflowService.executeTestSuite(buildParameters.testSuitePath, buildParameters);
|
||||||
const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);
|
let totalFailed = 0;
|
||||||
|
for (const result of results || []) {
|
||||||
|
totalFailed += result.failed;
|
||||||
|
}
|
||||||
if (totalFailed > 0) {
|
if (totalFailed > 0) {
|
||||||
core.setFailed(`Test workflow completed with ${totalFailed} failure(s)`);
|
core.setFailed(`Test workflow completed with ${totalFailed} failure(s)`);
|
||||||
}
|
}
|
||||||
@@ -76,15 +74,15 @@ async function runMain() {
|
|||||||
// Pre-build reliability checks
|
// Pre-build reliability checks
|
||||||
if (buildParameters.gitIntegrityCheck) {
|
if (buildParameters.gitIntegrityCheck) {
|
||||||
core.info('Running git integrity checks...');
|
core.info('Running git integrity checks...');
|
||||||
const isHealthy = reliability_1.BuildReliabilityService.checkGitIntegrity(workspace);
|
const isHealthy = enterprise?.BuildReliabilityService.checkGitIntegrity(workspace);
|
||||||
reliability_1.BuildReliabilityService.cleanStaleLockFiles(workspace);
|
enterprise?.BuildReliabilityService.cleanStaleLockFiles(workspace);
|
||||||
reliability_1.BuildReliabilityService.validateSubmoduleBackingStores(workspace);
|
enterprise?.BuildReliabilityService.validateSubmoduleBackingStores(workspace);
|
||||||
if (buildParameters.cleanReservedFilenames) {
|
if (buildParameters.cleanReservedFilenames) {
|
||||||
reliability_1.BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
enterprise?.BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
||||||
}
|
}
|
||||||
if (!isHealthy && buildParameters.gitAutoRecover) {
|
if (!isHealthy && buildParameters.gitAutoRecover) {
|
||||||
core.info('Git corruption detected, attempting automatic recovery...');
|
core.info('Git corruption detected, attempting automatic recovery...');
|
||||||
const recovered = reliability_1.BuildReliabilityService.recoverCorruptedRepo(workspace);
|
const recovered = enterprise?.BuildReliabilityService.recoverCorruptedRepo(workspace);
|
||||||
if (!recovered) {
|
if (!recovered) {
|
||||||
core.warning('Automatic recovery failed. Build may encounter issues.');
|
core.warning('Automatic recovery failed. Build may encounter issues.');
|
||||||
}
|
}
|
||||||
@@ -92,7 +90,7 @@ async function runMain() {
|
|||||||
}
|
}
|
||||||
else if (buildParameters.cleanReservedFilenames) {
|
else if (buildParameters.cleanReservedFilenames) {
|
||||||
// cleanReservedFilenames can run independently of gitIntegrityCheck
|
// cleanReservedFilenames can run independently of gitIntegrityCheck
|
||||||
reliability_1.BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
enterprise?.BuildReliabilityService.cleanReservedFilenames(buildParameters.projectPath);
|
||||||
}
|
}
|
||||||
let exitCode = -1;
|
let exitCode = -1;
|
||||||
// Hot runner path: attempt to use a persistent Unity editor instance
|
// Hot runner path: attempt to use a persistent Unity editor instance
|
||||||
@@ -107,7 +105,10 @@ async function runMain() {
|
|||||||
maxIdleTime: buildParameters.hotRunnerMaxIdle,
|
maxIdleTime: buildParameters.hotRunnerMaxIdle,
|
||||||
maxJobsBeforeRecycle: 0, // no automatic recycle by job count
|
maxJobsBeforeRecycle: 0, // no automatic recycle by job count
|
||||||
};
|
};
|
||||||
const hotRunnerService = new hot_runner_1.HotRunnerService();
|
if (!enterprise?.HotRunnerService) {
|
||||||
|
throw new Error('[HotRunner] Enterprise services required for hot runner mode');
|
||||||
|
}
|
||||||
|
const hotRunnerService = new enterprise.HotRunnerService();
|
||||||
try {
|
try {
|
||||||
await hotRunnerService.initialize(hotRunnerConfig);
|
await hotRunnerService.initialize(hotRunnerConfig);
|
||||||
const result = await hotRunnerService.submitBuild(buildParameters, (output) => {
|
const result = await hotRunnerService.submitBuild(buildParameters, (output) => {
|
||||||
@@ -133,10 +134,9 @@ async function runMain() {
|
|||||||
// Child workspace isolation - restore cached workspace before any other setup
|
// Child workspace isolation - restore cached workspace before any other setup
|
||||||
let childWorkspaceConfig;
|
let childWorkspaceConfig;
|
||||||
if (buildParameters.childWorkspacesEnabled && buildParameters.childWorkspaceName) {
|
if (buildParameters.childWorkspacesEnabled && buildParameters.childWorkspaceName) {
|
||||||
const { ChildWorkspaceService } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(93834)));
|
|
||||||
const cacheRoot = buildParameters.childWorkspaceCacheRoot ||
|
const cacheRoot = buildParameters.childWorkspaceCacheRoot ||
|
||||||
node_path_1.default.join(buildParameters.runnerTempPath || process.env.RUNNER_TEMP || '', 'game-ci-workspaces');
|
node_path_1.default.join(buildParameters.runnerTempPath || process.env.RUNNER_TEMP || '', 'game-ci-workspaces');
|
||||||
childWorkspaceConfig = ChildWorkspaceService.buildConfig({
|
childWorkspaceConfig = enterprise?.ChildWorkspaceService.buildConfig({
|
||||||
childWorkspacesEnabled: buildParameters.childWorkspacesEnabled,
|
childWorkspacesEnabled: buildParameters.childWorkspacesEnabled,
|
||||||
childWorkspaceName: buildParameters.childWorkspaceName,
|
childWorkspaceName: buildParameters.childWorkspaceName,
|
||||||
childWorkspaceCacheRoot: cacheRoot,
|
childWorkspaceCacheRoot: cacheRoot,
|
||||||
@@ -144,54 +144,55 @@ async function runMain() {
|
|||||||
childWorkspaceSeparateLibrary: buildParameters.childWorkspaceSeparateLibrary,
|
childWorkspaceSeparateLibrary: buildParameters.childWorkspaceSeparateLibrary,
|
||||||
});
|
});
|
||||||
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
||||||
const restored = ChildWorkspaceService.initializeWorkspace(projectFullPath, childWorkspaceConfig);
|
const restored = enterprise?.ChildWorkspaceService.initializeWorkspace(projectFullPath, childWorkspaceConfig);
|
||||||
core.info(`Child workspace "${buildParameters.childWorkspaceName}": ${restored ? 'restored from cache' : 'starting fresh'}`);
|
core.info(`Child workspace "${buildParameters.childWorkspaceName}": ${restored ? 'restored from cache' : 'starting fresh'}`);
|
||||||
// Log workspace size for resource tracking
|
// Log workspace size for resource tracking
|
||||||
const size = ChildWorkspaceService.getWorkspaceSize(projectFullPath);
|
const size = enterprise?.ChildWorkspaceService.getWorkspaceSize(projectFullPath);
|
||||||
core.info(`Child workspace size after restore: ${size}`);
|
core.info(`Child workspace size after restore: ${size}`);
|
||||||
}
|
}
|
||||||
// Submodule profile initialization
|
// Submodule profile initialization
|
||||||
if (buildParameters.submoduleProfilePath) {
|
if (buildParameters.submoduleProfilePath) {
|
||||||
const { SubmoduleProfileService } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(88664)));
|
|
||||||
core.info('Initializing submodules from profile...');
|
core.info('Initializing submodules from profile...');
|
||||||
const plan = await SubmoduleProfileService.createInitPlan(buildParameters.submoduleProfilePath, buildParameters.submoduleVariantPath, workspace);
|
const plan = await enterprise?.SubmoduleProfileService.createInitPlan(buildParameters.submoduleProfilePath, buildParameters.submoduleVariantPath, workspace);
|
||||||
await SubmoduleProfileService.execute(plan, workspace, buildParameters.submoduleToken || buildParameters.gitPrivateToken);
|
if (plan) {
|
||||||
|
await enterprise?.SubmoduleProfileService.execute(plan, workspace, buildParameters.submoduleToken || buildParameters.gitPrivateToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Configure custom LFS transfer agent
|
// Configure custom LFS transfer agent
|
||||||
if (buildParameters.lfsTransferAgent) {
|
if (buildParameters.lfsTransferAgent) {
|
||||||
const { LfsAgentService } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(85985)));
|
|
||||||
core.info('Configuring custom LFS transfer agent...');
|
core.info('Configuring custom LFS transfer agent...');
|
||||||
await LfsAgentService.configure(buildParameters.lfsTransferAgent, buildParameters.lfsTransferAgentArgs, buildParameters.lfsStoragePaths ? buildParameters.lfsStoragePaths.split(';') : [], workspace);
|
await enterprise?.LfsAgentService.configure(buildParameters.lfsTransferAgent, buildParameters.lfsTransferAgentArgs, buildParameters.lfsStoragePaths ? buildParameters.lfsStoragePaths.split(';') : [], workspace);
|
||||||
}
|
}
|
||||||
// Local build caching - restore
|
// Local build caching - restore
|
||||||
let cacheRoot = '';
|
let cacheRoot = '';
|
||||||
let cacheKey = '';
|
let cacheKey = '';
|
||||||
if (buildParameters.localCacheEnabled) {
|
if (buildParameters.localCacheEnabled) {
|
||||||
const { LocalCacheService } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(68829)));
|
cacheRoot = enterprise?.LocalCacheService.resolveCacheRoot(buildParameters) || '';
|
||||||
cacheRoot = LocalCacheService.resolveCacheRoot(buildParameters);
|
cacheKey =
|
||||||
cacheKey = LocalCacheService.generateCacheKey(buildParameters.targetPlatform, buildParameters.editorVersion, buildParameters.branch || '');
|
enterprise?.LocalCacheService.generateCacheKey(buildParameters.targetPlatform, buildParameters.editorVersion, buildParameters.branch || '') || '';
|
||||||
if (buildParameters.localCacheLfs) {
|
if (buildParameters.localCacheLfs) {
|
||||||
await LocalCacheService.restoreLfsCache(workspace, cacheRoot, cacheKey);
|
await enterprise?.LocalCacheService.restoreLfsCache(workspace, cacheRoot, cacheKey);
|
||||||
}
|
}
|
||||||
if (buildParameters.localCacheLibrary) {
|
if (buildParameters.localCacheLibrary) {
|
||||||
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
||||||
await LocalCacheService.restoreLibraryCache(projectFullPath, cacheRoot, cacheKey);
|
await enterprise?.LocalCacheService.restoreLibraryCache(projectFullPath, cacheRoot, cacheKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Git hooks — opt-in only. When disabled (default), do not touch hooks at all.
|
// Git hooks — opt-in only. When disabled (default), do not touch hooks at all.
|
||||||
if (buildParameters.gitHooksEnabled) {
|
if (buildParameters.gitHooksEnabled) {
|
||||||
const { GitHooksService } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(9146)));
|
await enterprise?.GitHooksService.installHooks(workspace);
|
||||||
await GitHooksService.installHooks(workspace);
|
|
||||||
if (buildParameters.gitHooksSkipList) {
|
if (buildParameters.gitHooksSkipList) {
|
||||||
const environment = GitHooksService.configureSkipList(buildParameters.gitHooksSkipList.split(','));
|
const environment = enterprise?.GitHooksService.configureSkipList(buildParameters.gitHooksSkipList.split(','));
|
||||||
|
if (environment) {
|
||||||
Object.assign(process.env, environment);
|
Object.assign(process.env, environment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Apply incremental sync strategy before build
|
// Apply incremental sync strategy before build
|
||||||
const syncStrategy = buildParameters.syncStrategy;
|
const syncStrategy = buildParameters.syncStrategy;
|
||||||
if (syncStrategy !== 'full') {
|
if (syncStrategy !== 'full') {
|
||||||
core.info(`[Sync] Applying sync strategy: ${syncStrategy}`);
|
core.info(`[Sync] Applying sync strategy: ${syncStrategy}`);
|
||||||
await applySyncStrategy(buildParameters, workspace);
|
await applySyncStrategy(buildParameters, workspace, enterprise);
|
||||||
}
|
}
|
||||||
await platform_setup_1.default.setup(buildParameters, actionFolder);
|
await platform_setup_1.default.setup(buildParameters, actionFolder);
|
||||||
exitCode =
|
exitCode =
|
||||||
@@ -204,29 +205,27 @@ async function runMain() {
|
|||||||
});
|
});
|
||||||
// Local build caching - save
|
// Local build caching - save
|
||||||
if (buildParameters.localCacheEnabled) {
|
if (buildParameters.localCacheEnabled) {
|
||||||
const { LocalCacheService } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(68829)));
|
|
||||||
if (buildParameters.localCacheLibrary) {
|
if (buildParameters.localCacheLibrary) {
|
||||||
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
||||||
await LocalCacheService.saveLibraryCache(projectFullPath, cacheRoot, cacheKey);
|
await enterprise?.LocalCacheService.saveLibraryCache(projectFullPath, cacheRoot, cacheKey);
|
||||||
}
|
}
|
||||||
if (buildParameters.localCacheLfs) {
|
if (buildParameters.localCacheLfs) {
|
||||||
await LocalCacheService.saveLfsCache(workspace, cacheRoot, cacheKey);
|
await enterprise?.LocalCacheService.saveLfsCache(workspace, cacheRoot, cacheKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Child workspace isolation - save workspace for next run
|
// Child workspace isolation - save workspace for next run
|
||||||
if (childWorkspaceConfig && childWorkspaceConfig.enabled) {
|
if (childWorkspaceConfig && childWorkspaceConfig.enabled) {
|
||||||
const { ChildWorkspaceService } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(93834)));
|
|
||||||
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
const projectFullPath = node_path_1.default.join(workspace, buildParameters.projectPath);
|
||||||
const preSaveSize = ChildWorkspaceService.getWorkspaceSize(projectFullPath);
|
const preSaveSize = enterprise?.ChildWorkspaceService.getWorkspaceSize(projectFullPath);
|
||||||
core.info(`Child workspace size before save: ${preSaveSize}`);
|
core.info(`Child workspace size before save: ${preSaveSize}`);
|
||||||
ChildWorkspaceService.saveWorkspace(projectFullPath, childWorkspaceConfig);
|
enterprise?.ChildWorkspaceService.saveWorkspace(projectFullPath, childWorkspaceConfig);
|
||||||
core.info(`Child workspace "${buildParameters.childWorkspaceName}" saved to cache`);
|
core.info(`Child workspace "${buildParameters.childWorkspaceName}" saved to cache`);
|
||||||
}
|
}
|
||||||
// Revert overlays after job completion if configured
|
// Revert overlays after job completion if configured
|
||||||
if (buildParameters.syncRevertAfter && syncStrategy !== 'full') {
|
if (buildParameters.syncRevertAfter && syncStrategy !== 'full') {
|
||||||
core.info('[Sync] Reverting overlay changes after job completion');
|
core.info('[Sync] Reverting overlay changes after job completion');
|
||||||
try {
|
try {
|
||||||
await sync_1.IncrementalSyncService.revertOverlays(workspace, buildParameters.syncStatePath);
|
await enterprise?.IncrementalSyncService.revertOverlays(workspace, buildParameters.syncStatePath);
|
||||||
}
|
}
|
||||||
catch (revertError) {
|
catch (revertError) {
|
||||||
core.warning(`[Sync] Overlay revert failed: ${revertError.message}`);
|
core.warning(`[Sync] Overlay revert failed: ${revertError.message}`);
|
||||||
@@ -235,14 +234,18 @@ async function runMain() {
|
|||||||
exitCode = await runColdBuild(buildParameters, baseImage, workspace, actionFolder);
|
exitCode = await runColdBuild(buildParameters, baseImage, workspace, actionFolder);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await model_1.Orchestrator.run(buildParameters, baseImage.toString());
|
const orchestrator = await (0, orchestrator_plugin_1.loadOrchestrator)();
|
||||||
|
if (!orchestrator) {
|
||||||
|
throw new Error('Orchestrator package not available. Install @game-ci/orchestrator or use providerStrategy=local.');
|
||||||
|
}
|
||||||
|
await orchestrator.run(buildParameters, baseImage.toString());
|
||||||
exitCode = 0;
|
exitCode = 0;
|
||||||
}
|
}
|
||||||
// Post-build: archive and enforce retention
|
// Post-build: archive and enforce retention
|
||||||
if (buildParameters.buildArchiveEnabled && exitCode === 0) {
|
if (buildParameters.buildArchiveEnabled && exitCode === 0) {
|
||||||
core.info('Archiving build output...');
|
core.info('Archiving build output...');
|
||||||
reliability_1.BuildReliabilityService.archiveBuildOutput(buildParameters.buildPath, buildParameters.buildArchivePath);
|
enterprise?.BuildReliabilityService.archiveBuildOutput(buildParameters.buildPath, buildParameters.buildArchivePath);
|
||||||
reliability_1.BuildReliabilityService.enforceRetention(buildParameters.buildArchivePath, buildParameters.buildArchiveRetention);
|
enterprise?.BuildReliabilityService.enforceRetention(buildParameters.buildArchivePath, buildParameters.buildArchiveRetention);
|
||||||
}
|
}
|
||||||
// Set output
|
// Set output
|
||||||
await model_1.Output.setBuildVersion(buildParameters.buildVersion);
|
await model_1.Output.setBuildVersion(buildParameters.buildVersion);
|
||||||
@@ -256,7 +259,7 @@ async function runMain() {
|
|||||||
const customTypes = JSON.parse(buildParameters.artifactCustomTypes);
|
const customTypes = JSON.parse(buildParameters.artifactCustomTypes);
|
||||||
if (Array.isArray(customTypes)) {
|
if (Array.isArray(customTypes)) {
|
||||||
for (const ct of customTypes) {
|
for (const ct of customTypes) {
|
||||||
output_type_registry_1.OutputTypeRegistry.registerType({
|
enterprise?.OutputTypeRegistry.registerType({
|
||||||
name: ct.name,
|
name: ct.name,
|
||||||
defaultPath: ct.defaultPath || ct.pattern || `./${ct.name}/`,
|
defaultPath: ct.defaultPath || ct.pattern || `./${ct.name}/`,
|
||||||
description: ct.description || `Custom output type: ${ct.name}`,
|
description: ct.description || `Custom output type: ${ct.name}`,
|
||||||
@@ -271,18 +274,22 @@ async function runMain() {
|
|||||||
}
|
}
|
||||||
// Collect outputs and generate manifest
|
// Collect outputs and generate manifest
|
||||||
const manifestPath = node_path_1.default.join(buildParameters.projectPath, 'output-manifest.json');
|
const manifestPath = node_path_1.default.join(buildParameters.projectPath, 'output-manifest.json');
|
||||||
const manifest = await output_service_1.OutputService.collectOutputs(buildParameters.projectPath, buildParameters.buildGuid, buildParameters.artifactOutputTypes, manifestPath);
|
const manifest = await enterprise?.OutputService.collectOutputs(buildParameters.projectPath, buildParameters.buildGuid, buildParameters.artifactOutputTypes, manifestPath);
|
||||||
core.setOutput('artifactManifestPath', manifestPath);
|
core.setOutput('artifactManifestPath', manifestPath);
|
||||||
|
if (manifest) {
|
||||||
// Upload artifacts
|
// Upload artifacts
|
||||||
const uploadConfig = artifact_upload_handler_1.ArtifactUploadHandler.parseConfig(buildParameters.artifactUploadTarget, buildParameters.artifactUploadPath || undefined, buildParameters.artifactCompression, buildParameters.artifactRetentionDays);
|
const uploadConfig = enterprise?.ArtifactUploadHandler.parseConfig(buildParameters.artifactUploadTarget, buildParameters.artifactUploadPath || undefined, buildParameters.artifactCompression, buildParameters.artifactRetentionDays);
|
||||||
const uploadResult = await artifact_upload_handler_1.ArtifactUploadHandler.uploadArtifacts(manifest, uploadConfig, buildParameters.projectPath);
|
if (uploadConfig) {
|
||||||
if (!uploadResult.success) {
|
const uploadResult = await enterprise?.ArtifactUploadHandler.uploadArtifacts(manifest, uploadConfig, buildParameters.projectPath);
|
||||||
|
if (uploadResult && !uploadResult.success) {
|
||||||
core.warning(`Artifact upload completed with errors: ${uploadResult.entries
|
core.warning(`Artifact upload completed with errors: ${uploadResult.entries
|
||||||
.filter((e) => !e.success)
|
.filter((entry) => !entry.success)
|
||||||
.map((e) => `${e.type}: ${e.error}`)
|
.map((entry) => `${entry.type}: ${entry.error}`)
|
||||||
.join('; ')}`);
|
.join('; ')}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (artifactError) {
|
catch (artifactError) {
|
||||||
core.warning(`Artifact collection/upload failed: ${artifactError.message}`);
|
core.warning(`Artifact collection/upload failed: ${artifactError.message}`);
|
||||||
}
|
}
|
||||||
@@ -307,16 +314,25 @@ async function runColdBuild(buildParameters, baseImage, workspace, actionFolder)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await model_1.Orchestrator.run(buildParameters, baseImage.toString());
|
const orchestrator = await (0, orchestrator_plugin_1.loadOrchestrator)();
|
||||||
|
if (!orchestrator) {
|
||||||
|
throw new Error('Orchestrator package not available. Install @game-ci/orchestrator or use providerStrategy=local.');
|
||||||
|
}
|
||||||
|
await orchestrator.run(buildParameters, baseImage.toString());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Apply the configured sync strategy to the workspace before build.
|
* Apply the configured sync strategy to the workspace before build.
|
||||||
*/
|
*/
|
||||||
async function applySyncStrategy(buildParameters, workspace) {
|
async function applySyncStrategy(buildParameters, workspace, enterprise) {
|
||||||
|
if (!enterprise?.IncrementalSyncService) {
|
||||||
|
core.warning('[Sync] Enterprise services not available, skipping sync strategy');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { IncrementalSyncService } = enterprise;
|
||||||
const strategy = buildParameters.syncStrategy;
|
const strategy = buildParameters.syncStrategy;
|
||||||
const resolvedStrategy = sync_1.IncrementalSyncService.resolveStrategy(strategy, workspace, buildParameters.syncStatePath);
|
const resolvedStrategy = IncrementalSyncService.resolveStrategy(strategy, workspace, buildParameters.syncStatePath);
|
||||||
if (resolvedStrategy === 'full') {
|
if (resolvedStrategy === 'full') {
|
||||||
core.info('[Sync] Resolved to full sync (no incremental state available)');
|
core.info('[Sync] Resolved to full sync (no incremental state available)');
|
||||||
return;
|
return;
|
||||||
@@ -324,7 +340,7 @@ async function applySyncStrategy(buildParameters, workspace) {
|
|||||||
switch (resolvedStrategy) {
|
switch (resolvedStrategy) {
|
||||||
case 'git-delta': {
|
case 'git-delta': {
|
||||||
const targetReference = buildParameters.gitSha || buildParameters.branch;
|
const targetReference = buildParameters.gitSha || buildParameters.branch;
|
||||||
const changedFiles = await sync_1.IncrementalSyncService.syncGitDelta(workspace, targetReference, buildParameters.syncStatePath);
|
const changedFiles = await IncrementalSyncService.syncGitDelta(workspace, targetReference, buildParameters.syncStatePath);
|
||||||
core.info(`[Sync] Git delta sync applied: ${changedFiles} file(s) changed`);
|
core.info(`[Sync] Git delta sync applied: ${changedFiles} file(s) changed`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -332,7 +348,7 @@ async function applySyncStrategy(buildParameters, workspace) {
|
|||||||
if (!buildParameters.syncInputRef) {
|
if (!buildParameters.syncInputRef) {
|
||||||
throw new Error('[Sync] direct-input strategy requires syncInputRef to be set');
|
throw new Error('[Sync] direct-input strategy requires syncInputRef to be set');
|
||||||
}
|
}
|
||||||
const overlays = await sync_1.IncrementalSyncService.applyDirectInput(workspace, buildParameters.syncInputRef, buildParameters.syncStorageRemote || undefined, buildParameters.syncStatePath);
|
const overlays = await IncrementalSyncService.applyDirectInput(workspace, buildParameters.syncInputRef, buildParameters.syncStorageRemote || undefined, buildParameters.syncStatePath);
|
||||||
core.info(`[Sync] Direct input applied: ${overlays.length} overlay(s)`);
|
core.info(`[Sync] Direct input applied: ${overlays.length} overlay(s)`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -340,7 +356,7 @@ async function applySyncStrategy(buildParameters, workspace) {
|
|||||||
if (!buildParameters.syncInputRef) {
|
if (!buildParameters.syncInputRef) {
|
||||||
throw new Error('[Sync] storage-pull strategy requires syncInputRef to be set');
|
throw new Error('[Sync] storage-pull strategy requires syncInputRef to be set');
|
||||||
}
|
}
|
||||||
const pulledFiles = await sync_1.IncrementalSyncService.syncStoragePull(workspace, buildParameters.syncInputRef, {
|
const pulledFiles = await IncrementalSyncService.syncStoragePull(workspace, buildParameters.syncInputRef, {
|
||||||
rcloneRemote: buildParameters.syncStorageRemote || undefined,
|
rcloneRemote: buildParameters.syncStorageRemote || undefined,
|
||||||
syncRevertAfter: buildParameters.syncRevertAfter,
|
syncRevertAfter: buildParameters.syncRevertAfter,
|
||||||
statePath: buildParameters.syncStatePath,
|
statePath: buildParameters.syncStatePath,
|
||||||
@@ -2533,6 +2549,95 @@ class MacBuilder {
|
|||||||
exports["default"] = MacBuilder;
|
exports["default"] = MacBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 2075:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Orchestrator plugin loader.
|
||||||
|
*
|
||||||
|
* After extraction, the orchestrator lives in @game-ci/orchestrator.
|
||||||
|
* This module provides a thin loader that dynamically imports it,
|
||||||
|
* falling back gracefully if the package is not installed.
|
||||||
|
*/
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.loadEnterpriseServices = exports.loadOrchestrator = void 0;
|
||||||
|
const core = __importStar(__nccwpck_require__(42186));
|
||||||
|
/**
|
||||||
|
* Attempt to load the orchestrator package.
|
||||||
|
* Returns undefined if @game-ci/orchestrator is not installed.
|
||||||
|
*/
|
||||||
|
async function loadOrchestrator() {
|
||||||
|
try {
|
||||||
|
// During extraction: use local source (will become package import)
|
||||||
|
const { default: Orchestrator } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(8330)));
|
||||||
|
return {
|
||||||
|
run: Orchestrator.run.bind(Orchestrator),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// Package not installed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.loadOrchestrator = loadOrchestrator;
|
||||||
|
/**
|
||||||
|
* Attempt to load enterprise services for local builds.
|
||||||
|
* These services (child workspaces, local cache, git hooks, etc.)
|
||||||
|
* are part of the orchestrator package but also used in local builds.
|
||||||
|
*/
|
||||||
|
async function loadEnterpriseServices() {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
ChildWorkspaceService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(93834))))
|
||||||
|
.ChildWorkspaceService,
|
||||||
|
LocalCacheService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(68829)))).LocalCacheService,
|
||||||
|
SubmoduleProfileService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(88664))))
|
||||||
|
.SubmoduleProfileService,
|
||||||
|
LfsAgentService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(85985)))).LfsAgentService,
|
||||||
|
GitHooksService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(9146)))).GitHooksService,
|
||||||
|
IncrementalSyncService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(98729)))).IncrementalSyncService,
|
||||||
|
BuildReliabilityService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(9842)))).BuildReliabilityService,
|
||||||
|
TestWorkflowService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(22377)))).TestWorkflowService,
|
||||||
|
HotRunnerService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(74283)))).HotRunnerService,
|
||||||
|
OutputService: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(18795)))).OutputService,
|
||||||
|
OutputTypeRegistry: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(58012)))).OutputTypeRegistry,
|
||||||
|
ArtifactUploadHandler: (await Promise.resolve().then(() => __importStar(__nccwpck_require__(49063))))
|
||||||
|
.ArtifactUploadHandler,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
core.warning(`Enterprise services not available: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.loadEnterpriseServices = loadEnterpriseServices;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 41594:
|
/***/ 41594:
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user