CultLib split packages/cultcache-py into cultcache-py, cultnet-py and cultmesh-py. Module names did not change, so archiving only the first still succeeds and produces a tarball missing two thirds of the library -- a failure that surfaces later as an ImportError with nothing pointing back to this line. The two sibling deploy scripts ship cultnet-ts and cultcache-ts and are unaffected by a Python split. Not exercised: repixelizer.service is inactive, so this is a trap defused rather than a break repaired. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
161 lines
6.9 KiB
PowerShell
161 lines
6.9 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
|
|
}
|
|
# All three Python packages. CultLib split packages/cultcache-py into
|
|
# cultcache-py / cultnet-py / cultmesh-py; module names did not change, so
|
|
# archiving only the first still succeeds and ships an incomplete library
|
|
# that fails later as an ImportError, far from this line.
|
|
git -C $CultLibRoot archive --format=tar --output=$cultLibTarPath $cultLibSourceRef packages/cultcache-py packages/cultnet-py packages/cultmesh-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"
|