Add ABB120 demo suite and docs
This commit is contained in:
184
kdl-wasm/web/scripts/deploy-demo-package.ps1
Normal file
184
kdl-wasm/web/scripts/deploy-demo-package.ps1
Normal file
@@ -0,0 +1,184 @@
|
||||
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
|
||||
Reference in New Issue
Block a user