feat: move web-probe to top-level cli (#933)
Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
@@ -172,7 +172,7 @@ export function runWebProbeSentinelCommand(spec: HwlabRuntimeLaneSpec, options:
|
||||
}
|
||||
|
||||
function runSentinelImage(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "image" }>): RenderedCliResult {
|
||||
const command = `hwlab nodes web-probe sentinel image ${options.action}`;
|
||||
const command = `web-probe sentinel image ${options.action}`;
|
||||
if (options.action === "build" && options.confirm) {
|
||||
if (!options.wait) return renderAsyncSentinelJob(state, "image", "build", options.timeoutSeconds);
|
||||
return runSentinelImageBuildConfirmed(state, options);
|
||||
@@ -192,10 +192,10 @@ function runSentinelImage(state: SentinelCicdState, options: Extract<WebProbeSen
|
||||
registry,
|
||||
blocker: null,
|
||||
next: {
|
||||
status: `bun scripts/cli.ts hwlab nodes web-probe sentinel image status --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
|
||||
dryRun: `bun scripts/cli.ts hwlab nodes web-probe sentinel image build --node ${state.spec.nodeId} --lane ${state.spec.lane} --dry-run`,
|
||||
confirm: `bun scripts/cli.ts hwlab nodes web-probe sentinel image build --node ${state.spec.nodeId} --lane ${state.spec.lane} --confirm`,
|
||||
controlPlanePlan: `bun scripts/cli.ts hwlab nodes web-probe sentinel control-plane plan --node ${state.spec.nodeId} --lane ${state.spec.lane} --dry-run`,
|
||||
status: `bun scripts/cli.ts web-probe sentinel image status --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
|
||||
dryRun: `bun scripts/cli.ts web-probe sentinel image build --node ${state.spec.nodeId} --lane ${state.spec.lane} --dry-run`,
|
||||
confirm: `bun scripts/cli.ts web-probe sentinel image build --node ${state.spec.nodeId} --lane ${state.spec.lane} --confirm`,
|
||||
controlPlanePlan: `bun scripts/cli.ts web-probe sentinel control-plane plan --node ${state.spec.nodeId} --lane ${state.spec.lane} --dry-run`,
|
||||
},
|
||||
valuesRedacted: true,
|
||||
};
|
||||
@@ -203,7 +203,7 @@ function runSentinelImage(state: SentinelCicdState, options: Extract<WebProbeSen
|
||||
}
|
||||
|
||||
function runSentinelControlPlane(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "control-plane" }>): RenderedCliResult {
|
||||
const command = `hwlab nodes web-probe sentinel control-plane ${options.action}`;
|
||||
const command = `web-probe sentinel control-plane ${options.action}`;
|
||||
const mutationAction = options.action === "apply" || options.action === "trigger-current";
|
||||
if (options.confirm && mutationAction) {
|
||||
if (!options.wait) return renderAsyncSentinelJob(state, "control-plane", options.action, options.timeoutSeconds);
|
||||
@@ -512,7 +512,7 @@ function probeImageRegistry(state: SentinelCicdState, timeoutSeconds: number): R
|
||||
}
|
||||
|
||||
function runSentinelImageBuildConfirmed(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "image" }>): RenderedCliResult {
|
||||
const command = "hwlab nodes web-probe sentinel image build";
|
||||
const command = "web-probe sentinel image build";
|
||||
const publish = runSentinelPublishJob(state, false, options.timeoutSeconds);
|
||||
const registry = probeImageRegistry(state, options.timeoutSeconds);
|
||||
const registryReady = record(registry.probe).present === true;
|
||||
@@ -531,8 +531,8 @@ function runSentinelImageBuildConfirmed(state: SentinelCicdState, options: Extra
|
||||
warnings: sentinelElapsedWarnings(record(publish).elapsedMs),
|
||||
blocker: null,
|
||||
next: {
|
||||
status: `bun scripts/cli.ts hwlab nodes web-probe sentinel image status --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
|
||||
controlPlaneTrigger: `bun scripts/cli.ts hwlab nodes web-probe sentinel control-plane trigger-current --node ${state.spec.nodeId} --lane ${state.spec.lane} --confirm`,
|
||||
status: `bun scripts/cli.ts web-probe sentinel image status --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
|
||||
controlPlaneTrigger: `bun scripts/cli.ts web-probe sentinel control-plane trigger-current --node ${state.spec.nodeId} --lane ${state.spec.lane} --confirm`,
|
||||
},
|
||||
valuesRedacted: true,
|
||||
};
|
||||
@@ -540,7 +540,7 @@ function runSentinelImageBuildConfirmed(state: SentinelCicdState, options: Extra
|
||||
}
|
||||
|
||||
function runSentinelControlPlaneConfirmed(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "control-plane" }>): RenderedCliResult {
|
||||
const command = `hwlab nodes web-probe sentinel control-plane ${options.action}`;
|
||||
const command = `web-probe sentinel control-plane ${options.action}`;
|
||||
const applyOnly = options.action === "apply";
|
||||
const publish = applyOnly ? null : runSentinelPublishJob(state, true, options.timeoutSeconds);
|
||||
const flush = !applyOnly && record(publish).ok === true
|
||||
@@ -627,10 +627,10 @@ function runSentinelControlPlaneConfirmed(state: SentinelCicdState, options: Ext
|
||||
|
||||
function renderAsyncSentinelJob(state: SentinelCicdState, domain: "image" | "control-plane", action: string, timeoutSeconds: number): RenderedCliResult {
|
||||
const args = domain === "image"
|
||||
? ["hwlab", "nodes", "web-probe", "sentinel", "image", action, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)]
|
||||
: ["hwlab", "nodes", "web-probe", "sentinel", "control-plane", action, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)];
|
||||
? ["web-probe", "sentinel", "image", action, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)]
|
||||
: ["web-probe", "sentinel", "control-plane", action, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)];
|
||||
const job = startJob(`hwlab_nodes_${state.spec.lane}_web_probe_sentinel_${domain}_${action}`, ["bun", "scripts/cli.ts", ...args], `Run HWLAB ${state.spec.lane} web-probe sentinel ${domain} ${action} for node ${state.spec.nodeId}`);
|
||||
const command = `hwlab nodes web-probe sentinel ${domain} ${action}`;
|
||||
const command = `web-probe sentinel ${domain} ${action}`;
|
||||
const result = {
|
||||
ok: true,
|
||||
command,
|
||||
@@ -1121,17 +1121,17 @@ function controlPlaneNext(state: SentinelCicdState, action: WebProbeSentinelCont
|
||||
const node = state.spec.nodeId;
|
||||
const lane = state.spec.lane;
|
||||
return {
|
||||
plan: `bun scripts/cli.ts hwlab nodes web-probe sentinel control-plane plan --node ${node} --lane ${lane} --dry-run`,
|
||||
status: `bun scripts/cli.ts hwlab nodes web-probe sentinel control-plane status --node ${node} --lane ${lane}`,
|
||||
image: `bun scripts/cli.ts hwlab nodes web-probe sentinel image status --node ${node} --lane ${lane}`,
|
||||
triggerCurrent: `bun scripts/cli.ts hwlab nodes web-probe sentinel control-plane trigger-current --node ${node} --lane ${lane} --dry-run`,
|
||||
plan: `bun scripts/cli.ts web-probe sentinel control-plane plan --node ${node} --lane ${lane} --dry-run`,
|
||||
status: `bun scripts/cli.ts web-probe sentinel control-plane status --node ${node} --lane ${lane}`,
|
||||
image: `bun scripts/cli.ts web-probe sentinel image status --node ${node} --lane ${lane}`,
|
||||
triggerCurrent: `bun scripts/cli.ts web-probe sentinel control-plane trigger-current --node ${node} --lane ${lane} --dry-run`,
|
||||
issue: "https://github.com/pikasTech/unidesk/issues/889",
|
||||
currentAction: action,
|
||||
};
|
||||
}
|
||||
|
||||
function runSentinelMaintenance(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "maintenance" }>): RenderedCliResult {
|
||||
const command = `hwlab nodes web-probe sentinel maintenance ${options.action}`;
|
||||
const command = `web-probe sentinel maintenance ${options.action}`;
|
||||
const serviceHealth = callSentinelService(state, "GET", "/api/health", null, options.timeoutSeconds);
|
||||
if (options.action === "status") {
|
||||
const maintenance = callSentinelService(state, "GET", "/api/maintenance", null, options.timeoutSeconds);
|
||||
@@ -1206,7 +1206,7 @@ function runSentinelMaintenance(state: SentinelCicdState, options: Extract<WebPr
|
||||
}
|
||||
|
||||
function runSentinelValidate(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "validate" }>): RenderedCliResult {
|
||||
const command = "hwlab nodes web-probe sentinel validate";
|
||||
const command = "web-probe sentinel validate";
|
||||
const initialHealth = callSentinelService(state, "GET", "/api/health", null, options.timeoutSeconds);
|
||||
let quickVerify: Record<string, unknown> | null = null;
|
||||
if (options.quickVerify) {
|
||||
@@ -1271,7 +1271,7 @@ function runSentinelValidate(state: SentinelCicdState, options: Extract<WebProbe
|
||||
}
|
||||
|
||||
function runSentinelReport(state: SentinelCicdState, options: Extract<WebProbeSentinelOptions, { kind: "report" }>): RenderedCliResult {
|
||||
const command = `hwlab nodes web-probe sentinel report ${options.latest ? "--latest " : ""}--view ${options.view}`;
|
||||
const command = `web-probe sentinel report ${options.latest ? "--latest " : ""}--view ${options.view}`;
|
||||
const query = new URLSearchParams({ view: options.view });
|
||||
if (options.runId !== null) query.set("run", options.runId);
|
||||
if (options.traceId !== null) query.set("traceId", options.traceId);
|
||||
@@ -1284,12 +1284,12 @@ function runSentinelReport(state: SentinelCicdState, options: Extract<WebProbeSe
|
||||
}
|
||||
|
||||
function renderAsyncP5Job(state: SentinelCicdState, subcommand: readonly string[], timeoutSeconds: number, releaseId: string | null, reason: string | null, quickVerify: boolean): RenderedCliResult {
|
||||
const args = ["hwlab", "nodes", "web-probe", "sentinel", ...subcommand, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)];
|
||||
const args = ["web-probe", "sentinel", ...subcommand, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--confirm", "--wait", "--timeout-seconds", String(timeoutSeconds)];
|
||||
if (releaseId !== null) args.push("--release-id", releaseId);
|
||||
if (reason !== null) args.push("--reason", reason);
|
||||
if (quickVerify) args.push("--quick-verify");
|
||||
const job = startJob(`hwlab_nodes_${state.spec.lane}_web_probe_sentinel_${subcommand.join("_")}`, ["bun", "scripts/cli.ts", ...args], `Run HWLAB ${state.spec.lane} web-probe sentinel ${subcommand.join(" ")} for node ${state.spec.nodeId}`);
|
||||
const command = `hwlab nodes web-probe sentinel ${subcommand.join(" ")}`;
|
||||
const command = `web-probe sentinel ${subcommand.join(" ")}`;
|
||||
return rendered(true, command, renderAsyncJobResult({
|
||||
ok: true,
|
||||
command,
|
||||
@@ -1318,7 +1318,7 @@ function runSentinelQuickVerify(state: SentinelCicdState, reason: string, timeou
|
||||
const runId = `sentinel-run-${Date.now().toString(36)}-${randomUUID().slice(0, 8)}`;
|
||||
const steps: Record<string, unknown>[] = [];
|
||||
const startArgs = [
|
||||
"hwlab", "nodes", "web-probe", "observe", "start",
|
||||
"web-probe", "observe", "start",
|
||||
"--node", state.spec.nodeId,
|
||||
"--lane", state.spec.lane,
|
||||
"--target-path", stringAt(scenario, "observeTargetPath"),
|
||||
@@ -1360,7 +1360,7 @@ function runSentinelQuickVerify(state: SentinelCicdState, reason: string, timeou
|
||||
promptSource: prompts.summary,
|
||||
}));
|
||||
}
|
||||
const args = ["hwlab", "nodes", "web-probe", "observe", "command", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--type", type, "--wait-ms", "55000", "--command-timeout-seconds", String(remainingSeconds(deadline, 55))];
|
||||
const args = ["web-probe", "observe", "command", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--type", type, "--wait-ms", "55000", "--command-timeout-seconds", String(remainingSeconds(deadline, 55))];
|
||||
if (type === "selectProvider") args.push("--provider", stringAt(item, "provider"));
|
||||
if (type === "sendPrompt") {
|
||||
args.push("--text", prompts.prompts[promptIndex % prompts.prompts.length] ?? "");
|
||||
@@ -1399,7 +1399,7 @@ function runSentinelQuickVerify(state: SentinelCicdState, reason: string, timeou
|
||||
}
|
||||
}
|
||||
}
|
||||
const analysis = runChildCli(["hwlab", "nodes", "web-probe", "observe", "analyze", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--command-timeout-seconds", String(remainingSeconds(deadline, 120))], remainingSeconds(deadline, 120));
|
||||
const analysis = runChildCli(["web-probe", "observe", "analyze", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--command-timeout-seconds", String(remainingSeconds(deadline, 120))], remainingSeconds(deadline, 120));
|
||||
steps.push({ phase: "observe-analyze", ok: analysis.ok, result: analysis.result });
|
||||
const indexEntry = readLocalObserveIndex(observerId);
|
||||
const artifactSummary = indexEntry === null ? { ok: false, reason: "observe-index-entry-missing", observerId, valuesRedacted: true } : readAnalysisSummaryFromWorkspace(state, indexEntry.stateDir, remainingSeconds(deadline, 30));
|
||||
@@ -1446,7 +1446,7 @@ function finalizeQuickVerifyFailure(state: SentinelCicdState, input: {
|
||||
const cleanupSteps: Record<string, unknown>[] = [];
|
||||
if (input.promptIndex > 0) {
|
||||
const cancel = runChildCli([
|
||||
"hwlab", "nodes", "web-probe", "observe", "command", input.observerId,
|
||||
"web-probe", "observe", "command", input.observerId,
|
||||
"--node", state.spec.nodeId,
|
||||
"--lane", state.spec.lane,
|
||||
"--type", "cancel",
|
||||
@@ -1456,7 +1456,7 @@ function finalizeQuickVerifyFailure(state: SentinelCicdState, input: {
|
||||
cleanupSteps.push({ phase: "observe-cancel-after-failure", ok: cancel.ok, result: cancel.result });
|
||||
}
|
||||
const stop = runChildCli([
|
||||
"hwlab", "nodes", "web-probe", "observe", "stop", input.observerId,
|
||||
"web-probe", "observe", "stop", input.observerId,
|
||||
"--node", state.spec.nodeId,
|
||||
"--lane", state.spec.lane,
|
||||
"--force",
|
||||
@@ -1464,7 +1464,7 @@ function finalizeQuickVerifyFailure(state: SentinelCicdState, input: {
|
||||
], 30);
|
||||
cleanupSteps.push({ phase: "observe-stop-after-failure", ok: stop.ok, result: stop.result });
|
||||
const analysis = runChildCli([
|
||||
"hwlab", "nodes", "web-probe", "observe", "analyze", input.observerId,
|
||||
"web-probe", "observe", "analyze", input.observerId,
|
||||
"--node", state.spec.nodeId,
|
||||
"--lane", state.spec.lane,
|
||||
"--command-timeout-seconds", "55",
|
||||
@@ -1815,7 +1815,7 @@ function readAnalysisSummaryFromWorkspace(state: SentinelCicdState, stateDir: st
|
||||
}
|
||||
|
||||
function collectObserveView(state: SentinelCicdState, observerId: string, view: "turn-summary" | "trace-frame", turn: number | null, timeoutSeconds: number): Record<string, unknown> {
|
||||
const args = ["hwlab", "nodes", "web-probe", "observe", "collect", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--view", view, "--command-timeout-seconds", String(Math.max(5, Math.min(timeoutSeconds, 55))), "--raw", "--compact-raw"];
|
||||
const args = ["web-probe", "observe", "collect", observerId, "--node", state.spec.nodeId, "--lane", state.spec.lane, "--view", view, "--command-timeout-seconds", String(Math.max(5, Math.min(timeoutSeconds, 55))), "--raw", "--compact-raw"];
|
||||
if (turn !== null) args.push("--turn", String(turn));
|
||||
const result = runChildCli(args, timeoutSeconds);
|
||||
const payload = cliDataPayload(result.parsed);
|
||||
@@ -2124,7 +2124,7 @@ function serviceUnavailableBlocker(state: SentinelCicdState): Record<string, unk
|
||||
code: "sentinel-service-unavailable",
|
||||
policy: stringAt(state.cicd, "targetValidation.serviceUnavailablePolicy"),
|
||||
reason: "sentinel service must be reachable through k3s internal Service DNS before quick verify can run; no public/fallback path is used.",
|
||||
retry: `bun scripts/cli.ts hwlab nodes web-probe sentinel validate --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
|
||||
retry: `bun scripts/cli.ts web-probe sentinel validate --node ${state.spec.nodeId} --lane ${state.spec.lane}`,
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
@@ -2133,11 +2133,11 @@ function sentinelP5Next(state: SentinelCicdState): Record<string, string> {
|
||||
const node = state.spec.nodeId;
|
||||
const lane = state.spec.lane;
|
||||
return {
|
||||
validate: `bun scripts/cli.ts hwlab nodes web-probe sentinel validate --node ${node} --lane ${lane}`,
|
||||
quickVerify: `bun scripts/cli.ts hwlab nodes web-probe sentinel validate --node ${node} --lane ${lane} --quick-verify --confirm --wait`,
|
||||
maintenanceStart: `bun scripts/cli.ts hwlab nodes web-probe sentinel maintenance start --node ${node} --lane ${lane} --confirm --wait`,
|
||||
maintenanceStop: `bun scripts/cli.ts hwlab nodes web-probe sentinel maintenance stop --node ${node} --lane ${lane} --confirm --wait`,
|
||||
report: `bun scripts/cli.ts hwlab nodes web-probe sentinel report --node ${node} --lane ${lane} --view summary`,
|
||||
validate: `bun scripts/cli.ts web-probe sentinel validate --node ${node} --lane ${lane}`,
|
||||
quickVerify: `bun scripts/cli.ts web-probe sentinel validate --node ${node} --lane ${lane} --quick-verify --confirm --wait`,
|
||||
maintenanceStart: `bun scripts/cli.ts web-probe sentinel maintenance start --node ${node} --lane ${lane} --confirm --wait`,
|
||||
maintenanceStop: `bun scripts/cli.ts web-probe sentinel maintenance stop --node ${node} --lane ${lane} --confirm --wait`,
|
||||
report: `bun scripts/cli.ts web-probe sentinel report --node ${node} --lane ${lane} --view summary`,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user