mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-30 02:08:44 +00:00
Scope config preflight note suppression (#84439)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { note } from "../../terminal/note.js";
|
||||
import { formatCliCommand } from "../command-format.js";
|
||||
import { ensureConfigReady, testApi } from "./config-guard.js";
|
||||
|
||||
@@ -39,10 +40,20 @@ function plainErrorCalls(runtime: ReturnType<typeof makeRuntime>): string[] {
|
||||
|
||||
async function withCapturedStdout(run: () => Promise<void>): Promise<string> {
|
||||
const writes: string[] = [];
|
||||
const writeSpy = vi.spyOn(process.stdout, "write").mockImplementation(((chunk: unknown) => {
|
||||
writes.push(String(chunk));
|
||||
return true;
|
||||
}) as typeof process.stdout.write);
|
||||
const writeSpy = vi
|
||||
.spyOn(process.stdout, "write")
|
||||
.mockImplementation(
|
||||
((
|
||||
chunk: unknown,
|
||||
encodingOrCallback?: BufferEncoding | ((error?: Error | null) => void),
|
||||
callback?: (error?: Error | null) => void,
|
||||
) => {
|
||||
writes.push(String(chunk));
|
||||
const done = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
|
||||
done?.();
|
||||
return true;
|
||||
}) as typeof process.stdout.write,
|
||||
);
|
||||
try {
|
||||
await run();
|
||||
return writes.join("");
|
||||
@@ -212,9 +223,9 @@ describe("ensureConfigReady", () => {
|
||||
expect(loadAndMaybeMigrateDoctorConfigMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("prevents preflight stdout noise when suppression is enabled", async () => {
|
||||
it("prevents preflight note noise when suppression is enabled", async () => {
|
||||
loadAndMaybeMigrateDoctorConfigMock.mockImplementation(async () => {
|
||||
process.stdout.write("Doctor warnings\n");
|
||||
note("Doctor warnings", "Config warnings");
|
||||
return {
|
||||
snapshot: makeSnapshot(),
|
||||
baseConfig: {},
|
||||
@@ -226,9 +237,9 @@ describe("ensureConfigReady", () => {
|
||||
expect(output).not.toContain("Doctor warnings");
|
||||
});
|
||||
|
||||
it("allows preflight stdout noise when suppression is not enabled", async () => {
|
||||
it("allows preflight note noise when suppression is not enabled", async () => {
|
||||
loadAndMaybeMigrateDoctorConfigMock.mockImplementation(async () => {
|
||||
process.stdout.write("Doctor warnings\n");
|
||||
note("Doctor warnings", "Config warnings");
|
||||
return {
|
||||
snapshot: makeSnapshot(),
|
||||
baseConfig: {},
|
||||
@@ -239,4 +250,39 @@ describe("ensureConfigReady", () => {
|
||||
});
|
||||
expect(output).toContain("Doctor warnings");
|
||||
});
|
||||
|
||||
it("does not suppress unrelated concurrent stdout writes while suppressing preflight notes", async () => {
|
||||
let releasePreflight: (() => void) | undefined;
|
||||
let preflightStarted: (() => void) | undefined;
|
||||
const preflightStartedPromise = new Promise<void>((resolve) => {
|
||||
preflightStarted = resolve;
|
||||
});
|
||||
const releasePreflightPromise = new Promise<void>((resolve) => {
|
||||
releasePreflight = resolve;
|
||||
});
|
||||
loadAndMaybeMigrateDoctorConfigMock.mockImplementation(async () => {
|
||||
note("Doctor warnings", "Config warnings");
|
||||
preflightStarted?.();
|
||||
await releasePreflightPromise;
|
||||
return {
|
||||
snapshot: makeSnapshot(),
|
||||
baseConfig: {},
|
||||
};
|
||||
});
|
||||
|
||||
let callbackCalled = false;
|
||||
const output = await withCapturedStdout(async () => {
|
||||
const ready = runEnsureConfigReady(["message"], true);
|
||||
await preflightStartedPromise;
|
||||
process.stdout.write("Concurrent output\n", () => {
|
||||
callbackCalled = true;
|
||||
});
|
||||
releasePreflight?.();
|
||||
await ready;
|
||||
});
|
||||
|
||||
expect(output).toContain("Concurrent output");
|
||||
expect(output).not.toContain("Doctor warnings");
|
||||
expect(callbackCalled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { readConfigFileSnapshot, setRuntimeConfigSnapshot } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { withSuppressedNotes } from "../../terminal/note.js";
|
||||
import { shouldMigrateStateFromPath } from "../argv.js";
|
||||
|
||||
const ALLOWED_INVALID_COMMANDS = new Set(["doctor", "logs", "health", "help", "status"]);
|
||||
@@ -62,20 +63,7 @@ export async function ensureConfigReady(params: {
|
||||
if (!params.suppressDoctorStdout) {
|
||||
preflightSnapshot = (await runDoctorConfigPreflight()).snapshot;
|
||||
} else {
|
||||
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
||||
const originalSuppressNotes = process.env.OPENCLAW_SUPPRESS_NOTES;
|
||||
process.stdout.write = (() => true) as unknown as typeof process.stdout.write;
|
||||
process.env.OPENCLAW_SUPPRESS_NOTES = "1";
|
||||
try {
|
||||
preflightSnapshot = (await runDoctorConfigPreflight()).snapshot;
|
||||
} finally {
|
||||
process.stdout.write = originalStdoutWrite;
|
||||
if (originalSuppressNotes === undefined) {
|
||||
delete process.env.OPENCLAW_SUPPRESS_NOTES;
|
||||
} else {
|
||||
process.env.OPENCLAW_SUPPRESS_NOTES = originalSuppressNotes;
|
||||
}
|
||||
}
|
||||
preflightSnapshot = (await withSuppressedNotes(runDoctorConfigPreflight)).snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user