Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Dashboard ambient layer, comrade presence, Mission Deck and War Room, Emberwake supply chain, spread/docs publishing, fleet policy and modules API, CI docker mining, and refreshed USB pack.
129 lines
4.6 KiB
PowerShell
129 lines
4.6 KiB
PowerShell
# CI Docker mining proof — Linux agent connects and reports hashrate > 0 (Windows + Docker Desktop).
|
|
param(
|
|
[string]$BaseUrl = "http://127.0.0.1:18989",
|
|
[string]$Username = "",
|
|
[string]$Password = "",
|
|
[string]$ExpectedWorker = "docker-e2e-linux",
|
|
[int]$WaitSeconds = 180,
|
|
[int]$PollIntervalSec = 5,
|
|
[switch]$SkipTeardown
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$Root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
|
$ComposeFile = Join-Path $Root "docker\docker-compose.yml"
|
|
|
|
if (-not $Username) { $Username = if ($env:AETHERFORGE_E2E_USER) { $env:AETHERFORGE_E2E_USER } else { "testuser" } }
|
|
if (-not $Password) { $Password = if ($env:AETHERFORGE_E2E_PASS) { $env:AETHERFORGE_E2E_PASS } else { "testpass" } }
|
|
|
|
$cred = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${Username}:${Password}"))
|
|
$authHeaders = @{ Authorization = "Basic $cred" }
|
|
|
|
function Write-Log([string]$Message) {
|
|
Write-Host "[ci-docker-mining] $Message"
|
|
}
|
|
|
|
function Ensure-Docker {
|
|
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
|
|
throw "docker not found — install Docker Desktop with compose v2"
|
|
}
|
|
docker compose version 2>$null | Out-Null
|
|
if ($LASTEXITCODE -ne 0) { throw "docker compose plugin not available" }
|
|
}
|
|
|
|
function Invoke-Teardown {
|
|
if ($SkipTeardown) { return }
|
|
Write-Log "Tearing down compose…"
|
|
Push-Location $Root
|
|
try {
|
|
docker compose -f $ComposeFile down --rmi local -v --remove-orphans 2>$null
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
}
|
|
|
|
function Wait-ForHealth {
|
|
param([datetime]$Deadline)
|
|
while ((Get-Date) -lt $Deadline) {
|
|
try {
|
|
$r = Invoke-RestMethod "$BaseUrl/api/v1/health" -TimeoutSec 5
|
|
if ($r.status -eq "ok") {
|
|
Write-Log "Server healthy at $BaseUrl/api/v1/health"
|
|
return
|
|
}
|
|
} catch {}
|
|
Start-Sleep -Seconds $PollIntervalSec
|
|
}
|
|
throw "server not healthy within ${WaitSeconds}s ($BaseUrl/api/v1/health)"
|
|
}
|
|
|
|
function Assert-Mining {
|
|
param([datetime]$Deadline)
|
|
while ((Get-Date) -lt $Deadline) {
|
|
try {
|
|
$agents = Invoke-RestMethod "$BaseUrl/api/v1/agents" -Headers $authHeaders -TimeoutSec 10
|
|
$stats = Invoke-RestMethod "$BaseUrl/api/v1/dashboard/stats" -Headers $authHeaders -TimeoutSec 10
|
|
|
|
$online = @($agents | Where-Object {
|
|
$_.status -eq "online" -and (
|
|
[double]$_.hashrate_15s -gt 0 -or
|
|
[double]$_.hashrate_1m -gt 0 -or
|
|
[double]$_.hashrate_15m -gt 0
|
|
)
|
|
})
|
|
|
|
$named = @($online | Where-Object { $_.worker_name -eq $ExpectedWorker -or $_.name -eq $ExpectedWorker })
|
|
$hit = if ($named.Count -gt 0) { $named[0] } elseif ($online.Count -gt 0) { $online[0] } else { $null }
|
|
|
|
if ($hit) {
|
|
$hr = [Math]::Max([double]$hit.hashrate_15s, [Math]::Max([double]$hit.hashrate_1m, [double]$hit.hashrate_15m))
|
|
Write-Log "PASS: online agent $($hit.id) ($($hit.worker_name)) hashrate=$([math]::Round($hr, 2)) H/s"
|
|
Write-Log "Fleet stats: online=$($stats.online_agents) total_hr=$([math]::Round([double]$stats.total_hashrate, 2))"
|
|
return
|
|
}
|
|
|
|
Write-Log "Waiting… online_agents=$($stats.online_agents) total_hashrate=$($stats.total_hashrate) (need online + hashrate>0)"
|
|
} catch {
|
|
Write-Log "Waiting… agents/stats API not ready ($($_.Exception.Message))"
|
|
}
|
|
Start-Sleep -Seconds $PollIntervalSec
|
|
}
|
|
|
|
throw "no online agent with hashrate>0 within ${WaitSeconds}s (expected worker: $ExpectedWorker)"
|
|
}
|
|
|
|
function Show-FailureLogs {
|
|
Push-Location $Root
|
|
try {
|
|
Write-Log "Recent server logs:"
|
|
docker compose -f $ComposeFile logs --tail=80 server 2>$null
|
|
Write-Log "Recent agent logs:"
|
|
docker compose -f $ComposeFile logs --tail=80 agent 2>$null
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
}
|
|
|
|
Ensure-Docker
|
|
|
|
try {
|
|
Push-Location $Root
|
|
Write-Log "Starting docker compose (build may take several minutes)…"
|
|
docker compose -f $ComposeFile up --build -d
|
|
if ($LASTEXITCODE -ne 0) { throw "docker compose up failed (exit $LASTEXITCODE)" }
|
|
Pop-Location
|
|
|
|
$deadline = (Get-Date).AddSeconds($WaitSeconds)
|
|
Write-Log "Waiting up to ${WaitSeconds}s for health + mining proof…"
|
|
Wait-ForHealth -Deadline $deadline
|
|
Assert-Mining -Deadline $deadline
|
|
Write-Log "Docker mining proof succeeded"
|
|
exit 0
|
|
} catch {
|
|
Write-Host "[ci-docker-mining] ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
|
Show-FailureLogs
|
|
exit 1
|
|
} finally {
|
|
Invoke-Teardown
|
|
}
|