From cadd14b1a25aea914d29ce0a2d47e9420d4d110a Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 24 Jun 2026 16:46:45 +0000 Subject: [PATCH] fix: honor web-probe direct proxy mode --- scripts/src/hwlab-node-impl.ts | 48 +++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/scripts/src/hwlab-node-impl.ts b/scripts/src/hwlab-node-impl.ts index 4214d3a3..46c06e4a 100644 --- a/scripts/src/hwlab-node-impl.ts +++ b/scripts/src/hwlab-node-impl.ts @@ -304,6 +304,7 @@ const CODE_AGENT_PROVIDER_SOURCE_NAMESPACE = "hwlab-v02"; const CODE_AGENT_PROVIDER_SOURCE_SECRET = "hwlab-v02-code-agent-provider"; const HWLAB_CI_NAMESPACE = "hwlab-ci"; const NODE_RUNTIME_CICD_WAIT_WARNING_SECONDS = 120; +const NODE_RUNTIME_TRIGGER_SEVERE_WARNING_MS = NODE_RUNTIME_CICD_WAIT_WARNING_SECONDS * 1000; export async function runHwlabNodeCommand(_config: Config, args: string[]): Promise | RenderedCliResult> { if (args.length === 0) return hwlabNodeHelp(); @@ -2785,6 +2786,8 @@ function nodeRuntimeTriggerCurrentOutput(scoped: ReturnType): Record { const spec = scoped.spec; const pipelineWaitSeconds = nodeRuntimeCicdWaitSeconds(scoped); + const triggerStartedAt = Date.now(); + const triggerElapsedMs = () => Date.now() - triggerStartedAt; printNodeRuntimeTriggerProgress(spec, { stage: "source-head", status: "started" }); const head = resolveNodeRuntimeLaneHead(spec); const sourceCommit = head.sourceCommit; @@ -2838,6 +2841,9 @@ function nodeRuntimeTriggerCurrent(scoped: ReturnType | null { + if (elapsedMs < NODE_RUNTIME_TRIGGER_SEVERE_WARNING_MS) return null; + return { + code: "node-runtime-trigger-over-120s", + message: `trigger-current total elapsed time exceeded ${NODE_RUNTIME_CICD_WAIT_WARNING_SECONDS}s; this is a severe timeout even if the PipelineRun eventually succeeded and requires follow-up investigation of slow control-plane, Tekton and git-mirror stages.`, + thresholdMs: NODE_RUNTIME_TRIGGER_SEVERE_WARNING_MS, + elapsedMs, + inspectEnvReuse: `bun scripts/cli.ts hwlab nodes control-plane status --node ${spec.nodeId} --lane ${spec.lane} --pipeline-run ${pipelineRun} --full`, + inspectGitMirror: `bun scripts/cli.ts hwlab nodes git-mirror status --node ${spec.nodeId} --lane ${spec.lane}`, + }; +} + function withNodeRuntimeTriggerRendered(result: Record, scoped: ReturnType): RenderedCliResult { const pipelineWait = record(result.pipelineWait); const pipelineRunRecord = record(pipelineWait.pipelineRun ?? result.after ?? result.before); @@ -3013,6 +3036,7 @@ function withNodeRuntimeTriggerRendered(result: Record, scoped: ["create", create.exitCode === 0 || result.mutation === true ? "ok" : create.exitCode === undefined ? "-" : "failed", result.createObservedAfterTimeout === true ? "observed-after-timeout" : `exit=${webObserveText(create.exitCode)}`], ["pipeline-wait", webObserveText(pipelineWait.status), `pipeline=${webObserveText(pipelineStatus)} polls=${webObserveText(pipelineWait.polls)} elapsed=${formatElapsedMs(pipelineWait.elapsedMs)}`], ["post-flush", postFlush.ok === true ? "ok" : postFlush.ok === false ? "failed" : "-", webObserveText(postFlush.mode ?? postFlush.degradedReason)], + ["total", result.triggerElapsedMs === undefined ? "-" : "elapsed", formatElapsedMs(result.triggerElapsedMs)], ], ), "", @@ -3052,7 +3076,7 @@ function withNodeRuntimeTriggerRendered(result: Record, scoped: "", "Disclosure:", " default view is a bounded CICD summary; use --full or --raw for the complete JSON payload.", - ` default wait is ${NODE_RUNTIME_CICD_WAIT_WARNING_SECONDS}s; if exceeded, inspect env-reuse and git-mirror before rerun.`, + ` ${NODE_RUNTIME_CICD_WAIT_WARNING_SECONDS}s is the severe timeout warning threshold for both PipelineRun wait and total trigger elapsed time.`, ].join("\n"); return { ...result, renderedText, contentType: "text/plain" }; } @@ -7793,7 +7817,19 @@ interface NodeWebProbeHostProxyEnv { readonly summary: Record; } -function nodeWebProbeHostProxyEnv(spec: HwlabRuntimeLaneSpec): NodeWebProbeHostProxyEnv { +function nodeWebProbeHostProxyEnv(spec: HwlabRuntimeLaneSpec, browserProxyMode: WebProbeBrowserProxyMode = "auto"): NodeWebProbeHostProxyEnv { + if (browserProxyMode === "direct") { + return { + envAssignments: [], + summary: { + source: "option", + mode: "direct", + networkProfileId: spec.networkProfileId, + proxy: { enabled: false }, + valuesPrinted: false, + }, + }; + } const proxy = spec.networkProfile.proxy; const serviceCache = new Map(); const http = resolveNodeWebProbeHostProxyUrl(spec, proxy.http, serviceCache); @@ -7930,7 +7966,7 @@ function runNodeWebProbeObserveStart( const stateDir = options.stateDir ?? defaultStateDir; const runnerB64 = Buffer.from(nodeWebObserveRunnerSource(), "utf8").toString("base64"); const runnerB64Body = runnerB64.match(/.{1,76}/gu)?.join("\n") ?? runnerB64; - const webProbeProxy = nodeWebProbeHostProxyEnv(spec); + const webProbeProxy = nodeWebProbeHostProxyEnv(spec, options.browserProxyMode); const alertThresholds = nodeWebProbeAlertThresholds(spec); const runnerEnvAssignments = [ ...webProbeProxy.envAssignments, @@ -10702,7 +10738,7 @@ function runNodeWebProbeScript( material: BootstrapAdminPasswordMaterial, credential: Record, ): Record { - const webProbeProxy = nodeWebProbeHostProxyEnv(spec); + const webProbeProxy = nodeWebProbeHostProxyEnv(spec, options.browserProxyMode); const script = nodeWebProbeScriptRemoteShell(options, secretSpec, material.password ?? "", webProbeProxy); const result = runTransWorkspaceStdinScript(options.node, spec.workspace, script, options.commandTimeoutSeconds); const commandTimedOut = result.timedOut || result.exitCode === 124;