Odin/scripts/deploy-yggdrasil-repixelizer.ps1
Meta Vens 515a864ef0 Rebase Idunn actuator scripts off the projects root
The previous commit fixed the target catalog and the operator alarm, but the
actuators the catalog invokes carried the same E: paths. Idunn would have
resolved every target and then failed on the first restart or deploy it ran,
for exactly the reason the alarm failed.

Rebased 41 references across 27 scripts:

- .cmd bodies invoke their sibling .ps1 through %~dp0 instead of an absolute
  drive path, and restart-weksa.cmd reaches its sibling repo the same way.
- .ps1 parameter defaults and assignments derive from $PSScriptRoot: one level
  up for paths inside Odin, two for sibling repos under the projects root.

Left deliberately alone: $RemoteViliRoot and $StateRoot in restart-vili.ps1.
Both are consumed inside the EncodedCommand block that restart-vili ssh's to
raven, so they describe raven's filesystem, not starfire's. Whether raven also
moved off E: is an operator question, not something to infer from here.

Verified: all 46 scripts under scripts/ parse clean, and the derivation
resolves to F:\Projects\Odin and F:\Projects on this host.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 01:05:40 +02:00

157 lines
6.6 KiB
PowerShell

param(
[string] $SshTarget = "yggdrasil",
[string] $RepoRoot = (Join-Path (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) "repixelizer"),
[string] $CultLibRoot = (Join-Path (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) "CultLib"),
[string] $AppUser = "repixelizer",
[string] $RemoteAppHome = "/srv/repixelizer",
[string] $RemoteTarballName = "repixelizer-source.tar",
[string] $RemoteCultLibTarballName = "repixelizer-cultlib.tar",
[string] $DeployScript = (Join-Path (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) "gamecult-ops\scripts\deploy-repixelizer-gui.sh"),
[string] $CheckScript = (Join-Path (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) "gamecult-ops\scripts\check-repixelizer-gui.sh"),
[string] $UpstreamRemote = "origin",
[string] $UpstreamBranch = "main",
[string] $CultLibUpstreamRemote = "origin",
[string] $CultLibUpstreamBranch = "main"
)
$ErrorActionPreference = "Stop"
if ($env:IDUNN_ACTUATOR -ne "1" -or $env:IDUNN_COMMAND_AUTHORITY -ne "idunn-daemon") {
throw "This deployment script is an Idunn actuator. Agents must configure Idunn release targets and let Idunn run deployment; do not invoke deploy scripts manually."
}
foreach ($path in @($RepoRoot, $CultLibRoot, $DeployScript, $CheckScript)) {
if (-not (Test-Path -LiteralPath $path)) {
throw "Required path not found: $path"
}
}
$sourceRef = "$UpstreamRemote/$UpstreamBranch"
$cultLibSourceRef = "$CultLibUpstreamRemote/$CultLibUpstreamBranch"
git -C $RepoRoot fetch --prune $UpstreamRemote $UpstreamBranch
if ($LASTEXITCODE -ne 0) { throw "git fetch failed for $RepoRoot $sourceRef" }
git -C $CultLibRoot fetch --prune $CultLibUpstreamRemote $CultLibUpstreamBranch
if ($LASTEXITCODE -ne 0) { throw "git fetch failed for $CultLibRoot $cultLibSourceRef" }
$repixelizerCommit = (git -C $RepoRoot rev-parse $sourceRef).Trim()
if ([string]::IsNullOrWhiteSpace($repixelizerCommit)) {
throw "Could not determine Repixelizer git revision."
}
$cultLibCommit = (git -C $CultLibRoot rev-parse $cultLibSourceRef).Trim()
if ([string]::IsNullOrWhiteSpace($cultLibCommit)) {
throw "Could not determine CultLib git revision."
}
$scratch = Join-Path (Join-Path (Split-Path -Parent $PSScriptRoot) "scratch\idunn-deploy") "yggdrasil-repixelizer"
$sourceTarPath = Join-Path $scratch $RemoteTarballName
$cultLibTarPath = Join-Path $scratch $RemoteCultLibTarballName
$manifestPath = Join-Path $scratch "deployment-manifest.txt"
New-Item -ItemType Directory -Force -Path $scratch | Out-Null
git -C $RepoRoot archive --format=tar --output=$sourceTarPath $sourceRef
if ($LASTEXITCODE -ne 0) {
throw "git archive failed for $RepoRoot $sourceRef"
}
if (Test-Path -LiteralPath $cultLibTarPath) {
Remove-Item -LiteralPath $cultLibTarPath -Force
}
git -C $CultLibRoot archive --format=tar --output=$cultLibTarPath $cultLibSourceRef packages/cultcache-py
if ($LASTEXITCODE -ne 0) {
throw "CultLib tar build failed for $CultLibRoot $cultLibSourceRef"
}
$sourceHash = (Get-FileHash $sourceTarPath -Algorithm SHA256).Hash.ToLowerInvariant()
$cultLibHash = (Get-FileHash $cultLibTarPath -Algorithm SHA256).Hash.ToLowerInvariant()
$deployedAt = [DateTimeOffset]::UtcNow.ToString("O")
@(
"schema=gamecult.idunn.deployment_manifest.v1"
"appId=yggdrasil-repixelizer"
"repoRoot=$RepoRoot"
"upstreamRemote=$UpstreamRemote"
"upstreamBranch=$UpstreamBranch"
"sourceRef=$sourceRef"
"gitCommit=$repixelizerCommit"
"artifact=$RemoteTarballName"
"sha256=$sourceHash"
"cultLibRepoRoot=$CultLibRoot"
"cultLibUpstreamRemote=$CultLibUpstreamRemote"
"cultLibUpstreamBranch=$CultLibUpstreamBranch"
"cultLibSourceRef=$cultLibSourceRef"
"cultLibGitCommit=$cultLibCommit"
"cultLibArtifact=$RemoteCultLibTarballName"
"cultLibSha256=$cultLibHash"
"deployedAtUtc=$deployedAt"
) | Set-Content -Encoding ASCII -LiteralPath $manifestPath
$remoteDeploy = "/home/gamecultadmin/$([IO.Path]::GetFileName($DeployScript))"
$remoteCheck = "/home/gamecultadmin/$([IO.Path]::GetFileName($CheckScript))"
$remoteSourceTarball = "/home/gamecultadmin/$RemoteTarballName"
$remoteCultLibTarball = "/home/gamecultadmin/$RemoteCultLibTarballName"
$remoteManifest = "/home/gamecultadmin/yggdrasil-repixelizer-deployment-manifest.txt"
$remoteRunner = "/home/gamecultadmin/run-yggdrasil-repixelizer-deploy.sh"
$targetSourceTarball = "$RemoteAppHome/$RemoteTarballName"
$targetCultLibTarball = "$RemoteAppHome/$RemoteCultLibTarballName"
$targetManifest = "$RemoteAppHome/deployment-manifest.txt"
$sftpBatchPath = Join-Path $scratch "yggdrasil-repixelizer-upload.sftp"
$runnerPath = Join-Path $scratch "run-yggdrasil-repixelizer-deploy.sh"
$runnerScript = @"
#!/usr/bin/env bash
set -euo pipefail
sudo -n install -d -o '$AppUser' -g '$AppUser' '$RemoteAppHome'
sudo -n install -o '$AppUser' -g '$AppUser' -m 600 '$remoteSourceTarball' '$targetSourceTarball'
sudo -n install -o '$AppUser' -g '$AppUser' -m 600 '$remoteCultLibTarball' '$targetCultLibTarball'
sudo -n install -m 644 '$remoteManifest' '$targetManifest'
chmod +x '$remoteDeploy' '$remoteCheck'
sudo -n env GAMECULT_IDUNN_REMOTE_ACTUATOR=1 IDUNN_COMMAND_AUTHORITY=idunn-daemon bash '$remoteDeploy'
check_ok=0
for i in `$(seq 1 30); do
if sudo -n bash '$remoteCheck'; then
check_ok=1
break
fi
sleep 2
done
if [ "`$check_ok" -ne 1 ]; then
sudo -n bash '$remoteCheck'
exit 1
fi
"@.Replace("`r`n", "`n")
[System.IO.File]::WriteAllText($runnerPath, $runnerScript, [System.Text.Encoding]::ASCII)
@(
"put ""$sourceTarPath"" ""$remoteSourceTarball"""
"put ""$cultLibTarPath"" ""$remoteCultLibTarball"""
"put ""$DeployScript"" ""$remoteDeploy"""
"put ""$CheckScript"" ""$remoteCheck"""
"put ""$manifestPath"" ""$remoteManifest"""
"put ""$runnerPath"" ""$remoteRunner"""
) | Set-Content -Encoding ASCII -LiteralPath $sftpBatchPath
try {
& sftp.exe -b $sftpBatchPath $SshTarget
if ($LASTEXITCODE -ne 0) {
throw "sftp upload failed for yggdrasil-repixelizer"
}
& ssh.exe -o BatchMode=yes -o ConnectTimeout=10 $SshTarget "chmod +x '$remoteRunner' && bash '$remoteRunner'"
$remoteExit = $LASTEXITCODE
& ssh.exe -o BatchMode=yes -o ConnectTimeout=10 $SshTarget "rm -f '$remoteRunner'"
if ($remoteExit -ne 0) {
throw "remote deploy/check failed for yggdrasil-repixelizer"
}
}
finally {
Remove-Item -LiteralPath $runnerPath -Force -ErrorAction SilentlyContinue
Remove-Item -LiteralPath $sftpBatchPath -Force -ErrorAction SilentlyContinue
}
Write-Host "yggdrasil-repixelizer deployed with CultLib snapshot."
Write-Host " repixelizerCommit=$repixelizerCommit"
Write-Host " cultLibCommit=$cultLibCommit"
Write-Host " artifactSha256=$sourceHash"
Write-Host " cultLibSha256=$cultLibHash"