mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
chore(scripts): end failing oxlint runs with a stable status line (#112532)
* chore(scripts): end failing oxlint runs with a stable status line A crashed run-oxlint wrapper printed only a stack trace, and a lint invocation whose output was truncated (cmd | tail -N) read as success — which recently let a wrapper crash (stale node_modules after a dep-adding merge) masquerade as a clean lint. Route the CLI entry through a small wrapper that converts crashes into exit 1 and ends every failing run with '[oxlint] FAILED (exit N)' as the final line. * chore(scripts): declare runOxlintCliEntry in the script declaration contract check-guards verifies .d.mts contracts against .mjs exports and check-test-types consumes them; the new entry export needed both the declaration and explicit log-parameter annotations in the test.
This commit is contained in:
committed by
GitHub
parent
3946bcc20c
commit
5dafb13614
@@ -29,3 +29,11 @@ export function filterSparseMissingOxlintTargets(
|
||||
* Applies wrapper policy and runs oxlint with the final argument list.
|
||||
*/
|
||||
export function main(argv?: string[], runtimeEnv?: NodeJS.ProcessEnv): Promise<void>;
|
||||
/**
|
||||
* CLI entry: converts wrapper crashes into exit 1 and ends every failing run
|
||||
* with a stable `[oxlint] FAILED (exit N)` final line.
|
||||
*/
|
||||
export function runOxlintCliEntry(
|
||||
run?: () => Promise<void>,
|
||||
log?: (message: unknown) => void,
|
||||
): Promise<void>;
|
||||
|
||||
+20
-2
@@ -281,6 +281,24 @@ export async function main(argv = process.argv.slice(2), runtimeEnv = process.en
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
await main();
|
||||
/**
|
||||
* CLI entry: converts wrapper crashes into a nonzero exit and ends every
|
||||
* failing run with one stable final line. That line must survive output
|
||||
* truncation (`… | tail -N`): without it, a crash or lint failure whose
|
||||
* diagnostics scrolled away reads as success when only the tail is inspected.
|
||||
*/
|
||||
export async function runOxlintCliEntry(run = main, log = console.error) {
|
||||
try {
|
||||
await run();
|
||||
} catch (error) {
|
||||
log(error);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
if (typeof process.exitCode === "number" && process.exitCode !== 0) {
|
||||
log(`[oxlint] FAILED (exit ${process.exitCode})`);
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
await runOxlintCliEntry();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
} from "../../scripts/run-oxlint-shards.mjs";
|
||||
import {
|
||||
filterSparseMissingOxlintTargets,
|
||||
runOxlintCliEntry,
|
||||
shouldPrepareExtensionPackageBoundaryArtifacts,
|
||||
} from "../../scripts/run-oxlint.mjs";
|
||||
import { createScriptTestHarness } from "./test-helpers.js";
|
||||
@@ -49,6 +50,60 @@ function isProcessAlive(pid: number): boolean {
|
||||
}
|
||||
|
||||
describe("run-oxlint", () => {
|
||||
it("ends a failing run with a stable final status line", async () => {
|
||||
const priorExitCode = process.exitCode;
|
||||
const lines: unknown[] = [];
|
||||
try {
|
||||
process.exitCode = 0;
|
||||
await runOxlintCliEntry(
|
||||
async () => {
|
||||
process.exitCode = 2;
|
||||
},
|
||||
(line: unknown) => lines.push(line),
|
||||
);
|
||||
expect(lines).toEqual(["[oxlint] FAILED (exit 2)"]);
|
||||
} finally {
|
||||
process.exitCode = priorExitCode;
|
||||
}
|
||||
});
|
||||
|
||||
it("converts a wrapper crash into a nonzero exit with the status line last", async () => {
|
||||
// The original incident: a crashed wrapper printed only a stack trace, and
|
||||
// truncated output read as success. The marker must be the final line.
|
||||
const priorExitCode = process.exitCode;
|
||||
const lines: unknown[] = [];
|
||||
try {
|
||||
process.exitCode = 0;
|
||||
await runOxlintCliEntry(
|
||||
async () => {
|
||||
throw new Error("artifact prep failed");
|
||||
},
|
||||
(line: unknown) => lines.push(line),
|
||||
);
|
||||
expect(process.exitCode).toBe(1);
|
||||
expect(lines).toHaveLength(2);
|
||||
expect(lines[0]).toBeInstanceOf(Error);
|
||||
expect(lines[1]).toBe("[oxlint] FAILED (exit 1)");
|
||||
} finally {
|
||||
process.exitCode = priorExitCode;
|
||||
}
|
||||
});
|
||||
|
||||
it("stays silent on a clean run", async () => {
|
||||
const priorExitCode = process.exitCode;
|
||||
const lines: unknown[] = [];
|
||||
try {
|
||||
process.exitCode = 0;
|
||||
await runOxlintCliEntry(
|
||||
async () => {},
|
||||
(line: unknown) => lines.push(line),
|
||||
);
|
||||
expect(lines).toEqual([]);
|
||||
} finally {
|
||||
process.exitCode = priorExitCode;
|
||||
}
|
||||
});
|
||||
|
||||
it("prepares extension package boundary artifacts for normal lint runs", () => {
|
||||
expect(shouldPrepareExtensionPackageBoundaryArtifacts([])).toBe(true);
|
||||
expect(shouldPrepareExtensionPackageBoundaryArtifacts(["src/index.ts"])).toBe(true);
|
||||
|
||||
Reference in New Issue
Block a user