mirror of
https://github.com/morluto/rea.git
synced 2026-11-07 05:56:19 -10:00
fix(browser): redact scenario cleanup diagnostics
This commit is contained in:
1 parent
f1535a1753
commit
3a65ef0e4c
2 files changed
+88
-9
No files matched your search
@@ -1642,3 +1642,66 @@ it.each(["absent", "undefined", "inherited", "empty"] as const)(
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it("keeps declared secrets out of final cleanup and retry failure diagnostics", async () => {
|
||||
const { page, cleanup } = fixture();
|
||||
Object.assign(page, { waitForTimeout: vi.fn(async () => undefined) });
|
||||
const input = browserScenarioSchema.parse({
|
||||
...connectedScenario("allow"),
|
||||
secrets: [
|
||||
{
|
||||
secret_id: "credential",
|
||||
environment_variable: "REA_SCENARIO_TEST_SECRET",
|
||||
},
|
||||
],
|
||||
capture: { after_each_step: ["url"], at_end: [], events: [] },
|
||||
});
|
||||
const secret = "declared-cleanup-private-value";
|
||||
vi.spyOn(cleanup, "cleanupResources", "get").mockImplementation(() =>
|
||||
cleanup.browserClosed ? [] : [`browser_transport:${secret}`],
|
||||
);
|
||||
const originalClose = cleanup.close.getMockImplementation()!;
|
||||
let blocked = true;
|
||||
cleanup.close.mockImplementation(async (...args) => {
|
||||
if (blocked) throw new Error(`Close failed after ${secret}`);
|
||||
return originalClose(...args);
|
||||
});
|
||||
const provider = new PlaywrightBrowserScenarioProvider((scenario, options) =>
|
||||
PlaywrightScenarioSession.open(
|
||||
scenario,
|
||||
{ REA_SCENARIO_TEST_SECRET: secret },
|
||||
options,
|
||||
),
|
||||
);
|
||||
try {
|
||||
const result = await provider.captureScenario(input, {});
|
||||
if (result.ok) throw new Error("Expected final cleanup failure");
|
||||
expect(result.error.cleanupIncomplete).toBe(true);
|
||||
expect(result.error.partialObservation).toMatchObject({
|
||||
kind: "browser-scenario-observation",
|
||||
capture: {
|
||||
browser: { cleanup: "incomplete" },
|
||||
steps: [{ action: "goto_start" }, { action: "wait_for_timeout" }],
|
||||
},
|
||||
});
|
||||
expect(JSON.stringify(projectAnalysisError(result.error))).not.toContain(
|
||||
secret,
|
||||
);
|
||||
let retried: unknown;
|
||||
try {
|
||||
await provider.close();
|
||||
} catch (error) {
|
||||
retried = error;
|
||||
}
|
||||
if (!(retried instanceof ProviderCleanupError))
|
||||
throw new Error("Expected retained cleanup failure");
|
||||
expect(JSON.stringify(projectAnalysisError(retried))).not.toContain(secret);
|
||||
blocked = false;
|
||||
await provider.close();
|
||||
expect(cleanup.browserClosed).toBe(true);
|
||||
expect(result.error.cleanupIncomplete).toBe(false);
|
||||
} finally {
|
||||
blocked = false;
|
||||
await provider.close();
|
||||
}
|
||||
});
|
||||
@@ -131,11 +131,23 @@ export class PlaywrightScenarioSession implements BrowserScenarioSessionPort {
|
||||
this.initialUrl = opened.page.url();
|
||||
this.cleanupLease = new AnalysisCleanupLease(
|
||||
async () => {
|
||||
await this.#closeResources();
|
||||
try {
|
||||
await this.#closeResources();
|
||||
} catch (cause: unknown) {
|
||||
throw new BrowserObservationError(OPERATION, "cleanup_failed", {
|
||||
cause,
|
||||
cleanup: {
|
||||
reason: this.redactError(cause),
|
||||
resources: this.cleanupLease.cleanupResources ?? [],
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
get cleanupResources() {
|
||||
return opened.cleanup.cleanupResources;
|
||||
return opened.cleanup.cleanupResources?.map((resource) =>
|
||||
session.secrets.redact(resource),
|
||||
);
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -514,13 +526,17 @@ export class PlaywrightScenarioSession implements BrowserScenarioSessionPort {
|
||||
PLAYWRIGHT_CLEANUP_CONFIRMATION_TIMEOUT_MS,
|
||||
);
|
||||
} catch (cause: unknown) {
|
||||
const error = new BrowserObservationError(OPERATION, "cleanup_failed", {
|
||||
cause,
|
||||
cleanup: {
|
||||
reason: cause instanceof Error ? cause.message : String(cause),
|
||||
resources: this.cleanupLease.cleanupResources ?? [],
|
||||
},
|
||||
});
|
||||
const error =
|
||||
cause instanceof BrowserObservationError &&
|
||||
cause.reason === "cleanup_failed"
|
||||
? cause
|
||||
: new BrowserObservationError(OPERATION, "cleanup_failed", {
|
||||
cause,
|
||||
cleanup: {
|
||||
reason: this.redactError(cause),
|
||||
resources: this.cleanupLease.cleanupResources ?? [],
|
||||
},
|
||||
});
|
||||
new AnalysisCleanupLeaseGroup(error, [this.cleanupLease]);
|
||||
throw error;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user