mirror of
https://github.com/game-ci/unity-builder.git
synced 2025-07-04 12:25:19 -04:00
Feature/windows upgrades (#588)
- Allow updating container memory and cpu limits for Windows. Previously, they defaulted to 1cpu and 1gb ram which was far too low and it seems docker wouldn't allocate all available resources. Now it will use all available cores and 80% of system memory. - Allow setting docker isolation mode for windows. Defaults to default to ensure behavior doesn't change from prior versions but now you can do stuff like force process mode on non-server versions which grants a performance uplift during runs - Added logic to allow building Android on Windows. Android doesn't support burst when built on Linux, only on Windows and macOS. Thus we need to allow building Android on WIndows due to the major performance benefits of Burst. - Support Windows 2022 and VS2022 by mounting the x64 Visual Studio path in addition to the x86 path to maintain compatibility with VS2019 and older - Attempted fixes for windows builds hanging by killing the regsvr32 process after registering VS dll and using a different method to launch Unity. Unsure if this is a definite fix so I am leaving in several debug calls to print out running processes so we have more data to work with on chasing down this bug. I suspect there's a process that's hanging around that isn't cleaning itself up or is getting into some kind of deadlock situation and needs to be killed. But the changes I've made have seen no hangs on building during docker test workflows when previously there would be at least 3-5 hanging builds.
This commit is contained in:
parent
6419c8742b
commit
4c4611c021
7
.vscode/launch.json
vendored
7
.vscode/launch.json
vendored
@ -1,5 +1,12 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "PowerShell Launch Current File",
|
||||
"type": "PowerShell",
|
||||
"request": "launch",
|
||||
"script": "${file}",
|
||||
"cwd": "${cwd}"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
|
18
action.yml
18
action.yml
@ -106,6 +106,24 @@ inputs:
|
||||
default: ''
|
||||
description:
|
||||
'User and optionally group (user or user:group or uid:gid) to give ownership of the resulting build artifacts'
|
||||
dockerCpuLimit:
|
||||
required: false
|
||||
default: ''
|
||||
description: 'Number of CPU cores to assign the docker container. Defaults to all available cores on all platforms.'
|
||||
dockerMemoryLimit:
|
||||
required: false
|
||||
default: ''
|
||||
description:
|
||||
'Amount of memory to assign the docker container. Defaults to 95% of total system memory rounded down to the
|
||||
nearest megabyte on Linux and 80% on Windows. On unrecognized platforms, defaults to 75% of total system memory.
|
||||
To manually specify a value, use the format <number><unit>, where unit is either m or g. ie: 512m = 512 megabytes'
|
||||
dockerIsolationMode:
|
||||
required: false
|
||||
default: 'default'
|
||||
description:
|
||||
'Isolation mode to use for the docker container. Can be one of process, hyperv, or default. Default will pick the
|
||||
default mode as described by Microsoft where server versions use process and desktop versions use hyperv. Only
|
||||
applicable on Windows'
|
||||
allowDirtyBuild:
|
||||
required: false
|
||||
default: ''
|
||||
|
BIN
dist/index.js
generated
vendored
BIN
dist/index.js
generated
vendored
Binary file not shown.
BIN
dist/index.js.map
generated
vendored
BIN
dist/index.js.map
generated
vendored
Binary file not shown.
117
dist/platforms/windows/build.ps1
vendored
117
dist/platforms/windows/build.ps1
vendored
@ -66,6 +66,26 @@ else
|
||||
Get-ChildItem -Path $Env:UNITY_PROJECT_PATH\Assets\Editor -Recurse
|
||||
}
|
||||
|
||||
if ( "$Env:BUILD_TARGET" -eq "Android" -and -not ([string]::IsNullOrEmpty("$Env:ANDROID_KEYSTORE_BASE64")) )
|
||||
{
|
||||
Write-Output "Creating Android keystore."
|
||||
|
||||
# Write to consistent location as Windows Unity seems to have issues with pwd and can't find the keystore
|
||||
$keystorePath = "C:/android.keystore"
|
||||
[System.IO.File]::WriteAllBytes($keystorePath, [System.Convert]::FromBase64String($Env:ANDROID_KEYSTORE_BASE64))
|
||||
|
||||
# Ensure the project settings are pointed at the correct path
|
||||
$unitySettingsPath = "$Env:UNITY_PROJECT_PATH\ProjectSettings\ProjectSettings.asset"
|
||||
$fileContent = Get-Content -Path "$unitySettingsPath"
|
||||
$fileContent = $fileContent -replace "AndroidKeystoreName:\s+.*", "AndroidKeystoreName: $keystorePath"
|
||||
$fileContent | Set-Content -Path "$unitySettingsPath"
|
||||
|
||||
Write-Output "Created Android keystore."
|
||||
}
|
||||
else {
|
||||
Write-Output "Not creating Android keystore."
|
||||
}
|
||||
|
||||
#
|
||||
# Pre-build debug information
|
||||
#
|
||||
@ -112,48 +132,63 @@ Write-Output ""
|
||||
# If $Env:CUSTOM_PARAMETERS contains spaces and is passed directly on the command line to Unity, powershell will wrap it
|
||||
# in double quotes. To avoid this, parse $Env:CUSTOM_PARAMETERS into an array, while respecting any quotations within the string.
|
||||
$_, $customParametersArray = Invoke-Expression('Write-Output -- "" ' + $Env:CUSTOM_PARAMETERS)
|
||||
$unityArgs = @(
|
||||
"-quit",
|
||||
"-batchmode",
|
||||
"-nographics",
|
||||
"-silent-crashes",
|
||||
"-projectPath", $Env:UNITY_PROJECT_PATH,
|
||||
"-executeMethod", $Env:BUILD_METHOD,
|
||||
"-buildTarget", $Env:BUILD_TARGET,
|
||||
"-customBuildTarget", $Env:BUILD_TARGET,
|
||||
"-customBuildPath", $Env:CUSTOM_BUILD_PATH,
|
||||
"-buildVersion", $Env:VERSION,
|
||||
"-androidVersionCode", $Env:ANDROID_VERSION_CODE,
|
||||
"-androidKeystorePass", $Env:ANDROID_KEYSTORE_PASS,
|
||||
"-androidKeyaliasName", $Env:ANDROID_KEYALIAS_NAME,
|
||||
"-androidKeyaliasPass", $Env:ANDROID_KEYALIAS_PASS,
|
||||
"-androidTargetSdkVersion", $Env:ANDROID_TARGET_SDK_VERSION,
|
||||
"-androidExportType", $Env:ANDROID_EXPORT_TYPE,
|
||||
"-androidSymbolType", $Env:ANDROID_SYMBOL_TYPE,
|
||||
"-logfile", "-"
|
||||
) + $customParametersArray
|
||||
|
||||
& "C:\Program Files\Unity\Hub\Editor\$Env:UNITY_VERSION\Editor\Unity.exe" -quit -batchmode -nographics `
|
||||
-projectPath $Env:UNITY_PROJECT_PATH `
|
||||
-executeMethod $Env:BUILD_METHOD `
|
||||
-buildTarget $Env:BUILD_TARGET `
|
||||
-customBuildTarget $Env:BUILD_TARGET `
|
||||
-customBuildPath $Env:CUSTOM_BUILD_PATH `
|
||||
-buildVersion $Env:VERSION `
|
||||
-androidVersionCode $Env:ANDROID_VERSION_CODE `
|
||||
-androidKeystoreName $Env:ANDROID_KEYSTORE_NAME `
|
||||
-androidKeystorePass $Env:ANDROID_KEYSTORE_PASS `
|
||||
-androidKeyaliasName $Env:ANDROID_KEYALIAS_NAME `
|
||||
-androidKeyaliasPass $Env:ANDROID_KEYALIAS_PASS `
|
||||
-androidTargetSdkVersion $Env:ANDROID_TARGET_SDK_VERSION `
|
||||
-androidExportType $Env:ANDROID_EXPORT_TYPE `
|
||||
-androidSymbolType $Env:ANDROID_SYMBOL_TYPE `
|
||||
$customParametersArray `
|
||||
-logfile | Out-Host
|
||||
# Remove null items as that will fail the Start-Process call
|
||||
$unityArgs = $unityArgs | Where-Object { $_ -ne $null }
|
||||
|
||||
# Catch exit code
|
||||
$Env:BUILD_EXIT_CODE=$LastExitCode
|
||||
$process = Start-Process -FilePath "C:\Program Files\Unity\Hub\Editor\$Env:UNITY_VERSION\Editor\Unity.exe" `
|
||||
-ArgumentList $unityArgs `
|
||||
-PassThru `
|
||||
-NoNewWindow
|
||||
|
||||
# Display results
|
||||
if ($Env:BUILD_EXIT_CODE -eq 0)
|
||||
{
|
||||
Write-Output "Build Succeeded!"
|
||||
} else
|
||||
{
|
||||
Write-Output "$('Build failed, with exit code ')$($Env:BUILD_EXIT_CODE)$('"')"
|
||||
while (!$process.HasExited) {
|
||||
if ($process.HasExited) {
|
||||
Get-Process
|
||||
|
||||
Start-Sleep -Seconds 10
|
||||
|
||||
Get-Process
|
||||
|
||||
# Display results
|
||||
if ($process.ExitCode -eq 0)
|
||||
{
|
||||
Write-Output "Build Succeeded!!"
|
||||
} else
|
||||
{
|
||||
Write-Output "$('Build failed, with exit code ')$($process.ExitCode)$('"')"
|
||||
}
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "###########################"
|
||||
Write-Output "# Build output #"
|
||||
Write-Output "###########################"
|
||||
Write-Output ""
|
||||
|
||||
Get-ChildItem $Env:BUILD_PATH_FULL
|
||||
Write-Output ""
|
||||
|
||||
exit $process.ExitCode
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
|
||||
# TODO: Determine if we need to set permissions on any files
|
||||
|
||||
#
|
||||
# Results
|
||||
#
|
||||
|
||||
Write-Output ""
|
||||
Write-Output "###########################"
|
||||
Write-Output "# Build output #"
|
||||
Write-Output "###########################"
|
||||
Write-Output ""
|
||||
|
||||
Get-ChildItem $Env:BUILD_PATH_FULL
|
||||
Write-Output ""
|
||||
|
10
dist/platforms/windows/entrypoint.ps1
vendored
10
dist/platforms/windows/entrypoint.ps1
vendored
@ -1,10 +1,15 @@
|
||||
Get-Process
|
||||
|
||||
# Import any necessary registry keys, ie: location of windows 10 sdk
|
||||
# No guarantee that there will be any necessary registry keys, ie: tvOS
|
||||
Get-ChildItem -Path c:\regkeys -File | Foreach {reg import $_.fullname}
|
||||
Get-ChildItem -Path c:\regkeys -File | ForEach-Object {reg import $_.fullname}
|
||||
|
||||
# Register the Visual Studio installation so Unity can find it
|
||||
regsvr32 C:\ProgramData\Microsoft\VisualStudio\Setup\x64\Microsoft.VisualStudio.Setup.Configuration.Native.dll
|
||||
|
||||
# Kill the regsvr process
|
||||
Get-Process -Name regsvr32 | ForEach-Object { Stop-Process -Id $_.Id -Force }
|
||||
|
||||
# Setup Git Credentials
|
||||
& "c:\steps\set_gitcredential.ps1"
|
||||
|
||||
@ -16,3 +21,6 @@ regsvr32 C:\ProgramData\Microsoft\VisualStudio\Setup\x64\Microsoft.VisualStudio.
|
||||
|
||||
# Free the seat for the activated license
|
||||
& "c:\steps\return_license.ps1"
|
||||
|
||||
Start-Sleep 3
|
||||
Get-Process
|
||||
|
@ -25,7 +25,11 @@ async function runMain() {
|
||||
if (process.platform === 'darwin') {
|
||||
MacBuilder.run(actionFolder);
|
||||
} else {
|
||||
await Docker.run(baseImage.toString(), { workspace, actionFolder, ...buildParameters });
|
||||
await Docker.run(baseImage.toString(), {
|
||||
workspace,
|
||||
actionFolder,
|
||||
...buildParameters,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await CloudRunner.run(buildParameters, baseImage.toString());
|
||||
@ -38,4 +42,5 @@ async function runMain() {
|
||||
core.setFailed((error as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
runMain();
|
||||
|
@ -40,6 +40,9 @@ class BuildParameters {
|
||||
public androidSdkManagerParameters!: string;
|
||||
public androidExportType!: string;
|
||||
public androidSymbolType!: string;
|
||||
public dockerCpuLimit!: string;
|
||||
public dockerMemoryLimit!: string;
|
||||
public dockerIsolationMode!: string;
|
||||
|
||||
public customParameters!: string;
|
||||
public sshAgent!: string;
|
||||
@ -116,10 +119,12 @@ class BuildParameters {
|
||||
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
|
||||
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.`);
|
||||
serial number inside the UNITY_SERIAL GitHub secret.`,
|
||||
);
|
||||
}
|
||||
unitySerial = this.getSerialFromLicenseFile(Input.unityLicense);
|
||||
} else {
|
||||
@ -156,6 +161,9 @@ class BuildParameters {
|
||||
sshPublicKeysDirectoryPath: Input.sshPublicKeysDirectoryPath,
|
||||
gitPrivateToken: Input.gitPrivateToken || (await GithubCliReader.GetGitHubAuthToken()),
|
||||
chownFilesTo: Input.chownFilesTo,
|
||||
dockerCpuLimit: Input.dockerCpuLimit,
|
||||
dockerMemoryLimit: Input.dockerMemoryLimit,
|
||||
dockerIsolationMode: Input.dockerIsolationMode,
|
||||
providerStrategy: CloudRunnerOptions.providerStrategy,
|
||||
buildPlatform: CloudRunnerOptions.buildPlatform,
|
||||
kubeConfig: CloudRunnerOptions.kubeConfig,
|
||||
|
@ -48,6 +48,8 @@ class Docker {
|
||||
sshPublicKeysDirectoryPath,
|
||||
gitPrivateToken,
|
||||
dockerWorkspacePath,
|
||||
dockerCpuLimit,
|
||||
dockerMemoryLimit,
|
||||
} = parameters;
|
||||
|
||||
const githubHome = path.join(runnerTempPath, '_github_home');
|
||||
@ -72,6 +74,8 @@ class Docker {
|
||||
--volume "${actionFolder}/platforms/ubuntu/steps:/steps:z" \
|
||||
--volume "${actionFolder}/platforms/ubuntu/entrypoint.sh:/entrypoint.sh:z" \
|
||||
--volume "${actionFolder}/unity-config:/usr/share/unity3d/config/:z" \
|
||||
--cpus=${dockerCpuLimit} \
|
||||
--memory=${dockerMemoryLimit} \
|
||||
${sshAgent ? `--volume ${sshAgent}:/ssh-agent` : ''} \
|
||||
${
|
||||
sshAgent && !sshPublicKeysDirectoryPath
|
||||
@ -86,7 +90,16 @@ class Docker {
|
||||
}
|
||||
|
||||
static getWindowsCommand(image: string, parameters: DockerParameters): string {
|
||||
const { workspace, actionFolder, unitySerial, gitPrivateToken, dockerWorkspacePath } = parameters;
|
||||
const {
|
||||
workspace,
|
||||
actionFolder,
|
||||
unitySerial,
|
||||
gitPrivateToken,
|
||||
dockerWorkspacePath,
|
||||
dockerCpuLimit,
|
||||
dockerMemoryLimit,
|
||||
dockerIsolationMode,
|
||||
} = parameters;
|
||||
|
||||
return `docker run \
|
||||
--workdir c:${dockerWorkspacePath} \
|
||||
@ -97,12 +110,16 @@ class Docker {
|
||||
${gitPrivateToken ? `--env GIT_PRIVATE_TOKEN="${gitPrivateToken}"` : ''} \
|
||||
--volume "${workspace}":"c:${dockerWorkspacePath}" \
|
||||
--volume "c:/regkeys":"c:/regkeys" \
|
||||
--volume "C:/Program Files/Microsoft Visual Studio":"C:/Program Files/Microsoft Visual Studio" \
|
||||
--volume "C:/Program Files (x86)/Microsoft Visual Studio":"C:/Program Files (x86)/Microsoft Visual Studio" \
|
||||
--volume "C:/Program Files (x86)/Windows Kits":"C:/Program Files (x86)/Windows Kits" \
|
||||
--volume "C:/ProgramData/Microsoft/VisualStudio":"C:/ProgramData/Microsoft/VisualStudio" \
|
||||
--volume "${actionFolder}/default-build-script":"c:/UnityBuilderAction" \
|
||||
--volume "${actionFolder}/platforms/windows":"c:/steps" \
|
||||
--volume "${actionFolder}/BlankProject":"c:/BlankProject" \
|
||||
--cpus=${dockerCpuLimit} \
|
||||
--memory=${dockerMemoryLimit} \
|
||||
--isolation=${dockerIsolationMode} \
|
||||
${image} \
|
||||
powershell c:/steps/entrypoint.ps1`;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { Cli } from './cli/cli';
|
||||
import CloudRunnerQueryOverride from './cloud-runner/options/cloud-runner-query-override';
|
||||
import Platform from './platform';
|
||||
import GitHub from './github';
|
||||
import os from 'node:os';
|
||||
|
||||
import * as core from '@actions/core';
|
||||
|
||||
@ -226,6 +227,35 @@ class Input {
|
||||
return Input.getInput('dockerWorkspacePath') || '/github/workspace';
|
||||
}
|
||||
|
||||
static get dockerCpuLimit(): string {
|
||||
return Input.getInput('dockerCpuLimit') || os.cpus().length.toString();
|
||||
}
|
||||
|
||||
static get dockerMemoryLimit(): string {
|
||||
const bytesInMegabyte = 1024 * 1024;
|
||||
|
||||
let memoryMultiplier;
|
||||
switch (os.platform()) {
|
||||
case 'linux':
|
||||
memoryMultiplier = 0.95;
|
||||
break;
|
||||
case 'win32':
|
||||
memoryMultiplier = 0.8;
|
||||
break;
|
||||
default:
|
||||
memoryMultiplier = 0.75;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
Input.getInput('dockerMemoryLimit') || `${Math.floor((os.totalmem() / bytesInMegabyte) * memoryMultiplier)}m`
|
||||
);
|
||||
}
|
||||
|
||||
static get dockerIsolationMode(): string {
|
||||
return Input.getInput('dockerIsolationMode') || 'default';
|
||||
}
|
||||
|
||||
public static ToEnvVarFormat(input: string) {
|
||||
if (input.toUpperCase() === input) {
|
||||
return input;
|
||||
|
Loading…
Reference in New Issue
Block a user