#!/usr/bin/env node const assert = require("assert"); const cp = require("child_process"); const net = require("net"); const path = require("path"); const repo = path.resolve(__dirname, ".."); const project = path.join(repo, "examples/launch-build-demo"); function waitForJsonLine(child) { return new Promise((resolve, reject) => { let buffer = ""; child.stdout.on("data", (chunk) => { buffer += chunk.toString(); const newline = buffer.indexOf("\n"); if (newline < 0) return; try { resolve(JSON.parse(buffer.slice(0, newline).trim())); } catch (error) { reject(error); } }); child.once("exit", (code) => { reject(new Error(`process exited before JSON line with code ${code}`)); }); }); } function send(addr, message) { return new Promise((resolve, reject) => { const socket = net.connect(addr.port, addr.host, () => { socket.write(`${JSON.stringify(message)}\n`); }); let buffer = ""; socket.on("data", (chunk) => { buffer += chunk.toString(); const newline = buffer.indexOf("\n"); if (newline < 0) return; socket.end(); try { resolve(JSON.parse(buffer.slice(0, newline))); } catch (error) { reject(error); } }); socket.on("error", reject); }); } function runNode(addr) { return new Promise((resolve, reject) => { const child = cp.spawn( "cargo", [ "run", "-q", "-p", "disasmer-node", "--bin", "disasmer-node", "--", "--coordinator", `${addr.host}:${addr.port}`, "--tenant", "tenant", "--project-id", "project", "--node", "panel-node", "--process", "vp-panel", "--task", "compile-linux", "--project", project, "--artifact", "/vfs/artifacts/panel-output.txt" ], { cwd: repo } ); let stdout = ""; let stderr = ""; child.stdout.on("data", (chunk) => { stdout += chunk.toString(); }); child.stderr.on("data", (chunk) => { stderr += chunk.toString(); }); child.on("exit", (code) => { if (code !== 0) { reject(new Error(`node process failed with code ${code}\n${stderr}`)); return; } try { resolve(JSON.parse(stdout.trim().split("\n").at(-1))); } catch (error) { reject(new Error(`node output was not JSON: ${stdout}\n${error.stack || error.message}`)); } }); }); } function widget(panel, id) { const item = panel.widgets[id]; assert(item, `missing panel widget ${id}`); return item; } (async () => { const coordinator = cp.spawn( "cargo", [ "run", "-q", "-p", "disasmer-coordinator", "--bin", "disasmer-coordinator", "--", "--listen", "127.0.0.1:0" ], { cwd: repo } ); let coordinatorStderr = ""; coordinator.stderr.on("data", (chunk) => { coordinatorStderr += chunk.toString(); }); try { const ready = await waitForJsonLine(coordinator); const [host, portText] = ready.listen.split(":"); const addr = { host, port: Number(portText) }; assert.strictEqual((await send(addr, { type: "ping" })).type, "pong"); const report = await runNode(addr); assert.strictEqual(report.node_status, "completed"); assert.strictEqual(report.coordinator_response.type, "task_recorded"); const rendered = await send(addr, { type: "render_operator_panel", tenant: "tenant", project: "project", process: "vp-panel", actor_user: "user", max_download_bytes: 1024 * 1024, stopped: false }); assert.strictEqual(rendered.type, "operator_panel"); const panel = rendered.panel; assert.strictEqual(panel.tenant, "tenant"); assert.strictEqual(panel.project, "project"); assert.strictEqual(panel.process, "vp-panel"); assert.strictEqual(panel.program_ui_events_enabled, true); assert.deepStrictEqual(widget(panel, "process-status").kind, { Text: { value: "running" } }); assert.deepStrictEqual(widget(panel, "task-progress").kind, { Progress: { current: 1, total: 1 } }); assert.match( widget(panel, "task-summary").kind.Text.value, /compile-linux:Some\(0\):panel-node/ ); assert.match(widget(panel, "recent-logs").kind.Text.value, /stdout=\d+ stderr=\d+/); const downloadWidget = widget(panel, "download-artifact").kind; assert.deepStrictEqual(downloadWidget, { ArtifactDownload: { artifact: "panel-output.txt" } }); assert(!JSON.stringify(downloadWidget).includes("url_path")); assert(!JSON.stringify(downloadWidget).includes("scoped_token_digest")); assert.deepStrictEqual(widget(panel, "debug-process").kind, { Button: { action: "debug-process" } }); assert.deepStrictEqual(widget(panel, "cancel-process").kind, { Button: { action: "cancel-process" } }); assert.deepStrictEqual(widget(panel, "restart-selected-task").kind, { Button: { action: "restart-task" } }); assert(panel.control_plane_actions.includes("DebugProcess")); assert(panel.control_plane_actions.includes("CancelProcess")); assert( panel.control_plane_actions.some( (action) => action.RestartTask === "compile-linux" ) ); assert( panel.control_plane_actions.some( (action) => action.DownloadArtifact === "panel-output.txt" ) ); assert(!JSON.stringify(panel).includes(" action.DownloadArtifact === "panel-output.txt" ) ); const frozenEvent = await send(addr, { type: "submit_panel_event", tenant: "tenant", project: "project", process: "vp-panel", widget_id: "debug-process", kind: "ButtonClicked", max_events: 10 }); assert.strictEqual(frozenEvent.type, "error"); assert.match(frozenEvent.message, /program UI events are disabled/i); const crossTenant = await send(addr, { type: "render_operator_panel", tenant: "other", project: "project", process: "vp-panel", actor_user: "user", max_download_bytes: 1024 * 1024, stopped: false }); assert.strictEqual(crossTenant.type, "error"); assert.match(crossTenant.message, /scope|tenant|project/i); } catch (error) { if (coordinatorStderr) { error.message = `${error.message}\ncoordinator stderr:\n${coordinatorStderr}`; } throw error; } finally { coordinator.kill("SIGTERM"); } console.log("Operator panel smoke passed"); })().catch((error) => { console.error(error.stack || error.message); process.exit(1); });