From 7374ecc777629f2f0ea5697b42f0def53180ffd7 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Tue, 23 Jun 2026 13:34:20 +0200 Subject: [PATCH] fix(qa): reject duplicate qa e2e outputs --- scripts/qa-e2e.ts | 14 ++++++++++---- test/scripts/qa-e2e.test.ts | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/scripts/qa-e2e.ts b/scripts/qa-e2e.ts index 8c4ba39343c..41e5240e2b0 100644 --- a/scripts/qa-e2e.ts +++ b/scripts/qa-e2e.ts @@ -44,11 +44,17 @@ export function parseQaE2eArgs(argv: readonly string[]): QaE2eArgs { const args = argv[0] === "--" ? argv.slice(1) : argv; let outputPath = ""; let positionalMode = false; + const setOutputPath = (value: string) => { + if (outputPath) { + throw new Error("qa:e2e output path was provided more than once"); + } + outputPath = value; + }; for (let index = 0; index < args.length; index += 1) { const arg = args[index] ?? ""; if (positionalMode) { if (!outputPath && arg.trim()) { - outputPath = arg.trim(); + setOutputPath(arg.trim()); continue; } throw new Error(`Unexpected qa:e2e argument: ${arg}`); @@ -65,7 +71,7 @@ export function parseQaE2eArgs(argv: readonly string[]): QaE2eArgs { if (!inlineOutput) { throw new Error("--output requires a value"); } - outputPath = inlineOutput; + setOutputPath(inlineOutput); continue; } if (arg === "--output") { @@ -73,7 +79,7 @@ export function parseQaE2eArgs(argv: readonly string[]): QaE2eArgs { if (!value || value.startsWith("-")) { throw new Error("--output requires a value"); } - outputPath = value; + setOutputPath(value); index += 1; continue; } @@ -83,7 +89,7 @@ export function parseQaE2eArgs(argv: readonly string[]): QaE2eArgs { if (outputPath) { throw new Error(`Unexpected qa:e2e argument: ${arg}`); } - outputPath = arg.trim(); + setOutputPath(arg.trim()); } return outputPath ? { help: false, outputPath } : { help: false }; } diff --git a/test/scripts/qa-e2e.test.ts b/test/scripts/qa-e2e.test.ts index 35a9e3b6f76..5279a1543bf 100644 --- a/test/scripts/qa-e2e.test.ts +++ b/test/scripts/qa-e2e.test.ts @@ -95,6 +95,23 @@ describe("qa-e2e script", () => { expect(() => parseQaE2eArgs(["--output", "--help"])).toThrow("--output requires a value"); }); + it("rejects duplicate output destinations before loading QA Lab", async () => { + const env: NodeJS.ProcessEnv = {}; + const loadRuntime = vi.fn(async () => { + throw new Error("runtime loaded"); + }); + + expect(() => + parseQaE2eArgs(["--output", ".artifacts/first.md", "--output=.artifacts/second.md"]), + ).toThrow("qa:e2e output path was provided more than once"); + await expect( + main([".artifacts/first.md", "--output", ".artifacts/second.md"], { env, loadRuntime }), + ).rejects.toThrow("qa:e2e output path was provided more than once"); + + expect(loadRuntime).not.toHaveBeenCalled(); + expect(env.OPENCLAW_BUILD_PRIVATE_QA).toBeUndefined(); + }); + it.each([ { status: "pass" as const, exitCode: 0 }, { status: "fail" as const, exitCode: 1 },