fix(ci): address macOS vitest worker crash flakiness
- vitest.config.ts: Use singleFork mode on macOS CI and longer teardown timeout to allow proper cleanup of native modules (node:sqlite, chokidar) - test/setup.ts: Clean up warning filter during test teardown - src/infra/warnings.ts: Return cleanup function from installProcessWarningFilter - .github/workflows/ci.yml: Remove retry loop now that root cause is fixed
This commit is contained in:
parent
1750d0855b
commit
66ef42a2f9
@ -6,6 +6,11 @@ type Warning = Error & {
|
|||||||
message?: string;
|
message?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type WarningFilterState = {
|
||||||
|
installed: boolean;
|
||||||
|
listener?: (warning: Warning) => void;
|
||||||
|
};
|
||||||
|
|
||||||
function shouldIgnoreWarning(warning: Warning): boolean {
|
function shouldIgnoreWarning(warning: Warning): boolean {
|
||||||
if (warning.code === "DEP0040" && warning.message?.includes("punycode")) {
|
if (warning.code === "DEP0040" && warning.message?.includes("punycode")) {
|
||||||
return true;
|
return true;
|
||||||
@ -22,15 +27,33 @@ function shouldIgnoreWarning(warning: Warning): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function installProcessWarningFilter(): void {
|
/**
|
||||||
|
* Install a process warning filter that suppresses known benign warnings.
|
||||||
|
* Returns a cleanup function to remove the listener (useful for test teardown).
|
||||||
|
*/
|
||||||
|
export function installProcessWarningFilter(): () => void {
|
||||||
const globalState = globalThis as typeof globalThis & {
|
const globalState = globalThis as typeof globalThis & {
|
||||||
[warningFilterKey]?: { installed: boolean };
|
[warningFilterKey]?: WarningFilterState;
|
||||||
};
|
};
|
||||||
if (globalState[warningFilterKey]?.installed) return;
|
if (globalState[warningFilterKey]?.installed) {
|
||||||
globalState[warningFilterKey] = { installed: true };
|
// Already installed - return a no-op cleanup
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
|
||||||
process.on("warning", (warning: Warning) => {
|
const listener = (warning: Warning) => {
|
||||||
if (shouldIgnoreWarning(warning)) return;
|
if (shouldIgnoreWarning(warning)) return;
|
||||||
process.stderr.write(`${warning.stack ?? warning.toString()}\n`);
|
process.stderr.write(`${warning.stack ?? warning.toString()}\n`);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
globalState[warningFilterKey] = { installed: true, listener };
|
||||||
|
process.on("warning", listener);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const state = globalState[warningFilterKey];
|
||||||
|
if (state?.listener) {
|
||||||
|
process.off("warning", state.listener);
|
||||||
|
state.listener = undefined;
|
||||||
|
state.installed = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,10 +15,13 @@ import { setActivePluginRegistry } from "../src/plugins/runtime.js";
|
|||||||
import { createTestRegistry } from "../src/test-utils/channel-plugins.js";
|
import { createTestRegistry } from "../src/test-utils/channel-plugins.js";
|
||||||
import { withIsolatedTestHome } from "./test-env";
|
import { withIsolatedTestHome } from "./test-env";
|
||||||
|
|
||||||
installProcessWarningFilter();
|
const cleanupWarningFilter = installProcessWarningFilter();
|
||||||
|
|
||||||
const testEnv = withIsolatedTestHome();
|
const testEnv = withIsolatedTestHome();
|
||||||
afterAll(() => testEnv.cleanup());
|
afterAll(() => {
|
||||||
|
testEnv.cleanup();
|
||||||
|
cleanupWarningFilter();
|
||||||
|
});
|
||||||
const pickSendFn = (id: ChannelId, deps?: OutboundSendDeps) => {
|
const pickSendFn = (id: ChannelId, deps?: OutboundSendDeps) => {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case "discord":
|
case "discord":
|
||||||
|
|||||||
@ -11,6 +11,9 @@ const localWorkers = Math.max(4, Math.min(16, os.cpus().length));
|
|||||||
// Cap CI workers: Windows/macOS get 2 (flaky worker crashes), Linux gets 3
|
// Cap CI workers: Windows/macOS get 2 (flaky worker crashes), Linux gets 3
|
||||||
const ciWorkers = isWindows || isMacOS ? 2 : 3;
|
const ciWorkers = isWindows || isMacOS ? 2 : 3;
|
||||||
|
|
||||||
|
// macOS CI needs longer teardown for native module cleanup (sqlite, chokidar)
|
||||||
|
const macOSCI = isCI && isMacOS;
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
@ -20,6 +23,8 @@ export default defineConfig({
|
|||||||
test: {
|
test: {
|
||||||
testTimeout: 120_000,
|
testTimeout: 120_000,
|
||||||
hookTimeout: isWindows ? 180_000 : 120_000,
|
hookTimeout: isWindows ? 180_000 : 120_000,
|
||||||
|
// Longer teardown on macOS CI for native module cleanup (node:sqlite, etc.)
|
||||||
|
teardownTimeout: macOSCI ? 30_000 : 10_000,
|
||||||
pool: "forks",
|
pool: "forks",
|
||||||
maxWorkers: isCI ? ciWorkers : localWorkers,
|
maxWorkers: isCI ? ciWorkers : localWorkers,
|
||||||
include: [
|
include: [
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user