Files
archvillainette 93433e3f53
test-image / build-image (push) Successful in 44s
test / test (push) Successful in 1m20s
build-binaries / build-binaries (push) Successful in 2m0s
build-image / publish (push) Successful in 12s
Cross-Platform Crucible (#2)
Crucible groundwork for cross-platform compatibility.

Reviewed-on: #2
Reviewed-by: xtul <mpiasecki720@protonmail.com>
Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
2026-06-16 13:52:19 +00:00

90 lines
3.7 KiB
PowerShell

#!/usr/bin/env pwsh
# crucible - bootstrap wrapper (PowerShell). Prefers a crucible already on PATH;
# otherwise downloads the latest released binary from Gitea into a per-version
# cache and execs it.
#
# CANONICAL SOURCE: sow-tools/wrappers/crucible.ps1. Do not hand-edit copies in
# consumer repos - kept in sync by sow-tools CI (see drift-check).
#
# Env: CRUCIBLE_HOME, CRUCIBLE_TOKEN, CRUCIBLE_GITEA, CRUCIBLE_REPO.
$ErrorActionPreference = 'Stop'
# 0. Prefer an existing crucible.
$existing = Get-Command crucible -ErrorAction SilentlyContinue
if ($existing) { & $existing.Source @args; exit $LASTEXITCODE }
$gitea = if ($env:CRUCIBLE_GITEA) { $env:CRUCIBLE_GITEA } else { 'https://git.westgate.pw' }
$repo = if ($env:CRUCIBLE_REPO) { $env:CRUCIBLE_REPO } else { 'ShadowsOverWestgate/sow-tools' }
# 1. OS/arch -> asset name (.exe on Windows).
$os = if ($IsWindows) { 'windows' } elseif ($IsMacOS) { 'darwin' } else { 'linux' }
$arch = switch ($env:PROCESSOR_ARCHITECTURE) {
'AMD64' { 'amd64' } 'ARM64' { 'arm64' } default { 'amd64' }
}
$ext = if ($os -eq 'windows') { '.exe' } else { '' }
$asset = "crucible-$os-$arch$ext"
# 2. Auth header (anon first, token fallback).
$token = $env:CRUCIBLE_TOKEN
$tokenFile = Join-Path $HOME '.config/crucible/token'
if (-not $token -and (Test-Path $tokenFile)) { $token = (Get-Content $tokenFile -Raw).Trim() }
function Invoke-Fetch($url, $outFile) {
try { Invoke-WebRequest -Uri $url -OutFile $outFile -UseBasicParsing; return $true } catch {}
if ($token) {
Invoke-WebRequest -Uri $url -OutFile $outFile -UseBasicParsing -Headers @{ Authorization = "token $token" }
return $true
}
return $false
}
# 3. Resolve latest tag.
$tag = $null
try {
$hdr = if ($token) { @{ Authorization = "token $token" } } else { @{} }
$rel = Invoke-RestMethod -Uri "$gitea/api/v1/repos/$repo/releases/latest" -Headers $hdr
$tag = $rel.tag_name
} catch {}
# 4. Cache dir.
$cacheRoot = if ($env:CRUCIBLE_HOME) { $env:CRUCIBLE_HOME }
elseif ($env:LOCALAPPDATA) { Join-Path $env:LOCALAPPDATA 'crucible' }
else { Join-Path $HOME '.cache/crucible' }
# 5. Offline fallback.
if (-not $tag) {
if (Test-Path $cacheRoot) {
$cached = Get-ChildItem $cacheRoot -Directory | Sort-Object Name | Select-Object -Last 1
$cachedBin = if ($cached) { Join-Path $cached.FullName "crucible$ext" } else { $null }
if ($cachedBin -and (Test-Path $cachedBin)) {
Write-Error "crucible: offline - using cached $($cached.Name)" -ErrorAction Continue
& $cachedBin @args; exit $LASTEXITCODE
}
}
Write-Error "crucible: cannot reach $gitea and no cached binary found (set CRUCIBLE_TOKEN if private)."
exit 1
}
$destDir = Join-Path $cacheRoot $tag
$bin = Join-Path $destDir "crucible$ext"
# 6. Download + verify on cache miss.
if (-not (Test-Path $bin)) {
New-Item -ItemType Directory -Force -Path $destDir | Out-Null
$base = "$gitea/$repo/releases/download/$tag"
$tmp = New-Item -ItemType Directory -Path (Join-Path ([System.IO.Path]::GetTempPath()) ([guid]::NewGuid()))
$tmpBin = Join-Path $tmp "crucible$ext"
Write-Host "crucible: fetching $asset $tag..."
if (-not (Invoke-Fetch "$base/$asset" $tmpBin)) { Write-Error "crucible: download failed for $asset"; exit 1 }
$sums = Join-Path $tmp 'SHA256SUMS'
if (Invoke-Fetch "$base/SHA256SUMS" $sums) {
$want = (Select-String -Path $sums -Pattern ([regex]::Escape($asset) + '$') | Select-Object -First 1).Line -split '\s+' | Select-Object -First 1
$got = (Get-FileHash $tmpBin -Algorithm SHA256).Hash.ToLower()
if ($want -and ($want.ToLower() -ne $got)) { Write-Error "crucible: checksum mismatch for $asset"; exit 1 }
}
Move-Item -Force $tmpBin $bin
Remove-Item -Recurse -Force $tmp
}
& $bin @args
exit $LASTEXITCODE