PowerShell rewrite

This commit is contained in:
2026-08-30 07:22:18 -07:00
parent ef2f78ff91
commit ce35f98fb7
+172 -134
View File
@@ -1,11 +1,16 @@
[CmdletBinding()] [CmdletBinding()]
param() param(
[switch]$SkipExecution
)
Set-StrictMode -Version Latest Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
function Fail([string]$Message) { function Fail([string]$Message) {
Write-Error "::error::$Message" Write-Host "::error::$Message"
if ($SkipExecution) {
throw $Message
}
exit 1 exit 1
} }
@@ -47,160 +52,227 @@ function Get-ActualArchitecture {
} }
} }
function Get-Checksum([string]$ManifestPath, [string]$Asset) { function Get-GodotAssets([string]$Version, [string]$Dotnet, [string]$Architecture) {
if ($Dotnet -eq 'true') {
$edition = 'dotnet'
$editorBaseName = switch ($Architecture) {
'x86_32' { "Godot_v${Version}_mono_win32" }
'x86_64' { "Godot_v${Version}_mono_win64" }
'arm64' { "Godot_v${Version}_mono_windows_arm64" }
default { Fail "Unsupported Windows host-arch '$Architecture'." }
}
return [PSCustomObject]@{
Edition = $edition
EditorAsset = "$editorBaseName.zip"
EditorFileName = "${editorBaseName}_console.exe"
TemplatesAsset = "Godot_v${Version}_mono_export_templates.tpz"
TemplateVersion = ($Version -replace '-', '.') + '.mono'
}
}
$edition = 'standard'
$editorBaseName = switch ($Architecture) {
'x86_32' { "Godot_v${Version}_win32" }
'x86_64' { "Godot_v${Version}_win64" }
'arm64' { "Godot_v${Version}_windows_arm64" }
default { Fail "Unsupported Windows host-arch '$Architecture'." }
}
return [PSCustomObject]@{
Edition = $edition
EditorAsset = "${editorBaseName}.exe.zip"
EditorFileName = "${editorBaseName}_console.exe"
TemplatesAsset = "Godot_v${Version}_export_templates.tpz"
TemplateVersion = $Version -replace '-', '.'
}
}
function Get-ExpectedPeMachine([string]$Architecture) {
switch ($Architecture) {
'x86_32' { return [uint16]0x014c }
'x86_64' { return [uint16]0x8664 }
'arm64' { return [uint16]0xaa64 }
default { Fail "Unsupported Windows host-arch '$Architecture'." }
}
}
function Get-Checksum([string]$ManifestPath, [string]$Asset, [string]$Version, [string]$Edition, [string]$Architecture, [string]$BaseUrl) {
foreach ($line in Get-Content -LiteralPath $ManifestPath) { foreach ($line in Get-Content -LiteralPath $ManifestPath) {
if ($line -match '^([0-9A-Fa-f]{128})\s+\*?(.+)$' -and $Matches[2] -eq $Asset) { if ($line -match '^([0-9A-Fa-f]{128})\s+\*?(.+)$' -and $Matches[2] -eq $Asset) {
return $Matches[1].ToLowerInvariant() return $Matches[1].ToLowerInvariant()
} }
} }
Fail "Godot $GodotVersion does not publish required $edition asset '$Asset' for Windows/$HostArch at $script:BaseUrl. Choose a supported stable release and architecture." Fail "Godot $Version does not publish required $Edition asset '$Asset' for Windows/$Architecture at $BaseUrl. Choose a supported stable release and architecture."
} }
function Download-AndVerify([string]$Asset, [string]$Destination, [string]$ExpectedChecksum) { function Invoke-Download([string]$Uri, [string]$Destination) {
Invoke-WebRequest -UseBasicParsing -Uri "$script:BaseUrl/$Asset" -OutFile $Destination $lastError = $null
$actualChecksum = (Get-FileHash -LiteralPath $Destination -Algorithm SHA512).Hash.ToLowerInvariant() for ($attempt = 1; $attempt -le 3; $attempt++) {
if ($actualChecksum -ne $ExpectedChecksum) { try {
Fail "SHA-512 verification failed for $Asset." Invoke-WebRequest -UseBasicParsing -Uri $Uri -OutFile $Destination
$lastError = $null
break
} catch {
$lastError = $_
if (Test-Path -LiteralPath $Destination) {
Remove-Item -LiteralPath $Destination -Force
}
if ($attempt -lt 3) {
Start-Sleep -Seconds $attempt
}
}
}
if ($null -ne $lastError) {
Fail "Failed to download '$Uri' after 3 attempts: $($lastError.Exception.Message)"
} }
} }
function Get-CachePaths([string]$Root) { function Invoke-VerifiedDownload([string]$Uri, [string]$Destination, [string]$ExpectedChecksum) {
Invoke-Download $Uri $Destination
$actualChecksum = (Get-FileHash -LiteralPath $Destination -Algorithm SHA512).Hash.ToLowerInvariant()
if ($actualChecksum -ne $ExpectedChecksum) {
Fail "SHA-512 verification failed for $(Split-Path -Leaf $Destination)."
}
}
function Get-CachePaths([string]$Root, [string]$TemplateVersion) {
$editorDirectory = Join-Path $Root 'editor' $editorDirectory = Join-Path $Root 'editor'
$userHome = Join-Path $Root 'home' $userHome = Join-Path $Root 'home'
$templateDirectory = Join-Path $userHome "AppData\Roaming\Godot\export_templates\$templateVersion"
return [PSCustomObject]@{ return [PSCustomObject]@{
Root = $Root Root = $Root
EditorDirectory = $editorDirectory EditorDirectory = $editorDirectory
UserHome = $userHome UserHome = $userHome
TemplateDirectory = $templateDirectory TemplateDirectory = Join-Path $userHome "AppData\Roaming\Godot\export_templates\$TemplateVersion"
Marker = Join-Path $Root '.complete' Marker = Join-Path $Root '.complete'
} }
} }
function Get-EditorExecutable([string]$EditorDirectory) { function Get-EditorExecutable([string]$EditorDirectory, [string]$ExpectedFileName) {
$matches = @(Get-ChildItem -LiteralPath $EditorDirectory -Recurse -File -ErrorAction SilentlyContinue | $matches = @(Get-ChildItem -LiteralPath $EditorDirectory -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.Name -eq $expectedEditorFileName }) Where-Object { $_.Name -eq $ExpectedFileName })
if ($matches.Count -eq 1) { if ($matches.Count -eq 1) {
return $matches[0].FullName return $matches[0].FullName
} }
return $null return $null
} }
function Get-PeMachine([string]$Path) { function Get-PeMachine([string]$Path) {
try { try {
$bytes = [IO.File]::ReadAllBytes($Path) $stream = [IO.File]::Open($Path, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::Read)
try {
if ($stream.Length -lt 64) { return $null }
$header = New-Object byte[] 64
if ($stream.Read($header, 0, $header.Length) -ne $header.Length -or $header[0] -ne 0x4d -or $header[1] -ne 0x5a) {
return $null
}
$peOffset = [BitConverter]::ToInt32($header, 0x3c)
if ($peOffset -lt 0 -or ($peOffset + 6) -gt $stream.Length) { return $null }
$stream.Position = $peOffset
$signature = New-Object byte[] 6
if ($stream.Read($signature, 0, $signature.Length) -ne $signature.Length) { return $null }
if ($signature[0] -ne 0x50 -or $signature[1] -ne 0x45 -or $signature[2] -ne 0 -or $signature[3] -ne 0) { return $null }
return [BitConverter]::ToUInt16($signature, 4)
} finally {
$stream.Dispose()
}
} catch { } catch {
return $null return $null
} }
if ($bytes.Length -lt 64 -or $bytes[0] -ne 0x4d -or $bytes[1] -ne 0x5a) {
return $null
}
$peOffset = [BitConverter]::ToInt32($bytes, 0x3c)
if ($peOffset -lt 0 -or $peOffset -gt ($bytes.Length - 6)) {
return $null
}
if ($bytes[$peOffset] -ne 0x50 -or $bytes[$peOffset + 1] -ne 0x45 -or $bytes[$peOffset + 2] -ne 0 -or $bytes[$peOffset + 3] -ne 0) {
return $null
}
return [BitConverter]::ToUInt16($bytes, $peOffset + 4)
} }
function Test-ExpectedEditor([string]$EditorDirectory) { function Test-ExpectedEditor([string]$EditorDirectory, [string]$ExpectedFileName, [uint16]$ExpectedMachine) {
$editorExecutable = Get-EditorExecutable $EditorDirectory $editorExecutable = Get-EditorExecutable $EditorDirectory $ExpectedFileName
if (-not $editorExecutable) { return $null -ne $editorExecutable -and (Get-PeMachine $editorExecutable) -eq $ExpectedMachine
return $false
}
return (Get-PeMachine $editorExecutable) -eq $expectedPeMachine
} }
function Assert-ExpectedEditor([string]$EditorDirectory) { function Assert-ExpectedEditor([string]$EditorDirectory, [string]$ExpectedFileName, [uint16]$ExpectedMachine, [string]$Architecture) {
$editorExecutable = Get-EditorExecutable $EditorDirectory $editorExecutable = Get-EditorExecutable $EditorDirectory $ExpectedFileName
if (-not $editorExecutable) { if ($null -eq $editorExecutable) {
Fail "The Godot editor archive did not contain the expected console executable '$expectedEditorFileName'." Fail "The Godot editor archive did not contain the expected console executable '$ExpectedFileName'."
} }
if ((Get-PeMachine $editorExecutable) -ne $ExpectedMachine) {
$machine = Get-PeMachine $editorExecutable Fail "The expected Godot console executable '$ExpectedFileName' is not a valid $Architecture Windows executable."
if ($machine -ne $expectedPeMachine) {
Fail "The expected Godot console executable '$expectedEditorFileName' is not a valid $HostArch Windows executable."
} }
return $editorExecutable return $editorExecutable
} }
function Test-ValidCache($Paths) { function Test-ValidCache($Paths, [string]$TemplateVersion, [string]$ExpectedFileName, [uint16]$ExpectedMachine) {
if (-not (Test-Path -LiteralPath $Paths.Marker -PathType Leaf)) { if (-not (Test-Path -LiteralPath $Paths.Marker -PathType Leaf)) { return $false }
return $false
}
$installedVersion = Join-Path $Paths.TemplateDirectory 'version.txt' $installedVersion = Join-Path $Paths.TemplateDirectory 'version.txt'
if (-not (Test-Path -LiteralPath $installedVersion -PathType Leaf)) { if (-not (Test-Path -LiteralPath $installedVersion -PathType Leaf)) { return $false }
return $false if ((Get-Content -LiteralPath $installedVersion -Raw).Trim() -ne $TemplateVersion) { return $false }
} return Test-ExpectedEditor $Paths.EditorDirectory $ExpectedFileName $ExpectedMachine
if ((Get-Content -LiteralPath $installedVersion -Raw).Trim() -ne $templateVersion) {
return $false
}
return Test-ExpectedEditor $Paths.EditorDirectory
} }
function Install-ExportTemplates($Paths, [string]$StagingDirectory, [string]$TemplateAsset) { function Install-ExportTemplates($Paths, [string]$StagingDirectory, [string]$TemplateAsset, [string]$TemplateVersion) {
$stagedTemplates = Join-Path $StagingDirectory 'templates' $stagedTemplates = Join-Path $StagingDirectory 'templates'
$stagedVersion = Join-Path $stagedTemplates 'version.txt' $stagedVersion = Join-Path $stagedTemplates 'version.txt'
if (-not (Test-Path -LiteralPath $stagedVersion -PathType Leaf)) { if (-not (Test-Path -LiteralPath $stagedVersion -PathType Leaf)) {
Fail "The export-template archive '$TemplateAsset' did not contain templates/version.txt." Fail "The export-template archive '$TemplateAsset' did not contain templates/version.txt."
} }
if ((Get-Content -LiteralPath $stagedVersion -Raw).Trim() -ne $TemplateVersion) {
$actualVersion = (Get-Content -LiteralPath $stagedVersion -Raw).Trim() Fail "The export-template archive '$TemplateAsset' reports template version '$((Get-Content -LiteralPath $stagedVersion -Raw).Trim())', expected '$TemplateVersion'."
if ($actualVersion -ne $templateVersion) {
Fail "The export-template archive '$TemplateAsset' reports template version '$actualVersion', expected '$templateVersion'."
} }
New-Item -ItemType Directory -Force -Path $Paths.TemplateDirectory | Out-Null New-Item -ItemType Directory -Force -Path $Paths.TemplateDirectory | Out-Null
Get-ChildItem -LiteralPath $stagedTemplates -Force | Copy-Item -Destination $Paths.TemplateDirectory -Recurse -Force Get-ChildItem -LiteralPath $stagedTemplates -Force | Copy-Item -Destination $Paths.TemplateDirectory -Recurse -Force
if (-not (Test-Path -LiteralPath (Join-Path $Paths.TemplateDirectory 'version.txt') -PathType Leaf)) { if (-not (Test-Path -LiteralPath (Join-Path $Paths.TemplateDirectory 'version.txt') -PathType Leaf)) {
Fail "The export-template archive '$TemplateAsset' could not be installed to '$($Paths.TemplateDirectory)'." Fail "The export-template archive '$TemplateAsset' could not be installed to '$($Paths.TemplateDirectory)'."
} }
} }
function Install-Cache($Paths) { function Install-GodotCache($Paths, $Assets, [uint16]$ExpectedMachine, [string]$Architecture, [string]$Version, [string]$BaseUrl) {
New-Item -ItemType Directory -Force -Path $Paths.EditorDirectory | Out-Null New-Item -ItemType Directory -Force -Path $Paths.EditorDirectory | Out-Null
$manifestPath = Join-Path $Paths.Root 'SHA512-SUMS.txt' $manifestPath = Join-Path $Paths.Root 'SHA512-SUMS.txt'
$editorArchive = Join-Path $Paths.Root $editorAsset $editorArchive = Join-Path $Paths.Root $Assets.EditorAsset
$templatesArchive = Join-Path $Paths.Root $templatesAsset $templatesArchive = Join-Path $Paths.Root $Assets.TemplatesAsset
$templatesZipArchive = Join-Path $Paths.Root 'export-templates.zip' $templatesZipArchive = Join-Path $Paths.Root 'export-templates.zip'
$templatesStagingDirectory = Join-Path $Paths.Root 'templates-staging' $templatesStagingDirectory = Join-Path $Paths.Root 'templates-staging'
Invoke-WebRequest -UseBasicParsing -Uri "$script:BaseUrl/SHA512-SUMS.txt" -OutFile $manifestPath Invoke-Download "$BaseUrl/SHA512-SUMS.txt" $manifestPath
$editorChecksum = Get-Checksum $manifestPath $editorAsset $editorChecksum = Get-Checksum $manifestPath $Assets.EditorAsset $Version $Assets.Edition $Architecture $BaseUrl
$templatesChecksum = Get-Checksum $manifestPath $templatesAsset $templatesChecksum = Get-Checksum $manifestPath $Assets.TemplatesAsset $Version $Assets.Edition $Architecture $BaseUrl
Download-AndVerify $editorAsset $editorArchive $editorChecksum Invoke-VerifiedDownload "$BaseUrl/$($Assets.EditorAsset)" $editorArchive $editorChecksum
Download-AndVerify $templatesAsset $templatesArchive $templatesChecksum Invoke-VerifiedDownload "$BaseUrl/$($Assets.TemplatesAsset)" $templatesArchive $templatesChecksum
Expand-Archive -LiteralPath $editorArchive -DestinationPath $Paths.EditorDirectory -Force Expand-Archive -LiteralPath $editorArchive -DestinationPath $Paths.EditorDirectory -Force
Assert-ExpectedEditor $Paths.EditorDirectory | Out-Null Assert-ExpectedEditor $Paths.EditorDirectory $Assets.EditorFileName $ExpectedMachine $Architecture | Out-Null
# Expand-Archive only recognizes .zip files. The verified .tpz payload is a ZIP archive. # Expand-Archive recognizes .zip only; Godot's verified .tpz payload is a ZIP archive.
Move-Item -LiteralPath $templatesArchive -Destination $templatesZipArchive Copy-Item -LiteralPath $templatesArchive -Destination $templatesZipArchive -Force
Expand-Archive -LiteralPath $templatesZipArchive -DestinationPath $templatesStagingDirectory -Force Expand-Archive -LiteralPath $templatesZipArchive -DestinationPath $templatesStagingDirectory -Force
Install-ExportTemplates $Paths $templatesStagingDirectory $templatesAsset Install-ExportTemplates $Paths $templatesStagingDirectory $Assets.TemplatesAsset $Assets.TemplateVersion
Remove-Item -LiteralPath $templatesStagingDirectory -Recurse -Force Remove-Item -LiteralPath $templatesStagingDirectory -Recurse -Force
@("release=$GodotVersion", "editor=$editorAsset", "templates=$templatesAsset") | @("release=$Version", "editor=$($Assets.EditorAsset)", "templates=$($Assets.TemplatesAsset)") |
Set-Content -LiteralPath $Paths.Marker -NoNewline Set-Content -LiteralPath $Paths.Marker -NoNewline -Encoding ASCII
} }
function Invoke-GodotExport([string]$EditorExecutable, [string]$ProjectDirectory, [string]$ExportMode, [string]$ExportPreset, [string]$OutputFile, [scriptblock]$EditorRunner) {
try {
if ($null -ne $EditorRunner) {
& $EditorRunner $EditorExecutable $ProjectDirectory $ExportMode $ExportPreset $OutputFile
} else {
& $EditorExecutable --headless --path $ProjectDirectory "--export-$ExportMode" $ExportPreset $OutputFile
}
} catch {
Fail "Godot could not start '$EditorExecutable': $($_.Exception.Message)"
}
if ($LASTEXITCODE -ne 0) {
Fail "Godot export failed with exit code $LASTEXITCODE."
}
if (-not (Test-Path -LiteralPath $OutputFile -PathType Leaf)) {
Fail "Godot completed without creating the expected output '$(Split-Path -Leaf $OutputFile)'."
}
}
if ($SkipExecution) { return }
$GodotVersion = Require-Environment 'GODOT_VERSION' $GodotVersion = Require-Environment 'GODOT_VERSION'
$HostOs = Require-Environment 'GODOT_HOST_OS' $HostOs = Require-Environment 'GODOT_HOST_OS'
$HostArch = Require-Environment 'GODOT_HOST_ARCH' $HostArch = Require-Environment 'GODOT_HOST_ARCH'
@@ -228,54 +300,28 @@ $workspaceDirectory = [IO.Path]::GetFullPath($Workspace)
if ([IO.Path]::IsPathRooted($ProjectPath)) { Fail 'project-path must be relative to the checked-out workspace.' } if ([IO.Path]::IsPathRooted($ProjectPath)) { Fail 'project-path must be relative to the checked-out workspace.' }
$ProjectDirectory = [IO.Path]::GetFullPath((Join-Path $workspaceDirectory $ProjectPath)) $ProjectDirectory = [IO.Path]::GetFullPath((Join-Path $workspaceDirectory $ProjectPath))
if (-not (Test-PathIsWithinDirectory $workspaceDirectory $ProjectDirectory)) { Fail 'project-path must remain inside the checked-out workspace.' } if (-not (Test-PathIsWithinDirectory $workspaceDirectory $ProjectDirectory)) { Fail 'project-path must remain inside the checked-out workspace.' }
if (-not (Test-Path -LiteralPath $ProjectDirectory -PathType Container)) { Fail "project-path '$ProjectPath' does not exist." }
if (-not (Test-Path -LiteralPath (Join-Path $ProjectDirectory 'project.godot') -PathType Leaf)) { Fail "No project.godot was found in project-path '$ProjectPath'." } if (-not (Test-Path -LiteralPath (Join-Path $ProjectDirectory 'project.godot') -PathType Leaf)) { Fail "No project.godot was found in project-path '$ProjectPath'." }
$PresetFile = Join-Path $ProjectDirectory 'export_presets.cfg' $presetFile = Join-Path $ProjectDirectory 'export_presets.cfg'
if (-not (Test-Path -LiteralPath $PresetFile -PathType Leaf)) { Fail "No export_presets.cfg was found in project-path '$ProjectPath'." } if (-not (Test-Path -LiteralPath $presetFile -PathType Leaf)) { Fail "No export_presets.cfg was found in project-path '$ProjectPath'." }
if (-not (Select-String -LiteralPath $PresetFile -SimpleMatch "name=`"$ExportPreset`"" -Quiet)) { Fail "Export preset '$ExportPreset' was not found in export_presets.cfg." } if (-not (Select-String -LiteralPath $presetFile -SimpleMatch "name=`"$ExportPreset`"" -Quiet)) { Fail "Export preset '$ExportPreset' was not found in export_presets.cfg." }
if ($Dotnet -eq 'true') { $assets = Get-GodotAssets $GodotVersion $Dotnet $HostArch
$edition = 'dotnet' $expectedMachine = Get-ExpectedPeMachine $HostArch
$editorBaseName = switch ($HostArch) { $baseUrl = "https://github.com/godotengine/godot/releases/download/$GodotVersion"
'x86_32' { "Godot_v${GodotVersion}_mono_win32" } $cacheDirectory = Join-Path $ActionRoot "cache\$GodotVersion\$($assets.Edition)\windows-$HostArch"
'x86_64' { "Godot_v${GodotVersion}_mono_win64" } $cachePaths = Get-CachePaths $cacheDirectory $assets.TemplateVersion
'arm64' { "Godot_v${GodotVersion}_mono_windows_arm64" }
}
$editorAsset = "$editorBaseName.zip"
$templatesAsset = "Godot_v${GodotVersion}_mono_export_templates.tpz"
$templateVersion = ($GodotVersion -replace '-', '.') + '.mono'
} else {
$edition = 'standard'
$editorBaseName = switch ($HostArch) {
'x86_32' { "Godot_v${GodotVersion}_win32" }
'x86_64' { "Godot_v${GodotVersion}_win64" }
'arm64' { "Godot_v${GodotVersion}_windows_arm64" }
}
$editorAsset = "$editorBaseName.exe.zip"
$templatesAsset = "Godot_v${GodotVersion}_export_templates.tpz"
$templateVersion = $GodotVersion -replace '-', '.'
}
$expectedEditorFileName = "${editorBaseName}_console.exe" if (-not (Test-ValidCache $cachePaths $assets.TemplateVersion $assets.EditorFileName $expectedMachine)) {
$expectedPeMachine = switch ($HostArch) {
'x86_32' { [uint16]0x014c }
'x86_64' { [uint16]0x8664 }
'arm64' { [uint16]0xaa64 }
}
$script:BaseUrl = "https://github.com/godotengine/godot/releases/download/$GodotVersion"
$cacheDirectory = Join-Path $ActionRoot "cache\$GodotVersion\$edition\windows-$HostArch"
$cachePaths = Get-CachePaths $cacheDirectory
if (-not (Test-ValidCache $cachePaths)) {
$cacheParent = Split-Path -Parent $cacheDirectory $cacheParent = Split-Path -Parent $cacheDirectory
$stagingDirectory = Join-Path $cacheParent ((Split-Path -Leaf $cacheDirectory) + ".staging-$PID") $stagingDirectory = Join-Path $cacheParent ((Split-Path -Leaf $cacheDirectory) + ".staging-$PID")
if (Test-Path -LiteralPath $stagingDirectory) { Remove-Item -LiteralPath $stagingDirectory -Recurse -Force } if (Test-Path -LiteralPath $stagingDirectory) { Remove-Item -LiteralPath $stagingDirectory -Recurse -Force }
New-Item -ItemType Directory -Force -Path $cacheParent | Out-Null New-Item -ItemType Directory -Force -Path $cacheParent | Out-Null
try { try {
$stagingPaths = Get-CachePaths $stagingDirectory $stagingPaths = Get-CachePaths $stagingDirectory $assets.TemplateVersion
Install-Cache $stagingPaths Install-GodotCache $stagingPaths $assets $expectedMachine $HostArch $GodotVersion $baseUrl
if (-not (Test-ValidCache $stagingPaths)) { Fail 'Godot cache installation did not pass validation.' } if (-not (Test-ValidCache $stagingPaths $assets.TemplateVersion $assets.EditorFileName $expectedMachine)) { Fail 'Godot cache installation did not pass validation.' }
if (Test-Path -LiteralPath $cacheDirectory) { Remove-Item -LiteralPath $cacheDirectory -Recurse -Force } if (Test-Path -LiteralPath $cacheDirectory) { Remove-Item -LiteralPath $cacheDirectory -Recurse -Force }
Move-Item -LiteralPath $stagingDirectory -Destination $cacheDirectory Move-Item -LiteralPath $stagingDirectory -Destination $cacheDirectory
} finally { } finally {
@@ -283,7 +329,7 @@ if (-not (Test-ValidCache $cachePaths)) {
} }
} }
$editorExecutable = Assert-ExpectedEditor $cachePaths.EditorDirectory $editorExecutable = Assert-ExpectedEditor $cachePaths.EditorDirectory $assets.EditorFileName $expectedMachine $HostArch
$safePreset = ($ExportPreset -replace '[^A-Za-z0-9_.-]', '_').Trim('_') $safePreset = ($ExportPreset -replace '[^A-Za-z0-9_.-]', '_').Trim('_')
if ([string]::IsNullOrWhiteSpace($safePreset)) { $safePreset = 'export' } if ([string]::IsNullOrWhiteSpace($safePreset)) { $safePreset = 'export' }
$buildDirectory = Join-Path $ActionRoot "builds\$safePreset-$ExportMode-$PID" $buildDirectory = Join-Path $ActionRoot "builds\$safePreset-$ExportMode-$PID"
@@ -293,14 +339,6 @@ New-Item -ItemType Directory -Force -Path $buildDirectory | Out-Null
$env:USERPROFILE = $cachePaths.UserHome $env:USERPROFILE = $cachePaths.UserHome
$env:APPDATA = Join-Path $cachePaths.UserHome 'AppData\Roaming' $env:APPDATA = Join-Path $cachePaths.UserHome 'AppData\Roaming'
$env:LOCALAPPDATA = Join-Path $cachePaths.UserHome 'AppData\Local' $env:LOCALAPPDATA = Join-Path $cachePaths.UserHome 'AppData\Local'
Invoke-GodotExport $editorExecutable $ProjectDirectory $ExportMode $ExportPreset $outputFile $null
try { "build-directory=$buildDirectory" | Add-Content -LiteralPath $GithubOutput -Encoding ASCII
& $editorExecutable --headless --path $ProjectDirectory "--export-$ExportMode" $ExportPreset $outputFile
} catch {
Fail "Godot could not start '$editorExecutable': $($_.Exception.Message)"
}
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
if (-not (Test-Path -LiteralPath $outputFile)) { Fail "Godot completed without creating the expected output '$ExportFileName'." }
"build-directory=$buildDirectory" | Add-Content -LiteralPath $GithubOutput