fix(qa-lab): bound evidence checkout ref git probe with timeout (#111448)

Co-authored-by: thomas.szbay <thomas.szbay@example.com>
This commit is contained in:
thomas.szbay
2026-07-19 15:48:53 -07:00
committed by GitHub
co-authored by thomas.szbay
parent e0b1a39d2a
commit a0c3067b54
2 changed files with 72 additions and 0 deletions
@@ -0,0 +1,66 @@
// Qa Lab tests bound the evidence checkout ref git probe.
import { afterEach, describe, expect, it, vi } from "vitest";
const execFileSyncMock = vi.hoisted(() => vi.fn());
vi.mock("node:child_process", async () => {
const actual = await vi.importActual<typeof import("node:child_process")>("node:child_process");
return {
...actual,
execFileSync: execFileSyncMock,
};
});
import { resolveQaEvidenceEnvironment } from "./evidence-environment.js";
afterEach(() => {
vi.restoreAllMocks();
execFileSyncMock.mockReset();
});
describe("resolveQaEvidenceEnvironment", () => {
it("bounds the checkout ref git probe with a timeout", () => {
execFileSyncMock.mockReturnValue("abc123\n");
const environment = resolveQaEvidenceEnvironment({ env: {} });
expect(environment.ref).toBe("abc123");
expect(execFileSyncMock).toHaveBeenCalledWith(
"git",
["rev-parse", "--verify", "HEAD"],
expect.objectContaining({
killSignal: "SIGKILL",
timeout: 5_000,
}),
);
});
it("falls back to GITHUB_SHA when the git probe times out", () => {
execFileSyncMock.mockImplementation(() => {
throw Object.assign(new Error("Command timed out"), { code: "ETIMEDOUT" });
});
const environment = resolveQaEvidenceEnvironment({ env: { GITHUB_SHA: "fallbacksha" } });
expect(environment.ref).toBe("fallbacksha");
});
it("prefers OPENCLAW_QA_REF without invoking git", () => {
const environment = resolveQaEvidenceEnvironment({
env: { OPENCLAW_QA_REF: "qa-ref", GITHUB_SHA: "fallbacksha" },
});
expect(environment.ref).toBe("qa-ref");
expect(execFileSyncMock).not.toHaveBeenCalled();
});
it("returns a null ref when the probe fails and no env fallback exists", () => {
execFileSyncMock.mockImplementation(() => {
throw new Error("git unavailable");
});
const environment = resolveQaEvidenceEnvironment({ env: {} });
expect(environment.ref).toBeNull();
});
});
@@ -1,12 +1,18 @@
// Qa Lab plugin module resolves evidence runtime metadata.
import { execFileSync } from "node:child_process";
// A wedged git (NFS hang, credential helper prompt) must not block evidence
// metadata resolution; the caller already falls back to GITHUB_SHA/null.
const QA_EVIDENCE_GIT_PROBE_TIMEOUT_MS = 5_000;
function resolveQaEvidenceCheckoutRef(repoRoot?: string) {
try {
const ref = execFileSync("git", ["rev-parse", "--verify", "HEAD"], {
cwd: repoRoot ?? process.cwd(),
encoding: "utf8",
killSignal: "SIGKILL",
stdio: ["ignore", "pipe", "ignore"],
timeout: QA_EVIDENCE_GIT_PROBE_TIMEOUT_MS,
}).trim();
return ref || undefined;
} catch {