Files
LinkPort/scripts/package.ps1
T

80 lines
3.9 KiB
PowerShell

param([string]$Version, [switch]$RebuildWeb)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'build-lock.ps1')
$buildLock = Enter-LinkPortBuildLock
$previousPath = $env:PATH
try {
$totalTimer = [Diagnostics.Stopwatch]::StartNew()
$phaseTimer = [Diagnostics.Stopwatch]::StartNew()
function Write-PhaseTime([string]$Name) {
Write-Host ('{0}: {1:N1}s' -f $Name, $phaseTimer.Elapsed.TotalSeconds)
$phaseTimer.Restart()
}
. (Join-Path $PSScriptRoot 'version.ps1')
$buildInfo = Get-linkportBuildInfo -Version $Version
$Version = $buildInfo.Version
$repo = Split-Path $PSScriptRoot -Parent
. (Join-Path $PSScriptRoot 'go-toolchain.ps1')
$goExecutable = Get-LinkPortGoExecutable -ProjectRoot $repo
. (Join-Path $PSScriptRoot 'node-toolchain.ps1')
$nodeExecutable = Initialize-LinkPortNodeRuntime -ProjectRoot $repo
$stamp = (Get-Date -Format 'yyyyMMdd-HHmmss-fff') + '-' + [Guid]::NewGuid().ToString('N').Substring(0, 8)
$releaseRoot = Join-Path $repo "bin/releases/$stamp"
$stage = [IO.Path]::GetFullPath((Join-Path $repo "bin/build-cache/package-$stamp"))
$binary = Join-Path $stage 'linkport.exe'
$releaseBinary = Join-Path $releaseRoot 'linkport.exe'
$previous = @{}
foreach ($key in @('GOTOOLCHAIN','GO111MODULE','GOOS','GOARCH','CGO_ENABLED','LINKPORT_NO_BROWSER')) { $previous[$key] = [Environment]::GetEnvironmentVariable($key, 'Process') }
$keepPath = Join-Path $repo 'web/dist/.gitkeep'
$hadKeep = Test-Path -LiteralPath $keepPath
$keepBytes = [byte[]]@()
if ($hadKeep) { $keepBytes = [IO.File]::ReadAllBytes($keepPath) }
Push-Location -LiteralPath $repo
try {
$env:GOTOOLCHAIN = 'go1.27.1'
$env:GO111MODULE = 'on'
$env:LINKPORT_NO_BROWSER = '1'
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
$env:CGO_ENABLED = '0'
$webArguments = @((Join-Path $PSScriptRoot 'build-web.mjs'))
if ($RebuildWeb) { $webArguments += '--force' }
& $nodeExecutable @webArguments
if ($LASTEXITCODE -ne 0) { throw 'Frontend build failed' }
Write-PhaseTime 'Frontend and dependencies'
New-Item -ItemType Directory -Path $stage | Out-Null
& $goExecutable build -trimpath -ldflags $buildInfo.LDFlags -o $binary ./cmd/linkport
if ($LASTEXITCODE -ne 0) { throw 'linkport release build failed' }
Write-PhaseTime 'Go build'
& $nodeExecutable (Join-Path $PSScriptRoot 'verify-package.mjs') $stage
if ($LASTEXITCODE -ne 0) { throw 'Package verification failed' }
Write-PhaseTime 'Executable verification'
# Publish only after verification. The generated paths must stay in this repository.
$cacheRoot = [IO.Path]::GetFullPath((Join-Path $repo 'bin/build-cache')) + [IO.Path]::DirectorySeparatorChar
$releasesRoot = [IO.Path]::GetFullPath((Join-Path $repo 'bin/releases'))
$releaseRoot = [IO.Path]::GetFullPath($releaseRoot)
if (!$stage.StartsWith($cacheRoot, [StringComparison]::OrdinalIgnoreCase) -or
!(($releaseRoot + [IO.Path]::DirectorySeparatorChar).StartsWith($releasesRoot + [IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase))) {
throw 'Unexpected package output path'
}
$digest = (Get-FileHash -LiteralPath $binary -Algorithm SHA256).Hash.ToLowerInvariant()
New-Item -ItemType Directory -Path $releasesRoot -Force | Out-Null
if (Test-Path -LiteralPath $releaseRoot) { throw 'Release directory already exists' }
Move-Item -LiteralPath $stage -Destination $releaseRoot
Write-Output $releaseBinary
Write-Output "SHA256: $digest"
Write-PhaseTime 'Single EXE output'
Write-Host ('Total: {0:N1}s' -f $totalTimer.Elapsed.TotalSeconds)
} finally {
if ($hadKeep) {
New-Item -ItemType Directory -Path (Split-Path $keepPath -Parent) -Force | Out-Null
[IO.File]::WriteAllBytes($keepPath, [byte[]]$keepBytes)
}
foreach ($key in $previous.Keys) { [Environment]::SetEnvironmentVariable($key, $previous[$key], 'Process') }
Pop-Location
}
} finally {
$env:PATH = $previousPath
$buildLock.Dispose()
}