Scope config preflight note suppression (#84439)

This commit is contained in:
Andy Ye
2026-05-22 15:51:34 -07:00
committed by GitHub
parent 1cd6dce075
commit 91d85e70c3
3 changed files with 66 additions and 23 deletions

View File

@@ -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);
});
});

View File

@@ -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;
}
}