Files
unity-builder/src/model/platform-setup/setup-mac.ts
Andrew Kahr 2afd9cd86f Additional Fixes and Improvements (#596)
- Windows now exits with the proper exit codes. This mirrors Ubuntu behavior properly now and means we do not need the error parsing logic to handle error conditions which means we should be back to v2 behavior.
- Allow customizing image registry/image version
- Only create the licensing directory on Mac if it doesn't already exist. Don't delete the folder on build complete. This means builds nominally shouldn't need sudo permissions, very useful for self-hosted runners.
- Pick correct architecture when installing macos editor to support both x86 and arm-based systems (Credit @dcvz)
2023-11-15 06:17:55 -08:00

194 lines
7.3 KiB
TypeScript

import { BuildParameters } from '..';
import { getUnityChangeset } from 'unity-changeset';
import { exec, getExecOutput } from '@actions/exec';
import { restoreCache, saveCache } from '@actions/cache';
import fs from 'node:fs';
class SetupMac {
static unityHubBasePath = `/Applications/"Unity Hub.app"`;
static unityHubExecPath = `${SetupMac.unityHubBasePath}/Contents/MacOS/"Unity Hub"`;
public static async setup(buildParameters: BuildParameters, actionFolder: string) {
const unityEditorPath = `/Applications/Unity/Hub/Editor/${buildParameters.editorVersion}/Unity.app/Contents/MacOS/Unity`;
if (!fs.existsSync(this.unityHubExecPath.replace(/"/g, ''))) {
await SetupMac.installUnityHub(buildParameters);
}
if (!fs.existsSync(unityEditorPath.replace(/"/g, ''))) {
await SetupMac.installUnity(buildParameters);
}
await SetupMac.setEnvironmentVariables(buildParameters, actionFolder);
}
private static async installUnityHub(buildParameters: BuildParameters, silent = false) {
// Can't use quotes in the cache package so we need a different path
const unityHubCachePath = `/Applications/Unity\\ Hub.app`;
const targetHubVersion =
buildParameters.unityHubVersionOnMac !== ''
? buildParameters.unityHubVersionOnMac
: await SetupMac.getLatestUnityHubVersion();
const restoreKey = `Cache-MacOS-UnityHub@${targetHubVersion}`;
if (buildParameters.cacheUnityInstallationOnMac) {
const cacheId = await restoreCache([unityHubCachePath], restoreKey);
if (cacheId) {
// Cache restored successfully, unity hub is installed now
return;
}
}
const commandSuffix = buildParameters.unityHubVersionOnMac !== '' ? `@${buildParameters.unityHubVersionOnMac}` : '';
const command = `brew install unity-hub${commandSuffix}`;
// Ignoring return code because the log seems to overflow the internal buffer which triggers
// a false error
const errorCode = await exec(command, undefined, {
silent,
ignoreReturnCode: true,
});
if (errorCode) {
throw new Error(`There was an error installing the Unity Editor. See logs above for details.`);
}
if (buildParameters.cacheUnityInstallationOnMac) {
await saveCache([unityHubCachePath], restoreKey);
}
}
/**
* Gets the latest version of Unity Hub available on brew
* @returns The latest version of Unity Hub available on brew
*/
private static async getLatestUnityHubVersion(): Promise<string> {
// Need to check if the latest version available is the same as the one we have cached
const hubVersionCommand = `/bin/bash -c "brew info unity-hub | grep -o '[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+'"`;
const result = await getExecOutput(hubVersionCommand, undefined, {
silent: true,
});
if (result.exitCode === 0 && result.stdout !== '') {
return result.stdout;
}
return '';
}
private static getArchitectureParameters(): string[] {
const architectureArgument = [];
switch (process.arch) {
case 'x64':
architectureArgument.push('--architecture', 'x86_64');
break;
case 'arm64':
architectureArgument.push('--architecture', 'arm64');
break;
default:
throw new Error(`Unsupported architecture: ${process.arch}.`);
}
return architectureArgument;
}
private static getModuleParametersForTargetPlatform(targetPlatform: string): string[] {
const moduleArgument = [];
switch (targetPlatform) {
case 'iOS':
moduleArgument.push('--module', 'ios');
break;
case 'tvOS':
moduleArgument.push('--module', 'tvos');
break;
case 'StandaloneOSX':
moduleArgument.push('--module', 'mac-il2cpp');
break;
case 'Android':
moduleArgument.push('--module', 'android');
break;
case 'WebGL':
moduleArgument.push('--module', 'webgl');
break;
default:
throw new Error(`Unsupported module for target platform: ${targetPlatform}.`);
}
return moduleArgument;
}
private static async installUnity(buildParameters: BuildParameters, silent = false) {
const unityEditorPath = `/Applications/Unity/Hub/Editor/${buildParameters.editorVersion}`;
const key = `Cache-MacOS-UnityEditor-With-Module-${buildParameters.targetPlatform}@${buildParameters.editorVersion}`;
if (buildParameters.cacheUnityInstallationOnMac) {
const cacheId = await restoreCache([unityEditorPath], key);
if (cacheId) {
// Cache restored successfully, unity editor is installed now
return;
}
}
const unityChangeset = await getUnityChangeset(buildParameters.editorVersion);
const moduleArguments = SetupMac.getModuleParametersForTargetPlatform(buildParameters.targetPlatform);
const architectureArguments = SetupMac.getArchitectureParameters();
const execArguments: string[] = [
'--',
'--headless',
'install',
...['--version', buildParameters.editorVersion],
...['--changeset', unityChangeset.changeset],
...moduleArguments,
...architectureArguments,
'--childModules',
];
// Ignoring return code because the log seems to overflow the internal buffer which triggers
// a false error
const errorCode = await exec(this.unityHubExecPath, execArguments, {
silent,
ignoreReturnCode: true,
});
if (errorCode) {
throw new Error(`There was an error installing the Unity Editor. See logs above for details.`);
}
if (buildParameters.cacheUnityInstallationOnMac) {
await saveCache([unityEditorPath], key);
}
}
private static async setEnvironmentVariables(buildParameters: BuildParameters, actionFolder: string) {
// Need to set environment variables from here because we execute
// the scripts on the host for mac
process.env.ACTION_FOLDER = actionFolder;
process.env.UNITY_VERSION = buildParameters.editorVersion;
process.env.UNITY_SERIAL = buildParameters.unitySerial;
process.env.UNITY_LICENSING_SERVER = buildParameters.unityLicensingServer;
process.env.PROJECT_PATH = buildParameters.projectPath;
process.env.BUILD_TARGET = buildParameters.targetPlatform;
process.env.BUILD_NAME = buildParameters.buildName;
process.env.BUILD_PATH = buildParameters.buildPath;
process.env.BUILD_FILE = buildParameters.buildFile;
process.env.BUILD_METHOD = buildParameters.buildMethod;
process.env.VERSION = buildParameters.buildVersion;
process.env.ANDROID_VERSION_CODE = buildParameters.androidVersionCode;
process.env.ANDROID_KEYSTORE_NAME = buildParameters.androidKeystoreName;
process.env.ANDROID_KEYSTORE_BASE64 = buildParameters.androidKeystoreBase64;
process.env.ANDROID_KEYSTORE_PASS = buildParameters.androidKeystorePass;
process.env.ANDROID_KEYALIAS_NAME = buildParameters.androidKeyaliasName;
process.env.ANDROID_KEYALIAS_PASS = buildParameters.androidKeyaliasPass;
process.env.ANDROID_TARGET_SDK_VERSION = buildParameters.androidTargetSdkVersion;
process.env.ANDROID_SDK_MANAGER_PARAMETERS = buildParameters.androidSdkManagerParameters;
process.env.ANDROID_EXPORT_TYPE = buildParameters.androidExportType;
process.env.ANDROID_SYMBOL_TYPE = buildParameters.androidSymbolType;
process.env.CUSTOM_PARAMETERS = buildParameters.customParameters;
process.env.CHOWN_FILES_TO = buildParameters.chownFilesTo;
}
}
export default SetupMac;