diff --git a/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts b/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts index cc6a0d96b599..fe8eeb629d9c 100644 --- a/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts +++ b/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts @@ -253,6 +253,22 @@ describe("Slack live QA runtime helpers", () => { ); }); + it("preserves sanitized gateway debug artifacts on scenario failure", async () => { + const cleanupIssues: string[] = []; + const stop = vi.fn(async () => {}); + + await testing.preserveSlackGatewayDebugArtifacts({ + cleanupIssues, + gatewayDebugDirPath: ".artifacts/qa-e2e/slack-live-test/gateway-debug", + gatewayHarness: { stop } as never, + }); + + expect(stop).toHaveBeenCalledWith({ + preserveToDir: ".artifacts/qa-e2e/slack-live-test/gateway-debug", + }); + expect(cleanupIssues).toEqual([]); + }); + it("redacts approval artifact content and Slack metadata in summary-shaped results", () => { expect( testing.toSlackQaScenarioArtifactResults({ diff --git a/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts b/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts index 1fed9ddb4b37..befa8065bbbc 100644 --- a/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts +++ b/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts @@ -119,6 +119,8 @@ type SlackQaScenarioDefinition = LiveTransportScenarioDefinition>; + type SlackAuthIdentity = { botId?: string; teamId?: string; @@ -1718,6 +1720,16 @@ function renderSlackQaMarkdown(params: { return lines.join("\n"); } +async function preserveSlackGatewayDebugArtifacts(params: { + cleanupIssues: string[]; + gatewayDebugDirPath: string; + gatewayHarness: SlackQaGatewayHarness; +}) { + await params.gatewayHarness.stop({ preserveToDir: params.gatewayDebugDirPath }).catch((error) => { + appendLiveLaneIssue(params.cleanupIssues, "gateway debug preservation failed", error); + }); +} + export async function runSlackQaLive(params: { alternateModel?: string; credentialRole?: string; @@ -1789,7 +1801,7 @@ export async function runSlackQaLive(params: { for (const scenario of scenarios) { let scenarioAttempt = 1; while (true) { - let gatewayHarness: Awaited> | undefined; + let gatewayHarness: SlackQaGatewayHarness | undefined; try { assertLeaseHealthy(); gatewayHarness = await startQaLiveLaneGateway({ @@ -1971,11 +1983,11 @@ export async function runSlackQaLive(params: { }); preservedGatewayDebugArtifacts = true; if (gatewayHarness) { - await gatewayHarness - .stop({ keepTemp: true, preserveToDir: gatewayDebugDirPath }) - .catch((stopError) => { - appendLiveLaneIssue(cleanupIssues, "gateway debug preservation failed", stopError); - }); + await preserveSlackGatewayDebugArtifacts({ + cleanupIssues, + gatewayDebugDirPath, + gatewayHarness, + }); } break; } finally { @@ -2114,6 +2126,7 @@ export const testing = { findScenario, isSlackChannelReadyForQa, parseSlackQaCredentialPayload, + preserveSlackGatewayDebugArtifacts, resolveSlackChannelReadySince, resolveSlackApprovalCheckpointConfig, resolveApprovalDecision,