Rename Cloud Runner to Orchestrator (#775)

* Rename "Cloud Runner" to "Orchestrator" across entire codebase

Breaking change: All CloudRunner classes, options, environment variables,
and action.yml inputs have been renamed to Orchestrator equivalents.

- Renamed src/model/cloud-runner/ directory to src/model/orchestrator/
- Renamed all cloud-runner-* files to orchestrator-*
- Renamed all CloudRunner* classes to Orchestrator* (15+ classes)
- Renamed all cloudRunner* properties to orchestrator* equivalents
- Renamed CLOUD_RUNNER_* env vars to ORCHESTRATOR_*
- Updated action.yml [CloudRunner] markers to [Orchestrator]
- Updated workflow files and package.json test scripts
- Updated all runtime strings (cache paths, log messages, branch refs)
- Rebuilt dist/index.js

No backward compatibility layer is provided.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Remove tracked log/temp files and add to .gitignore

Remove $LOG_FILE and temp/job-log.txt debug artifacts that should
not be in the repository.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Frostebite
2026-03-04 21:53:47 +00:00
committed by GitHub
parent f3849ee1c9
commit 9d475434d3
117 changed files with 4756 additions and 4745 deletions
@@ -0,0 +1,4 @@
class OrchestratorConstants {
static alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';
}
export default OrchestratorConstants;
@@ -0,0 +1,5 @@
class OrchestratorEnvironmentVariable {
public name!: string;
public value!: string;
}
export default OrchestratorEnvironmentVariable;
@@ -0,0 +1,90 @@
import path from 'node:path';
import OrchestratorOptions from './orchestrator-options';
import Orchestrator from '../orchestrator';
import BuildParameters from '../../build-parameters';
export class OrchestratorFolders {
public static readonly repositoryFolder = 'repo';
public static ToLinuxFolder(folder: string) {
return folder.replace(/\\/g, `/`);
}
// Only the following paths that do not start a path.join with another "Full" suffixed property need to start with an absolute /
public static get uniqueOrchestratorJobFolderAbsolute(): string {
return Orchestrator.buildParameters && BuildParameters.shouldUseRetainedWorkspaceMode(Orchestrator.buildParameters)
? path.join(`/`, OrchestratorFolders.buildVolumeFolder, Orchestrator.lockedWorkspace)
: path.join(`/`, OrchestratorFolders.buildVolumeFolder, Orchestrator.buildParameters.buildGuid);
}
public static get cacheFolderForAllFull(): string {
return path.join('/', OrchestratorFolders.buildVolumeFolder, OrchestratorFolders.cacheFolder);
}
public static get cacheFolderForCacheKeyFull(): string {
return path.join(
'/',
OrchestratorFolders.buildVolumeFolder,
OrchestratorFolders.cacheFolder,
Orchestrator.buildParameters.cacheKey,
);
}
public static get builderPathAbsolute(): string {
return path.join(
OrchestratorOptions.useSharedBuilder
? `/${OrchestratorFolders.buildVolumeFolder}`
: OrchestratorFolders.uniqueOrchestratorJobFolderAbsolute,
`builder`,
);
}
public static get repoPathAbsolute(): string {
return path.join(OrchestratorFolders.uniqueOrchestratorJobFolderAbsolute, OrchestratorFolders.repositoryFolder);
}
public static get projectPathAbsolute(): string {
return path.join(OrchestratorFolders.repoPathAbsolute, Orchestrator.buildParameters.projectPath);
}
public static get libraryFolderAbsolute(): string {
return path.join(OrchestratorFolders.projectPathAbsolute, `Library`);
}
public static get projectBuildFolderAbsolute(): string {
return path.join(OrchestratorFolders.repoPathAbsolute, Orchestrator.buildParameters.buildPath);
}
public static get lfsFolderAbsolute(): string {
return path.join(OrchestratorFolders.repoPathAbsolute, `.git`, `lfs`);
}
public static get purgeRemoteCaching(): boolean {
return process.env.PURGE_REMOTE_BUILDER_CACHE !== undefined;
}
public static get lfsCacheFolderFull() {
return path.join(OrchestratorFolders.cacheFolderForCacheKeyFull, `lfs`);
}
public static get libraryCacheFolderFull() {
return path.join(OrchestratorFolders.cacheFolderForCacheKeyFull, `Library`);
}
public static get unityBuilderRepoUrl(): string {
return `https://${Orchestrator.buildParameters.gitPrivateToken}@github.com/${Orchestrator.buildParameters.orchestratorRepoName}.git`;
}
public static get targetBuildRepoUrl(): string {
return `https://${Orchestrator.buildParameters.gitPrivateToken}@github.com/${Orchestrator.buildParameters.githubRepo}.git`;
}
public static get buildVolumeFolder() {
return 'data';
}
public static get cacheFolder() {
return 'cache';
}
}
@@ -0,0 +1,11 @@
import { customAlphabet } from 'nanoid';
import OrchestratorConstants from './orchestrator-constants';
class OrchestratorNamespace {
static generateGuid(runNumber: string | number, platform: string) {
const nanoid = customAlphabet(OrchestratorConstants.alphabet, 4);
return `${runNumber}-${platform.toLowerCase().replace('standalone', '')}-${nanoid()}`;
}
}
export default OrchestratorNamespace;
@@ -0,0 +1,10 @@
import Input from '../../input';
import OrchestratorOptions from './orchestrator-options';
class OrchestratorOptionsReader {
static GetProperties() {
return [...Object.getOwnPropertyNames(Input), ...Object.getOwnPropertyNames(OrchestratorOptions)];
}
}
export default OrchestratorOptionsReader;
@@ -0,0 +1,338 @@
import { Cli } from '../../cli/cli';
import OrchestratorQueryOverride from './orchestrator-query-override';
import GitHub from '../../github';
import * as core from '@actions/core';
class OrchestratorOptions {
// ### ### ###
// Input Handling
// ### ### ###
public static getInput(query: string): string | undefined {
if (GitHub.githubInputEnabled) {
const coreInput = core.getInput(query);
if (coreInput && coreInput !== '') {
return coreInput;
}
}
const alternativeQuery = OrchestratorOptions.ToEnvVarFormat(query);
// Query input sources
if (Cli.query(query, alternativeQuery)) {
return Cli.query(query, alternativeQuery);
}
if (OrchestratorQueryOverride.query(query, alternativeQuery)) {
return OrchestratorQueryOverride.query(query, alternativeQuery);
}
if (process.env[query] !== undefined) {
return process.env[query];
}
if (alternativeQuery !== query && process.env[alternativeQuery] !== undefined) {
return process.env[alternativeQuery];
}
}
public static ToEnvVarFormat(input: string): string {
if (input.toUpperCase() === input) {
return input;
}
return input
.replace(/([A-Z])/g, ' $1')
.trim()
.toUpperCase()
.replace(/ /g, '_');
}
// ### ### ###
// Provider parameters
// ### ### ###
static get region(): string {
return OrchestratorOptions.getInput('region') || 'eu-west-2';
}
// ### ### ###
// GitHub parameters
// ### ### ###
static get githubChecks(): boolean {
const value = OrchestratorOptions.getInput('githubChecks');
return value === `true` || false;
}
static get githubCheckId(): string {
return OrchestratorOptions.getInput('githubCheckId') || ``;
}
static get githubOwner(): string {
return OrchestratorOptions.getInput('githubOwner') || OrchestratorOptions.githubRepo?.split(`/`)[0] || '';
}
static get githubRepoName(): string {
return OrchestratorOptions.getInput('githubRepoName') || OrchestratorOptions.githubRepo?.split(`/`)[1] || '';
}
static get orchestratorRepoName(): string {
return OrchestratorOptions.getInput('orchestratorRepoName') || 'game-ci/unity-builder';
}
static get cloneDepth(): string {
return OrchestratorOptions.getInput('cloneDepth') || '50';
}
static get finalHooks(): string[] {
return OrchestratorOptions.getInput('finalHooks')?.split(',') || [];
}
// ### ### ###
// Git syncronization parameters
// ### ### ###
static get githubRepo(): string | undefined {
return (
OrchestratorOptions.getInput('GITHUB_REPOSITORY') || OrchestratorOptions.getInput('GITHUB_REPO') || undefined
);
}
static get branch(): string {
if (OrchestratorOptions.getInput(`GITHUB_REF`)) {
return (
OrchestratorOptions.getInput(`GITHUB_REF`)?.replace('refs/', '').replace(`head/`, '').replace(`heads/`, '') ||
``
);
} else if (OrchestratorOptions.getInput('branch')) {
return OrchestratorOptions.getInput('branch') || ``;
} else {
return '';
}
}
// ### ### ###
// Orchestrator parameters
// ### ### ###
static get buildPlatform(): string {
const input = OrchestratorOptions.getInput('buildPlatform');
if (input && input !== '') {
return input;
}
if (OrchestratorOptions.providerStrategy !== 'local') {
return 'linux';
}
return process.platform;
}
static get orchestratorBranch(): string {
return OrchestratorOptions.getInput('orchestratorBranch') || 'main';
}
static get providerStrategy(): string {
const provider =
OrchestratorOptions.getInput('orchestratorCluster') || OrchestratorOptions.getInput('providerStrategy');
if (Cli.isCliMode) {
return provider || 'aws';
}
return provider || 'local';
}
static get containerCpu(): string {
return OrchestratorOptions.getInput('containerCpu') || `1024`;
}
static get containerMemory(): string {
return OrchestratorOptions.getInput('containerMemory') || `3072`;
}
static get containerNamespace(): string {
return OrchestratorOptions.getInput('containerNamespace') || `default`;
}
static get customJob(): string {
return OrchestratorOptions.getInput('customJob') || '';
}
// ### ### ###
// Custom commands from files parameters
// ### ### ###
static get containerHookFiles(): string[] {
return OrchestratorOptions.getInput('containerHookFiles')?.split(`,`) || [];
}
static get commandHookFiles(): string[] {
return OrchestratorOptions.getInput('commandHookFiles')?.split(`,`) || [];
}
// ### ### ###
// Custom commands from yaml parameters
// ### ### ###
static get commandHooks(): string {
return OrchestratorOptions.getInput('commandHooks') || '';
}
static get postBuildContainerHooks(): string {
return OrchestratorOptions.getInput('postBuildContainerHooks') || '';
}
static get preBuildContainerHooks(): string {
return OrchestratorOptions.getInput('preBuildContainerHooks') || '';
}
// ### ### ###
// Input override handling
// ### ### ###
static get pullInputList(): string[] {
return OrchestratorOptions.getInput('pullInputList')?.split(`,`) || [];
}
static get inputPullCommand(): string {
const value = OrchestratorOptions.getInput('inputPullCommand');
if (value === 'gcp-secret-manager') {
return 'gcloud secrets versions access 1 --secret="{0}"';
} else if (value === 'aws-secret-manager') {
return 'aws secretsmanager get-secret-value --secret-id {0}';
}
return value || '';
}
// ### ### ###
// Aws
// ### ### ###
static get awsStackName() {
return OrchestratorOptions.getInput('awsStackName') || 'game-ci';
}
static get awsEndpoint(): string | undefined {
return OrchestratorOptions.getInput('awsEndpoint');
}
static get awsCloudFormationEndpoint(): string | undefined {
return OrchestratorOptions.getInput('awsCloudFormationEndpoint') || OrchestratorOptions.awsEndpoint;
}
static get awsEcsEndpoint(): string | undefined {
return OrchestratorOptions.getInput('awsEcsEndpoint') || OrchestratorOptions.awsEndpoint;
}
static get awsKinesisEndpoint(): string | undefined {
return OrchestratorOptions.getInput('awsKinesisEndpoint') || OrchestratorOptions.awsEndpoint;
}
static get awsCloudWatchLogsEndpoint(): string | undefined {
return OrchestratorOptions.getInput('awsCloudWatchLogsEndpoint') || OrchestratorOptions.awsEndpoint;
}
static get awsS3Endpoint(): string | undefined {
return OrchestratorOptions.getInput('awsS3Endpoint') || OrchestratorOptions.awsEndpoint;
}
// ### ### ###
// Storage
// ### ### ###
static get storageProvider(): string {
return OrchestratorOptions.getInput('storageProvider') || 's3';
}
static get rcloneRemote(): string {
return OrchestratorOptions.getInput('rcloneRemote') || '';
}
// ### ### ###
// K8s
// ### ### ###
static get kubeConfig(): string {
return OrchestratorOptions.getInput('kubeConfig') || '';
}
static get kubeVolume(): string {
return OrchestratorOptions.getInput('kubeVolume') || '';
}
static get kubeVolumeSize(): string {
return OrchestratorOptions.getInput('kubeVolumeSize') || '25Gi';
}
static get kubeStorageClass(): string {
return OrchestratorOptions.getInput('kubeStorageClass') || '';
}
// ### ### ###
// Caching
// ### ### ###
static get cacheKey(): string {
return OrchestratorOptions.getInput('cacheKey') || OrchestratorOptions.branch;
}
// ### ### ###
// Utility Parameters
// ### ### ###
static get orchestratorDebug(): boolean {
return (
OrchestratorOptions.getInput(`orchestratorTests`) === `true` ||
OrchestratorOptions.getInput(`orchestratorDebug`) === `true` ||
OrchestratorOptions.getInput(`orchestratorDebugTree`) === `true` ||
OrchestratorOptions.getInput(`orchestratorDebugEnv`) === `true` ||
false
);
}
static get skipLfs(): boolean {
return OrchestratorOptions.getInput(`skipLfs`) === `true`;
}
static get skipCache(): boolean {
return OrchestratorOptions.getInput(`skipCache`) === `true`;
}
public static get asyncOrchestrator(): boolean {
return OrchestratorOptions.getInput('asyncOrchestrator') === 'true';
}
public static get resourceTracking(): boolean {
return OrchestratorOptions.getInput('resourceTracking') === 'true';
}
public static get useLargePackages(): boolean {
return OrchestratorOptions.getInput(`useLargePackages`) === `true`;
}
public static get useSharedBuilder(): boolean {
return OrchestratorOptions.getInput(`useSharedBuilder`) === `true`;
}
public static get useCompressionStrategy(): boolean {
return OrchestratorOptions.getInput(`useCompressionStrategy`) === `true`;
}
public static get useCleanupCron(): boolean {
return (OrchestratorOptions.getInput(`useCleanupCron`) || 'true') === 'true';
}
// ### ### ###
// Retained Workspace
// ### ### ###
public static get maxRetainedWorkspaces(): string {
return OrchestratorOptions.getInput(`maxRetainedWorkspaces`) || `0`;
}
// ### ### ###
// Garbage Collection
// ### ### ###
static get garbageMaxAge(): number {
return Number(OrchestratorOptions.getInput(`garbageMaxAge`)) || 24;
}
}
export default OrchestratorOptions;
@@ -0,0 +1,67 @@
import Input from '../../input';
import { GenericInputReader } from '../../input-readers/generic-input-reader';
import OrchestratorOptions from './orchestrator-options';
const formatFunction = (value: string, arguments_: any[]) => {
for (const element of arguments_) {
value = value.replace(`{${element.key}}`, element.value);
}
return value;
};
class OrchestratorQueryOverride {
static queryOverrides: { [key: string]: string } | undefined;
// TODO accept premade secret sources or custom secret source definition yamls
public static query(key: string, alternativeKey: string) {
if (OrchestratorQueryOverride.queryOverrides && OrchestratorQueryOverride.queryOverrides[key] !== undefined) {
return OrchestratorQueryOverride.queryOverrides[key];
}
if (
OrchestratorQueryOverride.queryOverrides &&
alternativeKey &&
OrchestratorQueryOverride.queryOverrides[alternativeKey] !== undefined
) {
return OrchestratorQueryOverride.queryOverrides[alternativeKey];
}
return;
}
private static shouldUseOverride(query: string) {
if (OrchestratorOptions.inputPullCommand !== '') {
if (OrchestratorOptions.pullInputList.length > 0) {
const doesInclude =
OrchestratorOptions.pullInputList.includes(query) ||
OrchestratorOptions.pullInputList.includes(Input.ToEnvVarFormat(query));
return doesInclude ? true : false;
} else {
return true;
}
}
}
private static async queryOverride(query: string) {
if (!this.shouldUseOverride(query)) {
throw new Error(`Should not be trying to run override query on ${query}`);
}
return await GenericInputReader.Run(
formatFunction(OrchestratorOptions.inputPullCommand, [{ key: 0, value: query }]),
);
}
public static async PopulateQueryOverrideInput() {
const queries = OrchestratorOptions.pullInputList;
OrchestratorQueryOverride.queryOverrides = {};
for (const element of queries) {
if (OrchestratorQueryOverride.shouldUseOverride(element)) {
OrchestratorQueryOverride.queryOverrides[element] = await OrchestratorQueryOverride.queryOverride(element);
}
}
}
}
export default OrchestratorQueryOverride;
@@ -0,0 +1,6 @@
class OrchestratorSecret {
public ParameterKey!: string;
public EnvironmentVariable!: string;
public ParameterValue!: string;
}
export default OrchestratorSecret;
@@ -0,0 +1,3 @@
export class OrchestratorStatics {
public static readonly logPrefix = `Orchestrator`;
}
@@ -0,0 +1,13 @@
import OrchestratorEnvironmentVariable from './orchestrator-environment-variable';
import OrchestratorSecret from './orchestrator-secret';
export class OrchestratorStepParameters {
public image: string;
public environment: OrchestratorEnvironmentVariable[];
public secrets: OrchestratorSecret[];
constructor(image: string, environmentVariables: OrchestratorEnvironmentVariable[], secrets: OrchestratorSecret[]) {
this.image = image;
this.environment = environmentVariables;
this.secrets = secrets;
}
}