Files
ARCADIA-Studio/scripts/package-linux.ps1
T

99 lines
5.5 KiB
PowerShell
Raw Normal View History

#Requires -Version 5.1
# Package already-built x86-64 glibc inputs or prepare strict server notices.
[CmdletBinding(DefaultParameterSetName = 'Package')]
param(
[ValidateSet('x86_64-unknown-linux-gnu')]
[string]$Target = 'x86_64-unknown-linux-gnu',
[Parameter(Mandatory = $true, ParameterSetName = 'Package')]
[ValidatePattern('^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$')]
[string]$Version,
[Parameter(Mandatory = $true, ParameterSetName = 'Package')]
[string]$BinaryDirectory,
[Parameter(Mandatory = $true, ParameterSetName = 'Notices')]
[switch]$ServerNoticesOnly,
[string]$BuildEvidence,
[string]$Python = 'python',
[string]$NoticeManifest = (Join-Path $PSScriptRoot 'windows-notices/manifest.json'),
[string]$OutputRoot = (Join-Path $PSScriptRoot '../dist')
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$repository = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
$encoding = New-Object Text.UTF8Encoding($false)
. (Join-Path $PSScriptRoot 'package-common.ps1')
. (Join-Path $PSScriptRoot 'windows-notices.ps1')
$inputs = [ordered]@{}
$inspectedHashes = @{}
$imports = [ordered]@{}
$evidence = $null
if (-not $ServerNoticesOnly) {
$binaryHashes = [ordered]@{}
foreach ($name in @('arcadia-studio', 'arcadia-server')) {
$path = [IO.Path]::GetFullPath((Join-Path $BinaryDirectory $name))
$elf = Invoke-PackageHelper $Python @('elf', $path)
$inputs[$name] = $path
$imports[$name] = $elf
$inspectedHashes[$name] = $elf.sha256
$binaryHashes[$name] = $elf.sha256
}
$evidence = Read-PackageBuildEvidence $BuildEvidence $Target $binaryHashes
$documentation = Get-PackageDocumentation $repository 'linux' $Python
foreach ($name in $documentation.Keys) { $inputs[$name] = $documentation[$name] }
$notices = Get-ArcadiaNotices $repository $Target $NoticeManifest ''
} else {
if ($BuildEvidence) { throw '-BuildEvidence applies to a binary package, not a notice-only bundle.' }
$notices = Get-ArcadiaNotices $repository $Target $NoticeManifest '' @('oa-server')
$inputs['LICENSE'] = Join-Path $repository 'LICENSE'
}
foreach ($name in $notices.Inputs.Keys) {
if ($inputs.Contains($name)) { throw "Notice collides with package input: $name" }
$inputs[$name] = $notices.Inputs[$name]
$inspectedHashes[$name] = $notices.Hashes[$name]
}
$output = [IO.Path]::GetFullPath($OutputRoot)
$packageName = if ($ServerNoticesOnly) { 'server-notices' } else { "ArcadiaStudio-$Version-$Target" }
$stage = Join-Path $output $packageName
$archive = "$stage.tar.gz"
$checksum = "$archive.sha256"
$lockPath = "$stage.packaging.lock"
foreach ($path in @($stage, $archive, $checksum, $lockPath)) {
if (Test-Path -LiteralPath $path) { throw "Output already exists; choose a fresh version/output root: $path" }
}
foreach ($directory in @('docs', 'examples', 'crates', 'scripts')) {
$sourceRoot = [IO.Path]::GetFullPath((Join-Path $repository $directory)) + [IO.Path]::DirectorySeparatorChar
if (($stage + [IO.Path]::DirectorySeparatorChar).StartsWith($sourceRoot, [StringComparison]::OrdinalIgnoreCase)) { throw 'Output must not be inside a packaged source directory.' }
}
[void][IO.Directory]::CreateDirectory($output)
$lock = [IO.File]::Open($lockPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try {
[void][IO.Directory]::CreateDirectory($stage)
$inputHashes = Copy-PackageInputs $stage $inputs $inspectedHashes
Write-PackageNotices $stage $notices
if (-not $ServerNoticesOnly) {
$metadata = [ordered]@{
version = $Version; target = $Target
acceptance = 'Packaging integrity only; current-tree native Linux acceptance required.'
build = 'Prebuilt inputs; no build profile, source identity or compiler inferred.'
build_evidence = $evidence; imports = $imports; input_sha256 = $inputHashes
runtime = 'Ubuntu 24.04 x86-64 is the validation baseline. Direct ELF dependencies only are inspected; graphics/window/portal dynamic loads must be verified on the actual runtime.'
}
[IO.File]::WriteAllText((Join-Path $stage 'package.json'), ($metadata | ConvertTo-Json -Depth 14) + "`n", $encoding)
[IO.File]::WriteAllText((Join-Path $stage 'START-HERE.txt'), "Arcadia Studio portable Linux bundle`nRun ./arcadia-studio. Keep examples/release1 beside the executable.`nRead README.md and docs/linux-packaging.md. The optional server is ./arcadia-server.`nSource checkout required for Cargo/Docker instructions. Packaging is not runtime acceptance.`n", $encoding)
$documentCheck = Invoke-PackageHelper $Python @('check-docs', '--stage', $stage)
[IO.File]::WriteAllText((Join-Path $stage 'documentation-check.json'), ($documentCheck | ConvertTo-Json) + "`n", $encoding)
}
Write-PackageChecksums $stage
if ($ServerNoticesOnly) {
[pscustomobject]@{ Directory = $stage; Target = $Target; Files = @(Get-ChildItem -LiteralPath $stage -Recurse -File).Count; Scope = 'Server-only notices; no application binary or runtime claim.' }
} else {
$result = Invoke-PackageHelper $Python @('archive', '--stage', $stage, '--archive', $archive, '--name', $packageName)
[IO.File]::WriteAllText($checksum, "$($result.sha256) $packageName.tar.gz`n", $encoding)
[pscustomobject]@{ Directory = $stage; Archive = $archive; SHA256 = $result.sha256; Files = $result.files; NativeAcceptance = 'Pending' }
}
} finally {
$lock.Dispose()
# Claims and partial outputs intentionally remain. Never overwrite a failed attempt.
}