import { customAlphabet } from 'nanoid'; import AndroidVersioning from './android-versioning'; import OrchestratorConstants from './orchestrator/options/orchestrator-constants'; import OrchestratorBuildGuid from './orchestrator/options/orchestrator-guid'; import Input from './input'; import Platform from './platform'; import UnityVersioning from './unity-versioning'; import Versioning from './versioning'; import { GitRepoReader } from './input-readers/git-repo'; import { GithubCliReader } from './input-readers/github-cli'; import { Cli } from './cli/cli'; import GitHub from './github'; import OrchestratorOptions from './orchestrator/options/orchestrator-options'; import Orchestrator from './orchestrator/orchestrator'; import * as core from '@actions/core'; class BuildParameters { // eslint-disable-next-line no-undef [key: string]: any; public editorVersion!: string; public customImage!: string; public unitySerial!: string; public unityLicensingServer!: string; public skipActivation!: string; public runnerTempPath!: string; public targetPlatform!: string; public projectPath!: string; public buildProfile!: string; public buildName!: string; public buildPath!: string; public buildFile!: string; public buildMethod!: string; public buildVersion!: string; public manualExit!: boolean; public enableGpu!: boolean; public androidVersionCode!: string; public androidKeystoreName!: string; public androidKeystoreBase64!: string; public androidKeystorePass!: string; public androidKeyaliasName!: string; public androidKeyaliasPass!: string; public androidTargetSdkVersion!: string; public androidSdkManagerParameters!: string; public androidExportType!: string; public androidSymbolType!: string; public dockerCpuLimit!: string; public dockerMemoryLimit!: string; public dockerIsolationMode!: string; public containerRegistryRepository!: string; public containerRegistryImageVersion!: string; public customParameters!: string; public sshAgent!: string; public sshPublicKeysDirectoryPath!: string; public providerStrategy!: string; public fallbackProviderStrategy!: string; public runnerCheckEnabled!: boolean; public runnerCheckLabels!: string[]; public runnerCheckMinAvailable!: number; public retryOnFallback!: boolean; public providerInitTimeout!: number; public gitAuthMode!: string; public gitPrivateToken!: string; public awsStackName!: string; public awsEndpoint?: string; public awsCloudFormationEndpoint?: string; public awsEcsEndpoint?: string; public awsKinesisEndpoint?: string; public awsCloudWatchLogsEndpoint?: string; public awsS3Endpoint?: string; public storageProvider!: string; public rcloneRemote!: string; public kubeConfig!: string; public containerMemory!: string; public containerCpu!: string; public containerNamespace!: string; public kubeVolumeSize!: string; public kubeVolume!: string; public kubeStorageClass!: string; public runAsHostUser!: string; public chownFilesTo!: string; public commandHooks!: string; public pullInputList!: string[]; public inputPullCommand!: string; public cacheKey!: string; public postBuildContainerHooks!: string; public preBuildContainerHooks!: string; public customJob!: string; public runNumber!: string; public branch!: string; public githubRepo!: string; public orchestratorRepoName!: string; public cloneDepth!: number; public gitSha!: string; public logId!: string; public buildGuid!: string; public orchestratorBranch!: string; public orchestratorDebug!: boolean | undefined; public buildPlatform!: string | undefined; public isCliMode!: boolean; public maxRetainedWorkspaces!: number; public useLargePackages!: boolean; public useCompressionStrategy!: boolean; public garbageMaxAge!: number; public githubChecks!: boolean; public asyncWorkflow!: boolean; public githubCheckId!: string; public finalHooks!: string[]; public skipLfs!: boolean; public skipCache!: boolean; public cacheUnityInstallationOnMac!: boolean; public unityHubVersionOnMac!: string; public dockerWorkspacePath!: string; public submoduleProfilePath!: string; public submoduleVariantPath!: string; public submoduleToken!: string; public localCacheEnabled!: boolean; public localCacheRoot!: string; public localCacheLibrary!: boolean; public localCacheLfs!: boolean; public childWorkspacesEnabled!: boolean; public childWorkspaceName!: string; public childWorkspaceCacheRoot!: string; public childWorkspacePreserveGit!: boolean; public childWorkspaceSeparateLibrary!: boolean; public lfsTransferAgent!: string; public lfsTransferAgentArgs!: string; public lfsStoragePaths!: string; public gitHooksEnabled!: boolean; public gitHooksSkipList!: string; public gitHooksRunBeforeBuild!: string; public providerExecutable!: string; // GCP Cloud Run (Experimental) public gcpProject!: string; public gcpRegion!: string; public gcpStorageType!: string; public gcpBucket!: string; public gcpFilestoreIp!: string; public gcpFilestoreShare!: string; public gcpMachineType!: string; public gcpDiskSizeGb!: string; public gcpServiceAccount!: string; public gcpVpcConnector!: string; // Azure Container Instances (Experimental) public azureResourceGroup!: string; public azureLocation!: string; public azureStorageType!: string; public azureStorageAccount!: string; public azureBlobContainer!: string; public azureFileShareName!: string; public azureSubscriptionId!: string; public azureCpu!: string; public azureMemoryGb!: string; public azureDiskSizeGb!: string; public azureSubnetId!: string; // Remote PowerShell provider public remotePowershellHost!: string; public remotePowershellCredential!: string; public remotePowershellTransport!: string; // GitHub Actions provider public githubActionsRepo!: string; public githubActionsWorkflow!: string; public githubActionsToken!: string; public githubActionsRef!: string; // GitLab CI provider public gitlabProjectId!: string; public gitlabTriggerToken!: string; public gitlabApiUrl!: string; public gitlabRef!: string; // Ansible provider public ansibleInventory!: string; public ansiblePlaybook!: string; public ansibleExtraVars!: string; public ansibleVaultPassword!: string; public gitIntegrityCheck!: boolean; public gitAutoRecover!: boolean; public cleanReservedFilenames!: boolean; public buildArchiveEnabled!: boolean; public buildArchivePath!: string; public buildArchiveRetention!: number; public testSuitePath!: string; public testSuiteEvent!: string; public testTaxonomyPath!: string; public testResultFormat!: string; public testResultPath!: string; public static shouldUseRetainedWorkspaceMode(buildParameters: BuildParameters) { return buildParameters.maxRetainedWorkspaces > 0 && Orchestrator.lockedWorkspace !== ``; } static async create(): Promise { const buildFile = this.parseBuildFile(Input.buildName, Input.targetPlatform, Input.androidExportType); const editorVersion = UnityVersioning.determineUnityVersion(Input.projectPath, Input.unityVersion); const buildVersion = await Versioning.determineBuildVersion(Input.versioningStrategy, Input.specifiedVersion); const androidVersionCode = AndroidVersioning.determineVersionCode(buildVersion, Input.androidVersionCode); const androidSdkManagerParameters = AndroidVersioning.determineSdkManagerParameters(Input.androidTargetSdkVersion); const androidSymbolExportType = Input.androidSymbolType; if (Platform.isAndroid(Input.targetPlatform)) { switch (androidSymbolExportType) { case 'none': case 'public': case 'debugging': break; default: throw new Error( `Invalid androidSymbolType: ${Input.androidSymbolType}. Must be one of: none, public, debugging`, ); } } let unitySerial = ''; if (Input.unityLicensingServer === '') { if (!Input.unitySerial && GitHub.githubInputEnabled) { // No serial was present, so it is a personal license that we need to convert if (!Input.unityLicense) { throw new Error( `Missing Unity License File and no Serial was found. If this is a personal license, make sure to follow the activation steps and set the UNITY_LICENSE GitHub secret or enter a Unity serial number inside the UNITY_SERIAL GitHub secret.`, ); } unitySerial = this.getSerialFromLicenseFile(Input.unityLicense); } else { unitySerial = Input.unitySerial!; } } if (unitySerial !== undefined && unitySerial.length === 27) { core.setSecret(unitySerial); core.setSecret(`${unitySerial.slice(0, -4)}XXXX`); } return { editorVersion, customImage: Input.customImage, unitySerial, unityLicensingServer: Input.unityLicensingServer, skipActivation: Input.skipActivation, runnerTempPath: Input.runnerTempPath, targetPlatform: Input.targetPlatform, projectPath: Input.projectPath, buildProfile: Input.buildProfile, buildName: Input.buildName, buildPath: `${Input.buildsPath}/${Input.targetPlatform}`, buildFile, buildMethod: Input.buildMethod, buildVersion, manualExit: Input.manualExit, enableGpu: Input.enableGpu, androidVersionCode, androidKeystoreName: Input.androidKeystoreName, androidKeystoreBase64: Input.androidKeystoreBase64, androidKeystorePass: Input.androidKeystorePass, androidKeyaliasName: Input.androidKeyaliasName, androidKeyaliasPass: Input.androidKeyaliasPass, androidTargetSdkVersion: Input.androidTargetSdkVersion, androidSdkManagerParameters, androidExportType: Input.androidExportType, androidSymbolType: androidSymbolExportType, customParameters: Input.customParameters, sshAgent: Input.sshAgent, sshPublicKeysDirectoryPath: Input.sshPublicKeysDirectoryPath, gitPrivateToken: Input.gitPrivateToken ?? (await GithubCliReader.GetGitHubAuthToken()), runAsHostUser: Input.runAsHostUser, chownFilesTo: Input.chownFilesTo, dockerCpuLimit: Input.dockerCpuLimit, dockerMemoryLimit: Input.dockerMemoryLimit, dockerIsolationMode: Input.dockerIsolationMode, containerRegistryRepository: Input.containerRegistryRepository, containerRegistryImageVersion: Input.containerRegistryImageVersion, providerStrategy: OrchestratorOptions.providerStrategy, fallbackProviderStrategy: OrchestratorOptions.fallbackProviderStrategy, runnerCheckEnabled: OrchestratorOptions.runnerCheckEnabled, runnerCheckLabels: OrchestratorOptions.runnerCheckLabels, runnerCheckMinAvailable: OrchestratorOptions.runnerCheckMinAvailable, retryOnFallback: OrchestratorOptions.retryOnFallback, providerInitTimeout: OrchestratorOptions.providerInitTimeout, gitAuthMode: OrchestratorOptions.gitAuthMode, buildPlatform: OrchestratorOptions.buildPlatform, kubeConfig: OrchestratorOptions.kubeConfig, containerMemory: OrchestratorOptions.containerMemory, containerCpu: OrchestratorOptions.containerCpu, containerNamespace: OrchestratorOptions.containerNamespace, kubeVolumeSize: OrchestratorOptions.kubeVolumeSize, kubeVolume: OrchestratorOptions.kubeVolume, postBuildContainerHooks: OrchestratorOptions.postBuildContainerHooks, preBuildContainerHooks: OrchestratorOptions.preBuildContainerHooks, customJob: OrchestratorOptions.customJob, runNumber: Input.runNumber, branch: Input.branch.replace('/head', '') || (await GitRepoReader.GetBranch()), orchestratorBranch: OrchestratorOptions.orchestratorBranch.split('/').reverse()[0], orchestratorDebug: OrchestratorOptions.orchestratorDebug, githubRepo: (Input.githubRepo ?? (await GitRepoReader.GetRemote())) || OrchestratorOptions.orchestratorRepoName, orchestratorRepoName: OrchestratorOptions.orchestratorRepoName, cloneDepth: Number.parseInt(OrchestratorOptions.cloneDepth), isCliMode: Cli.isCliMode, awsStackName: OrchestratorOptions.awsStackName, awsEndpoint: OrchestratorOptions.awsEndpoint, awsCloudFormationEndpoint: OrchestratorOptions.awsCloudFormationEndpoint, awsEcsEndpoint: OrchestratorOptions.awsEcsEndpoint, awsKinesisEndpoint: OrchestratorOptions.awsKinesisEndpoint, awsCloudWatchLogsEndpoint: OrchestratorOptions.awsCloudWatchLogsEndpoint, awsS3Endpoint: OrchestratorOptions.awsS3Endpoint, storageProvider: OrchestratorOptions.storageProvider, rcloneRemote: OrchestratorOptions.rcloneRemote, gitSha: Input.gitSha, logId: customAlphabet(OrchestratorConstants.alphabet, 9)(), buildGuid: OrchestratorBuildGuid.generateGuid(Input.runNumber, Input.targetPlatform), commandHooks: OrchestratorOptions.commandHooks, inputPullCommand: OrchestratorOptions.inputPullCommand, pullInputList: OrchestratorOptions.pullInputList, kubeStorageClass: OrchestratorOptions.kubeStorageClass, gcpProject: Input.gcpProject, gcpRegion: Input.gcpRegion, gcpStorageType: Input.gcpStorageType, gcpBucket: Input.gcpBucket, gcpFilestoreIp: Input.gcpFilestoreIp, gcpFilestoreShare: Input.gcpFilestoreShare, gcpMachineType: Input.gcpMachineType, gcpDiskSizeGb: Input.gcpDiskSizeGb, gcpServiceAccount: Input.gcpServiceAccount, gcpVpcConnector: Input.gcpVpcConnector, azureResourceGroup: Input.azureResourceGroup, azureLocation: Input.azureLocation, azureStorageType: Input.azureStorageType, azureStorageAccount: Input.azureStorageAccount, azureBlobContainer: Input.azureBlobContainer, azureFileShareName: Input.azureFileShareName, azureSubscriptionId: Input.azureSubscriptionId, azureCpu: Input.azureCpu, azureMemoryGb: Input.azureMemoryGb, azureDiskSizeGb: Input.azureDiskSizeGb, azureSubnetId: Input.azureSubnetId, cacheKey: OrchestratorOptions.cacheKey, maxRetainedWorkspaces: Number.parseInt(OrchestratorOptions.maxRetainedWorkspaces), useLargePackages: OrchestratorOptions.useLargePackages, useCompressionStrategy: OrchestratorOptions.useCompressionStrategy, garbageMaxAge: OrchestratorOptions.garbageMaxAge, githubChecks: OrchestratorOptions.githubChecks, asyncWorkflow: OrchestratorOptions.asyncOrchestrator, githubCheckId: OrchestratorOptions.githubCheckId, finalHooks: OrchestratorOptions.finalHooks, skipLfs: OrchestratorOptions.skipLfs, skipCache: OrchestratorOptions.skipCache, cacheUnityInstallationOnMac: Input.cacheUnityInstallationOnMac, unityHubVersionOnMac: Input.unityHubVersionOnMac, dockerWorkspacePath: Input.dockerWorkspacePath, submoduleProfilePath: Input.submoduleProfilePath, submoduleVariantPath: Input.submoduleVariantPath, submoduleToken: Input.submoduleToken, localCacheEnabled: Input.localCacheEnabled, localCacheRoot: Input.localCacheRoot, localCacheLibrary: Input.localCacheLibrary, localCacheLfs: Input.localCacheLfs, childWorkspacesEnabled: Input.childWorkspacesEnabled, childWorkspaceName: Input.childWorkspaceName, childWorkspaceCacheRoot: Input.childWorkspaceCacheRoot, childWorkspacePreserveGit: Input.childWorkspacePreserveGit, childWorkspaceSeparateLibrary: Input.childWorkspaceSeparateLibrary, lfsTransferAgent: Input.lfsTransferAgent, lfsTransferAgentArgs: Input.lfsTransferAgentArgs, lfsStoragePaths: Input.lfsStoragePaths, gitHooksEnabled: Input.gitHooksEnabled, gitHooksSkipList: Input.gitHooksSkipList, gitHooksRunBeforeBuild: Input.gitHooksRunBeforeBuild, providerExecutable: Input.providerExecutable, // Remote PowerShell provider remotePowershellHost: Input.remotePowershellHost, remotePowershellCredential: Input.remotePowershellCredential, remotePowershellTransport: Input.remotePowershellTransport, // GitHub Actions provider githubActionsRepo: Input.githubActionsRepo, githubActionsWorkflow: Input.githubActionsWorkflow, githubActionsToken: Input.githubActionsToken, githubActionsRef: Input.githubActionsRef, // GitLab CI provider gitlabProjectId: Input.gitlabProjectId, gitlabTriggerToken: Input.gitlabTriggerToken, gitlabApiUrl: Input.gitlabApiUrl, gitlabRef: Input.gitlabRef, // Ansible provider ansibleInventory: Input.ansibleInventory, ansiblePlaybook: Input.ansiblePlaybook, ansibleExtraVars: Input.ansibleExtraVars, ansibleVaultPassword: Input.ansibleVaultPassword, gitIntegrityCheck: Input.gitIntegrityCheck, gitAutoRecover: Input.gitAutoRecover, cleanReservedFilenames: Input.cleanReservedFilenames, buildArchiveEnabled: Input.buildArchiveEnabled, buildArchivePath: Input.buildArchivePath, buildArchiveRetention: Input.buildArchiveRetention, testSuitePath: Input.testSuitePath, testSuiteEvent: Input.testSuiteEvent, testTaxonomyPath: Input.testTaxonomyPath, testResultFormat: Input.testResultFormat, testResultPath: Input.testResultPath, }; } static parseBuildFile(filename: string, platform: string, androidExportType: string): string { if (Platform.isWindows(platform)) { return `${filename}.exe`; } if (Platform.isAndroid(platform)) { switch (androidExportType) { case `androidPackage`: return `${filename}.apk`; case `androidAppBundle`: return `${filename}.aab`; case `androidStudioProject`: return filename; default: throw new Error( `Unknown Android Export Type: ${androidExportType}. Must be one of androidPackage for apk, androidAppBundle for aab, androidStudioProject for android project`, ); } } return filename; } static getSerialFromLicenseFile(license: string) { const startKey = ``; const startIndex = license.indexOf(startKey) + startKey.length; if (startIndex < 0) { throw new Error(`License File was corrupted, unable to locate serial`); } const endIndex = license.indexOf(endKey, startIndex); // Slice off the first 4 characters as they are garbage values return Buffer.from(license.slice(startIndex, endIndex), 'base64').toString('binary').slice(4); } } export default BuildParameters;