From 4ee4a2bb4335ade89efe1c9078c3cd2cb6a9932e Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 22 May 2026 14:23:09 +0000 Subject: [PATCH] scripts: make Build-Pack and Deploy-Brass cross-platform Two small fixes that surface when running the deploy pipeline on a non-Windows host (we now do this on glados via the Telegram bridge): - Build-Pack.ps1: fall back to launcher/ModpackLauncher.csproj when Get-Item.VersionInfo.FileVersion returns empty. Linux PowerShell can't parse PE FileVersion from a Windows .exe, so the previous code threw "set in ModpackLauncher.csproj and republish" -- but the csproj *was* set, just not readable from a foreign PE. Appends ".0" so the embedded value still matches the 4-part form the Windows compile bakes in. - Deploy-Brass.ps1: prefer rsync where available, fall back to robocopy otherwise. robocopy is Windows-only and bails on Linux/macOS hosts. --- scripts/Build-Pack.ps1 | 21 +++++++++++++++++++-- scripts/Deploy-Brass.ps1 | 25 ++++++++++++++++++++----- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/scripts/Build-Pack.ps1 b/scripts/Build-Pack.ps1 index 12b305f..50965cd 100644 --- a/scripts/Build-Pack.ps1 +++ b/scripts/Build-Pack.ps1 @@ -163,8 +163,25 @@ if ($LauncherExePath) { } $launcherFile = Get-Item $LauncherExePath $launcherVersion = $launcherFile.VersionInfo.FileVersion + $versionSource = 'PE FileVersion' + + # Linux PowerShell can't read PE FileVersion from a Windows .exe. When that + # happens, fall back to launcher/ModpackLauncher.csproj's (the + # source of truth that the Windows compile bakes into FileVersion anyway). + # Append ".0" so callers get the same 4-part form as the PE metadata. if ([string]::IsNullOrWhiteSpace($launcherVersion)) { - throw "Launcher exe has no FileVersion -- set in ModpackLauncher.csproj and republish." + $csprojPath = Join-Path $here '..\launcher\ModpackLauncher.csproj' + if (Test-Path $csprojPath) { + [xml]$csproj = Get-Content $csprojPath + $csprojVersion = ($csproj.Project.PropertyGroup.Version | Where-Object { $_ }) | Select-Object -First 1 + if ($csprojVersion) { + $launcherVersion = if ($csprojVersion -match '^\d+\.\d+\.\d+$') { "$csprojVersion.0" } else { $csprojVersion } + $versionSource = "csproj (fallback)" + } + } + } + if ([string]::IsNullOrWhiteSpace($launcherVersion)) { + throw "Launcher exe has no FileVersion and csproj couldn't be read either -- set in ModpackLauncher.csproj and republish." } # FileVersion is the four-component form (e.g. "0.1.0.0" for csproj 0.1.0). # Embed as-is -- the launcher's Version.Parse handles it directly and avoids ambiguous @@ -174,7 +191,7 @@ if ($LauncherExePath) { Write-Host "" Write-Host ("Launcher metadata embedded:") - Write-Host (" Version: {0}" -f $launcherVersion) + Write-Host (" Version: {0} ({1})" -f $launcherVersion, $versionSource) Write-Host (" Url: {0}" -f $LauncherPublicUrl) Write-Host (" Source: {0}" -f $launcherFile.FullName) } diff --git a/scripts/Deploy-Brass.ps1 b/scripts/Deploy-Brass.ps1 index fe8c589..eab37c3 100644 --- a/scripts/Deploy-Brass.ps1 +++ b/scripts/Deploy-Brass.ps1 @@ -214,11 +214,26 @@ $overridesLocal = Join-Path $repoRoot 'pack\overrides' $shareFiles = Join-Path $DeployShare 'files' if ($shouldRunPack -and (Test-Path $overridesLocal)) { Step "Mirror pack/overrides/ -> $shareFiles" { - # /MIR makes destination match source (deletes orphan files in $shareFiles). - # /XJ skips junctions, /R:1 /W:1 keeps retry behaviour sane on flaky shares. - robocopy $overridesLocal $shareFiles /MIR /XJ /R:1 /W:1 /NFL /NDL /NJH /NJS /NP | Out-Host - # Robocopy returns 0-7 for success-with-info; 8+ is real failure. - if ($LASTEXITCODE -ge 8) { throw "robocopy failed with exit $LASTEXITCODE" } + # Prefer rsync where available (Linux/macOS); fall back to Windows robocopy. + # Both perform a mirror: orphan files in the destination are removed so + # the share matches the local overrides exactly. + if (Get-Command rsync -ErrorAction SilentlyContinue) { + $src = ($overridesLocal -replace '\\','/').TrimEnd('/') + '/' + $dst = ($shareFiles -replace '\\','/').TrimEnd('/') + '/' + if (-not (Test-Path $shareFiles)) { New-Item -ItemType Directory -Path $shareFiles -Force | Out-Null } + & rsync -a --delete $src $dst + if ($LASTEXITCODE -ne 0) { throw "rsync failed with exit $LASTEXITCODE" } + } + elseif (Get-Command robocopy -ErrorAction SilentlyContinue) { + # /MIR makes destination match source (deletes orphan files in $shareFiles). + # /XJ skips junctions, /R:1 /W:1 keeps retry behaviour sane on flaky shares. + robocopy $overridesLocal $shareFiles /MIR /XJ /R:1 /W:1 /NFL /NDL /NJH /NJS /NP | Out-Host + # Robocopy returns 0-7 for success-with-info; 8+ is real failure. + if ($LASTEXITCODE -ge 8) { throw "robocopy failed with exit $LASTEXITCODE" } + } + else { + throw "Neither rsync nor robocopy is available -- can't mirror pack overrides." + } } }