185 lines
5.9 KiB
PowerShell
185 lines
5.9 KiB
PowerShell
param(
|
|
[string]$ZipPath,
|
|
[string]$Target = "ubuntu@82.156.24.101",
|
|
[string]$RemoteRoot = "/opt/kdl-olp-demo/8095",
|
|
[string]$BaseUrl = "https://82.156.24.101:8095",
|
|
[switch]$Sudo,
|
|
[switch]$NoSudo,
|
|
[switch]$SkipSmoke
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..\..")
|
|
$DeployRoot = Join-Path $RepoRoot "kdl-wasm\web\test-results\deploy"
|
|
|
|
if ([string]::IsNullOrWhiteSpace($ZipPath)) {
|
|
$ZipPath = Get-ChildItem -LiteralPath $DeployRoot -Filter "kdl-olp-demo-*.zip" |
|
|
Sort-Object LastWriteTime -Descending |
|
|
Select-Object -First 1 -ExpandProperty FullName
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($ZipPath) -or -not (Test-Path -LiteralPath $ZipPath)) {
|
|
throw "Demo zip not found. Run: npm run demo:build"
|
|
}
|
|
|
|
$ZipPath = (Resolve-Path -LiteralPath $ZipPath).Path
|
|
$ZipName = Split-Path -Leaf $ZipPath
|
|
if ($ZipName -notmatch '^kdl-olp-demo-(.+)\.zip$') {
|
|
throw "Zip name must match kdl-olp-demo-<release_id>.zip: $ZipName"
|
|
}
|
|
$ReleaseId = $Matches[1]
|
|
$RemoteZip = "/tmp/$ZipName"
|
|
$RemoteRelease = "$RemoteRoot/releases/$ReleaseId"
|
|
|
|
function Invoke-Remote {
|
|
param([string]$Command)
|
|
ssh -o StrictHostKeyChecking=accept-new $Target $Command
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Remote command failed: $Command"
|
|
}
|
|
}
|
|
|
|
function Remote-Cmd {
|
|
param([string]$Command)
|
|
if ($script:UseSudo) {
|
|
return "sudo sh -lc " + (Quote-Sh $Command)
|
|
}
|
|
return "sh -lc " + (Quote-Sh $Command)
|
|
}
|
|
|
|
function Quote-Sh {
|
|
param([string]$Value)
|
|
return "'" + ($Value -replace "'", "'\''") + "'"
|
|
}
|
|
|
|
function Get-RemoteParent {
|
|
param([string]$Path)
|
|
$Normalized = $Path.TrimEnd("/")
|
|
$Index = $Normalized.LastIndexOf("/")
|
|
if ($Index -le 0) {
|
|
return "/"
|
|
}
|
|
return $Normalized.Substring(0, $Index)
|
|
}
|
|
|
|
$RemoteParent = Get-RemoteParent $RemoteRoot
|
|
|
|
Write-Host "Deploying $ZipName to ${Target}:$RemoteRoot"
|
|
|
|
scp -o StrictHostKeyChecking=accept-new $ZipPath "${Target}:$RemoteZip"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "scp upload failed"
|
|
}
|
|
|
|
$script:UseSudo = $false
|
|
if ($Sudo) {
|
|
$script:UseSudo = $true
|
|
} elseif (-not $NoSudo) {
|
|
ssh -o StrictHostKeyChecking=accept-new $Target "test -w $(Quote-Sh $RemoteParent)"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
ssh -o StrictHostKeyChecking=accept-new $Target "sudo -n true"
|
|
if ($LASTEXITCODE -eq 0) {
|
|
$script:UseSudo = $true
|
|
} else {
|
|
throw "Remote root is not writable and passwordless sudo is unavailable. Re-run with a writable -RemoteRoot or configure sudo."
|
|
}
|
|
}
|
|
}
|
|
|
|
$prepare = @(
|
|
"set -eu"
|
|
"mkdir -p $(Quote-Sh "$RemoteRoot/releases")"
|
|
"rm -rf $(Quote-Sh $RemoteRelease)"
|
|
"mkdir -p $(Quote-Sh $RemoteRelease)"
|
|
"unzip -q -o $(Quote-Sh $RemoteZip) -d $(Quote-Sh $RemoteRelease)"
|
|
"test -f $(Quote-Sh "$RemoteRelease/index.html")"
|
|
"test -f $(Quote-Sh "$RemoteRelease/demo-manifest.json")"
|
|
"test -f $(Quote-Sh "$RemoteRelease/app/virtual-controller.html")"
|
|
"if [ -L $(Quote-Sh "$RemoteRoot/current") ] || [ -e $(Quote-Sh "$RemoteRoot/current") ]; then rm -f $(Quote-Sh "$RemoteRoot/previous"); ln -sfn `"`$(readlink -f $(Quote-Sh "$RemoteRoot/current"))`" $(Quote-Sh "$RemoteRoot/previous"); fi"
|
|
"ln -sfn $(Quote-Sh "$RemoteRelease") $(Quote-Sh "$RemoteRoot/current")"
|
|
"rm -f $(Quote-Sh $RemoteZip)"
|
|
) -join "; "
|
|
|
|
Invoke-Remote (Remote-Cmd $prepare)
|
|
|
|
$restart = "if command -v systemctl >/dev/null 2>&1 && systemctl list-unit-files kdl-site-8095.service >/dev/null 2>&1; then systemctl restart kdl-site-8095; fi"
|
|
Invoke-Remote (Remote-Cmd $restart)
|
|
|
|
$smoke = @{
|
|
release_id = $ReleaseId
|
|
zip = $ZipPath
|
|
target = $Target
|
|
remote_root = $RemoteRoot
|
|
remote_release = $RemoteRelease
|
|
base_url = $BaseUrl
|
|
deployed_at = (Get-Date).ToUniversalTime().ToString("o")
|
|
urls = @()
|
|
}
|
|
|
|
if (-not $SkipSmoke) {
|
|
$nodeSmoke = @"
|
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
const baseUrl = "$BaseUrl";
|
|
const get = async (path) => {
|
|
const response = await fetch(baseUrl + path);
|
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
if (response.status !== 200) {
|
|
throw new Error(path + " returned " + response.status);
|
|
}
|
|
return {
|
|
path,
|
|
status: response.status,
|
|
bytes: buffer.length,
|
|
text: buffer.toString("utf8")
|
|
};
|
|
};
|
|
const manifestResponse = await get("/demo-manifest.json");
|
|
const manifest = JSON.parse(manifestResponse.text);
|
|
const jobId = manifest.job_id;
|
|
const paths = [
|
|
"/",
|
|
"/demo-manifest.json",
|
|
"/spec-programs/manifest.json",
|
|
"/app/virtual-controller.html",
|
|
"/test-results/abb120-spec/" + jobId + "/report.json",
|
|
"/test-results/abb120-spec/" + jobId + "/report.html",
|
|
"/test-results/virtual-controller/virtual-controller-desktop.png",
|
|
"/test-results/virtual-controller/virtual-controller-mobile.png"
|
|
];
|
|
const urls = [];
|
|
for (const path of paths) {
|
|
const result = path === "/demo-manifest.json" ? manifestResponse : await get(path);
|
|
urls.push({ url: baseUrl + path, status: result.status, bytes: result.bytes });
|
|
}
|
|
const reportResponse = await get("/test-results/abb120-spec/" + jobId + "/report.json");
|
|
const report = JSON.parse(reportResponse.text);
|
|
if (Number(manifest.program_count) !== 19) {
|
|
throw new Error("Expected program_count=19, got " + manifest.program_count);
|
|
}
|
|
if (Number(report.summary.fail) !== 0) {
|
|
throw new Error("Expected summary.fail=0, got " + report.summary.fail);
|
|
}
|
|
console.log(JSON.stringify({
|
|
job_id: jobId,
|
|
program_count: Number(manifest.program_count),
|
|
summary_fail: Number(report.summary.fail),
|
|
urls
|
|
}));
|
|
"@
|
|
$nodeOutput = $nodeSmoke | node --input-type=module
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Smoke check failed"
|
|
}
|
|
$nodeSmokeResult = $nodeOutput | Select-Object -Last 1 | ConvertFrom-Json
|
|
$smoke.job_id = $nodeSmokeResult.job_id
|
|
$smoke.program_count = [int]$nodeSmokeResult.program_count
|
|
$smoke.summary_fail = [int]$nodeSmokeResult.summary_fail
|
|
$smoke.urls = @($nodeSmokeResult.urls)
|
|
}
|
|
|
|
$SmokePath = Join-Path $DeployRoot "kdl-olp-demo-$ReleaseId.deploy.json"
|
|
$smoke | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $SmokePath -Encoding UTF8
|
|
$smoke | ConvertTo-Json -Depth 8
|