Files
Alphaeus Mote 6d8d6b713b ci: align Go toolchain to go.mod (1.25)
go get bumped go.mod to 'go 1.25.0' (modernc requirement), but CI used setup-go
1.24 and the image used golang:1.24 — with GOTOOLCHAIN=local the test step failed
('requires go >= 1.25.0'). Install the exact version from go.mod via
go-version-file, bump the builder image to golang:1.25-alpine, and drop the stray
GOTOOLCHAIN override in build.ps1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 09:33:57 -04:00

181 lines
7.1 KiB
PowerShell

# OrchestrAD Build Script
# Builds for Windows, macOS, and Linux (amd64 and arm64)
# Version format: yyyy.MM.dd.HHmm
param(
[switch]$All,
[switch]$Windows,
[switch]$MacOS,
[switch]$Linux,
[switch]$Clean,
[switch]$SkipFrontend
)
$ErrorActionPreference = "Stop"
# Version generation
$Version = Get-Date -Format "yyyy.MM.dd.HHmm"
$BuildTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
$GitCommit = git rev-parse --short HEAD 2>$null
if (-not $GitCommit) { $GitCommit = "unknown" }
Write-Host "Building OrchestrAD v$Version" -ForegroundColor Cyan
Write-Host "Build Time: $BuildTime"
Write-Host "Git Commit: $GitCommit"
$ProjectRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
if (-not (Test-Path "$ProjectRoot\backend")) {
$ProjectRoot = Split-Path -Parent $PSScriptRoot
}
$BackendDir = Join-Path $ProjectRoot "backend"
$FrontendDir = Join-Path $ProjectRoot "frontend"
$FrontendOut = Join-Path $FrontendDir "out"
$WebUIDist = Join-Path $BackendDir "internal\webui\dist"
$BinariesDir = Join-Path $ProjectRoot "binaries"
$ResourcesDir = Join-Path $ProjectRoot "resources"
# Clean binaries directory if requested
if ($Clean) {
Write-Host "Cleaning binaries directory..." -ForegroundColor Yellow
if (Test-Path $BinariesDir) {
Remove-Item -Recurse -Force $BinariesDir
}
}
# Build the frontend and stage it into the backend embed directory so the
# produced binary ships the full UI (see docs/DesignSpecification.md §6.2.1).
if (-not $SkipFrontend) {
Write-Host "`nBuilding frontend (Next.js static export)..." -ForegroundColor Cyan
Push-Location $FrontendDir
try {
if (-not (Test-Path (Join-Path $FrontendDir "node_modules"))) {
Write-Host " Installing frontend dependencies..." -ForegroundColor Yellow
npm install
if ($LASTEXITCODE -ne 0) { throw "npm install failed" }
}
npm run build
if ($LASTEXITCODE -ne 0) { throw "frontend build failed" }
} finally {
Pop-Location
}
if (-not (Test-Path $FrontendOut) -or -not (Get-ChildItem $FrontendOut -File -Recurse | Select-Object -First 1)) {
throw "Frontend output directory '$FrontendOut' is missing or empty after build. Refusing to produce a binary without the UI."
}
Write-Host "Staging frontend assets into $WebUIDist..." -ForegroundColor Cyan
if (-not (Test-Path $WebUIDist)) { New-Item -ItemType Directory -Path $WebUIDist -Force | Out-Null }
Get-ChildItem -LiteralPath $WebUIDist -Force | Where-Object { $_.Name -ne ".gitignore" } | Remove-Item -Recurse -Force
Copy-Item -Path (Join-Path $FrontendOut "*") -Destination $WebUIDist -Recurse -Force
$uiFileCount = (Get-ChildItem $WebUIDist -Recurse -File).Count
Write-Host " Staged $uiFileCount UI files" -ForegroundColor Green
} else {
Write-Host "`nSkipping frontend build (--SkipFrontend)." -ForegroundColor Yellow
if (-not (Test-Path (Join-Path $WebUIDist "_next"))) {
Write-Host " Warning: $WebUIDist does not contain a built UI; binary will ship the placeholder page." -ForegroundColor Yellow
}
}
# Create output directories
$Platforms = @(
@{ OS = "windows"; Arch = "amd64"; Ext = ".exe" },
@{ OS = "windows"; Arch = "arm64"; Ext = ".exe" },
@{ OS = "darwin"; Arch = "amd64"; Ext = "" },
@{ OS = "darwin"; Arch = "arm64"; Ext = "" },
@{ OS = "linux"; Arch = "amd64"; Ext = "" },
@{ OS = "linux"; Arch = "arm64"; Ext = "" }
)
# Filter platforms based on flags
if (-not $All) {
if ($Windows) {
$Platforms = $Platforms | Where-Object { $_.OS -eq "windows" }
} elseif ($MacOS) {
$Platforms = $Platforms | Where-Object { $_.OS -eq "darwin" }
} elseif ($Linux) {
$Platforms = $Platforms | Where-Object { $_.OS -eq "linux" }
} else {
# Default to all platforms
$All = $true
}
}
# LDFlags for version injection
$LDFlags = "-s -w -X github.com/Grace-Solutions/OrchestrAD/internal/version.Version=$Version -X github.com/Grace-Solutions/OrchestrAD/internal/version.BuildTime=$BuildTime -X github.com/Grace-Solutions/OrchestrAD/internal/version.GitCommit=$GitCommit"
# Generate the Windows icon/version resource so the windows/* binaries embed the
# OrchestrAD icon. goversioninfo is a pure-Go tool and runs on any host; the
# arch-suffixed .syso files are only linked into their matching GOARCH build.
$BuildWindows = $All -or ($Platforms | Where-Object { $_.OS -eq "windows" })
if ($BuildWindows) {
Write-Host "`nGenerating Windows resource (icon + version metadata)..." -ForegroundColor Cyan
$GoVersionInfo = Join-Path (Join-Path $env:USERPROFILE "go\bin") "goversioninfo.exe"
if (-not (Test-Path $GoVersionInfo)) {
Write-Host " Installing goversioninfo..." -ForegroundColor Yellow
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@v1.7.0
}
$vp = $Version -split '\.'
Push-Location $BackendDir
try {
foreach ($a in @(@{arch='amd64';flags=@('-64')}, @{arch='arm64';flags=@('-64','-arm')})) {
$out = "cmd\orchestrad\resource_windows_$($a.arch).syso"
& $GoVersionInfo @($a.flags) `
"-ver-major=$([int]$vp[0])" "-ver-minor=$([int]$vp[1])" "-ver-patch=$([int]$vp[2])" "-ver-build=$([int]$vp[3])" `
"-product-version=$([int]$vp[0]).$([int]$vp[1]).$([int]$vp[2])" `
"-o" $out "versioninfo.json"
}
} finally {
Pop-Location
}
}
Push-Location $BackendDir
try {
foreach ($Platform in $Platforms) {
$OS = $Platform.OS
$Arch = $Platform.Arch
$Ext = $Platform.Ext
# Map darwin to macos for folder naming
$FolderOS = if ($OS -eq "darwin") { "macos" } else { $OS }
$OutputDir = Join-Path $BinariesDir "$FolderOS\$Arch"
$OutputFile = Join-Path $OutputDir "orchestrad$Ext"
# Create output directory
if (-not (Test-Path $OutputDir)) {
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
}
Write-Host "`nBuilding for $OS/$Arch..." -ForegroundColor Green
# Pure-Go build (modernc.org/sqlite): CGO is disabled, so every target
# cross-compiles from any host with no C toolchain. Windows binaries pick
# up the icon/version resource generated into cmd/orchestrad before the
# loop (resource_windows_<arch>.syso).
$env:GOOS = $OS
$env:GOARCH = $Arch
$env:CGO_ENABLED = "0"
go build -ldflags "$LDFlags" -o "$OutputFile" ./cmd/orchestrad
if ($LASTEXITCODE -eq 0) {
$FileSize = (Get-Item $OutputFile).Length / 1MB
Write-Host " Built: $OutputFile ($([math]::Round($FileSize, 2)) MB)" -ForegroundColor Green
} else {
Write-Host " Failed to build for $OS/$Arch" -ForegroundColor Red
}
}
} finally {
Pop-Location
Remove-Item Env:GOOS -ErrorAction SilentlyContinue
Remove-Item Env:GOARCH -ErrorAction SilentlyContinue
Remove-Item Env:CGO_ENABLED -ErrorAction SilentlyContinue
}
Write-Host "`nBuild complete!" -ForegroundColor Cyan
Write-Host "Binaries are in: $BinariesDir"