6d8d6b713b
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>
181 lines
7.1 KiB
PowerShell
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"
|