fix: harden workbench smoke dependencies

This commit is contained in:
Code Queue Review
2026-05-23 04:53:56 +00:00
parent b9b625c4e8
commit 48e078e55c
2 changed files with 94 additions and 14 deletions
+2
View File
@@ -365,6 +365,8 @@ function copyHeaders(headers) {
const result = {};
for (const [key, value] of Object.entries(headers)) {
if (value === undefined) continue;
if (key.toLowerCase() === "transfer-encoding") continue;
if (key.toLowerCase() === "content-length") continue;
result[key] = value;
}
return result;
+92 -14
View File
@@ -3,7 +3,7 @@ import { execFileSync } from "node:child_process";
import { createHash } from "node:crypto";
import http from "node:http";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { fileURLToPath, pathToFileURL } from "node:url";
import { gateSummary } from "../../web/hwlab-cloud-web/gate-summary.mjs";
import { runtime } from "../../web/hwlab-cloud-web/runtime.mjs";
@@ -172,6 +172,10 @@ const markdownRendererPackages = Object.freeze([
"commonmark"
]);
const playwrightDependencyCommand = "npm install";
const playwrightDependencySummary =
"Install repository dependencies before running browser smokes: npm install provides the declared playwright package; the Code Queue image may also provide the same package globally.";
export function runDevCloudWorkbenchStaticSmoke() {
return runStaticSmoke();
}
@@ -194,6 +198,40 @@ export async function runDevCloudWorkbenchSmoke(argv = []) {
return runStaticSmoke();
}
async function importPlaywright() {
try {
return normalizePlaywrightModule(await import("playwright"));
} catch (localError) {
const globalRoot = npmGlobalRoot();
if (globalRoot) {
try {
return normalizePlaywrightModule(await import(pathToFileURL(path.join(globalRoot, "playwright/index.js")).href));
} catch {
// Fall through to the original local resolution error so the remediation points at package.json.
}
}
throw localError;
}
}
function normalizePlaywrightModule(module) {
if (module?.chromium) return module;
if (module?.default?.chromium) return module.default;
return module;
}
function npmGlobalRoot() {
try {
return execFileSync("npm", ["root", "-g"], {
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
timeout: 5000
}).trim();
} catch {
return "";
}
}
export function parseSmokeArgs(argv) {
const args = { mode: "static", url: defaultLiveUrl };
for (let index = 0; index < argv.length; index += 1) {
@@ -1698,7 +1736,7 @@ function liveHtmlLooksLikeWorkbench(html) {
async function inspectLiveDom(url) {
let chromium;
try {
({ chromium } = await import("playwright"));
({ chromium } = await importPlaywright());
} catch (error) {
return {
status: "skip",
@@ -1792,7 +1830,7 @@ async function inspectLiveDom(url) {
async function inspectLiveHelpRoute(url) {
let chromium;
try {
({ chromium } = await import("playwright"));
({ chromium } = await importPlaywright());
} catch (error) {
return {
status: "skip",
@@ -1837,7 +1875,7 @@ async function inspectLiveHelpRoute(url) {
async function inspectLiveUserJourney(url) {
let chromium;
try {
({ chromium } = await import("playwright"));
({ chromium } = await importPlaywright());
} catch (error) {
return {
status: "skip",
@@ -2054,18 +2092,38 @@ async function runLocalAgentFixtureSmoke({
} = {}) {
let chromium;
try {
({ chromium } = await import("playwright"));
({ chromium } = await importPlaywright());
} catch (error) {
const summary = `Local Code Agent browser fixture smoke skipped because Playwright is unavailable: ${error.message}`;
return {
status: "skip",
task: "DC-DCSN-P0-2026-003",
mode,
evidenceLevel: "SOURCE",
devLive: false,
summary: `Local Code Agent browser fixture smoke skipped because Playwright is unavailable: ${error.message}`,
checks: [],
blockers: [],
safety: staticSafety()
summary,
checks: [
{
id: "local-agent-fixture-browser-dependency",
status: "skip",
summary: playwrightDependencySummary,
evidence: [playwrightDependencyCommand, "package.json dependencies.playwright"]
}
],
blockers: [
{
type: "environment_blocker",
scope: "local-agent-fixture-browser-dependency",
status: "open",
summary
}
],
safety: staticSafety(),
dependency: {
package: "playwright",
declaredIn: "package.json",
installCommand: playwrightDependencyCommand
}
};
}
@@ -2240,8 +2298,9 @@ async function runLocalAgentFixtureSmoke({
export async function runDevCloudWorkbenchMobileSmoke() {
let chromium;
try {
({ chromium } = await import("playwright"));
({ chromium } = await importPlaywright());
} catch (error) {
const summary = `Mobile browser smoke skipped because Playwright is unavailable: ${error.message}`;
return {
status: "skip",
task: "DC-DCSN-P0-2026-003",
@@ -2249,10 +2308,29 @@ export async function runDevCloudWorkbenchMobileSmoke() {
viewport: { width: 390, height: 844 },
evidenceLevel: "SOURCE",
devLive: false,
summary: `Mobile browser smoke skipped because Playwright is unavailable: ${error.message}`,
checks: [],
blockers: [],
safety: staticSafety()
summary,
checks: [
{
id: "mobile-browser-dependency",
status: "skip",
summary: playwrightDependencySummary,
evidence: [playwrightDependencyCommand, "package.json dependencies.playwright"]
}
],
blockers: [
{
type: "environment_blocker",
scope: "mobile-browser-dependency",
status: "open",
summary
}
],
safety: staticSafety(),
dependency: {
package: "playwright",
declaredIn: "package.json",
installCommand: playwrightDependencyCommand
}
};
}