fix(test): bound direct gateway server runs (#119184)

This commit is contained in:
Peter Steinberger
2026-08-04 03:38:39 -07:00
committed by GitHub
parent 121c6c1042
commit b5d41f9005
12 changed files with 339 additions and 169 deletions
+7 -34
View File
@@ -5,6 +5,10 @@ import {
embeddedAgentVitestProjectOwners,
} from "../../test/vitest/vitest.agents-paths.mjs";
import { commandsLightTestFiles } from "../../test/vitest/vitest.commands-light-paths.mjs";
import {
isGatewayServerBackedHttpTestFile,
isGatewayServerTestFile,
} from "../../test/vitest/vitest.gateway-server-paths.mjs";
import { fullSuiteVitestShards } from "../../test/vitest/vitest.test-shards.mjs";
import { toolingIsolatedTestFiles } from "../../test/vitest/vitest.tooling-isolated-paths.mjs";
import {
@@ -612,29 +616,6 @@ function createAgentCoreSplitShards() {
];
}
const GATEWAY_SERVER_BACKED_HTTP_TESTS = new Set([
"src/gateway/embeddings-http.test.ts",
"src/gateway/models-http.test.ts",
"src/gateway/openai-http.test.ts",
"src/gateway/openresponses-http.test.ts",
"src/gateway/probe.auth.integration.test.ts",
]);
const GATEWAY_SERVER_EXCLUDED_TESTS = new Set([
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
]);
function isGatewayServerTestFile(file) {
return (
file.startsWith("src/gateway/") &&
!file.startsWith("src/gateway/server-methods/") &&
!GATEWAY_SERVER_EXCLUDED_TESTS.has(file) &&
(file.includes("server") || GATEWAY_SERVER_BACKED_HTTP_TESTS.has(file))
);
}
function resolveGatewayStartupShardName(file) {
const name = relative("src/gateway", file).replaceAll("\\", "/");
if (name.startsWith("server-startup-config") || name.startsWith("server-startup-early")) {
@@ -643,9 +624,7 @@ function resolveGatewayStartupShardName(file) {
if (
name.startsWith("server-runtime") ||
name.startsWith("server.health") ||
name.startsWith("server.lazy") ||
name.startsWith("server/health-state") ||
name.startsWith("server/readiness")
name.startsWith("server.lazy")
) {
return "agentic-control-plane-startup-health-runtime";
}
@@ -658,7 +637,7 @@ function resolveGatewayStartupShardName(file) {
function resolveGatewayServerShardName(file) {
const name = relative("src/gateway", file).replaceAll("\\", "/");
if (
GATEWAY_SERVER_BACKED_HTTP_TESTS.has(file) ||
isGatewayServerBackedHttpTestFile(file) ||
name.startsWith("server.models") ||
name.startsWith("server.talk")
) {
@@ -688,8 +667,6 @@ function resolveGatewayServerShardName(file) {
name.startsWith("server-runtime") ||
name.startsWith("server.lazy") ||
name.startsWith("server.health") ||
name.startsWith("server/health-state") ||
name.startsWith("server/readiness") ||
name === "server-close.test.ts"
) {
return resolveGatewayStartupShardName(file);
@@ -725,10 +702,7 @@ function resolveGatewayServerShardName(file) {
) {
return "agentic-control-plane-runtime-ui-tools";
}
if (name.startsWith("server/")) {
return "agentic-control-plane-runtime-events";
}
if (name.startsWith("server.") || name.startsWith("server/")) {
if (name.startsWith("server.")) {
return "agentic-control-plane-runtime-state";
}
return "agentic-control-plane-runtime";
@@ -748,7 +722,6 @@ function createGatewayServerSplitShards() {
"agentic-control-plane-runtime",
"agentic-control-plane-runtime-config",
"agentic-control-plane-runtime-cron",
"agentic-control-plane-runtime-events",
"agentic-control-plane-runtime-network",
"agentic-control-plane-runtime-server",
"agentic-control-plane-runtime-shared-token",
@@ -0,0 +1,4 @@
export const GATEWAY_SERVER_TEST_PROCESS_COUNT: 4;
export function listGatewayServerTestTargets(cwd?: string): string[];
export function splitTestTargetChunks(targets: string[], chunkCount: number): string[][];
export function createGatewayServerTestTargetChunks(cwd?: string): string[][];
+72
View File
@@ -0,0 +1,72 @@
// Bounds the non-isolated Gateway server project before its shared module graph
// reaches the V8 worker heap limit.
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { isGatewayServerTestFile } from "../../test/vitest/vitest.gateway-server-paths.mjs";
export const GATEWAY_SERVER_TEST_PROCESS_COUNT = 4;
function normalizePath(value) {
return value.replaceAll("\\", "/");
}
function listRepoFilesRecursive(root, cwd) {
const entries = fs.readdirSync(root, { withFileTypes: true });
return entries.flatMap((entry) => {
const absolute = path.join(root, entry.name);
if (entry.isDirectory()) {
return listRepoFilesRecursive(absolute, cwd);
}
return entry.isFile() ? [normalizePath(path.relative(cwd, absolute))] : [];
});
}
function listGatewayFilesFromGit(cwd) {
const result = spawnSync("git", ["ls-files", "--", "src/gateway"], {
cwd,
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
});
if (result.status !== 0) {
return null;
}
return result.stdout
.split("\n")
.map((line) => normalizePath(line.trim()))
.filter((line) => line.length > 0);
}
export function listGatewayServerTestTargets(cwd = process.cwd()) {
const gatewayDir = path.join(cwd, "src/gateway");
if (!fs.existsSync(gatewayDir)) {
return [];
}
return (listGatewayFilesFromGit(cwd) ?? listRepoFilesRecursive(gatewayDir, cwd))
.filter(isGatewayServerTestFile)
.toSorted((a, b) => a.localeCompare(b));
}
export function splitTestTargetChunks(targets, chunkCount) {
if (targets.length === 0) {
return [];
}
const normalizedChunkCount = Math.min(chunkCount, targets.length);
const baseSize = Math.floor(targets.length / normalizedChunkCount);
const remainder = targets.length % normalizedChunkCount;
const chunks = [];
let offset = 0;
for (let index = 0; index < normalizedChunkCount; index += 1) {
const chunkSize = baseSize + (index < remainder ? 1 : 0);
chunks.push(targets.slice(offset, offset + chunkSize));
offset += chunkSize;
}
return chunks;
}
export function createGatewayServerTestTargetChunks(cwd = process.cwd()) {
return splitTestTargetChunks(
listGatewayServerTestTargets(cwd),
GATEWAY_SERVER_TEST_PROCESS_COUNT,
);
}
+8
View File
@@ -41,6 +41,14 @@ export function resolveMissingExplicitTestFiles(
fsImpl?: VitestFs,
): string[];
export function resolveImplicitVitestArgs(argv: string[], cwd?: string): string[];
export function resolveBoundedVitestInvocations(
argv: string[],
options?: {
cwd?: string;
env?: NodeJS.ProcessEnv;
gatewayServerTargetChunks?: string[][];
},
): string[][];
export function installVitestNoOutputWatchdog(params: {
streams?: Array<{ on(event: string, listener: (...args: unknown[]) => void): unknown } | null>;
timeoutMs: number | null;
+93 -20
View File
@@ -9,6 +9,7 @@ import { toolingIsolatedTestFiles } from "../test/vitest/vitest.tooling-isolated
import { isUiTestTarget } from "../test/vitest/vitest.ui-paths.mjs";
import { boundaryTestFiles } from "../test/vitest/vitest.unit-paths.mjs";
import { runWithFailedTrailer, writeFailedTrailer } from "./lib/failed-trailer.mjs";
import { createGatewayServerTestTargetChunks } from "./lib/gateway-server-test-plan.mjs";
import { signalExitCode } from "./lib/managed-child-process.mjs";
import { resolveRepoRoot } from "./lib/repo-root.mjs";
import { resolveLocalVitestEnv } from "./lib/vitest-local-scheduling.mjs";
@@ -126,6 +127,16 @@ const VITEST_DOTTED_OPTIONS_WITH_VALUE_PREFIXES = [
"--sequence.",
"--typecheck.",
];
const UNBOUNDED_CONFIG_ONLY_OPTIONS = [
"--changed",
"--coverage",
"--dir",
"--mergeReports",
"--outputFile",
"--project",
"--root",
"--shard",
];
const require = createRequire(import.meta.url);
const repoRoot = resolveRepoRoot(import.meta.url);
const testProjectsRunnerPath = path.join(repoRoot, "scripts", "test-projects.mjs");
@@ -427,15 +438,66 @@ function resolveVitestConfigArg(argv) {
}
function resolveVitestConfigNoOutputTimeoutMs(config) {
const normalized = path.normalize(config).replaceAll(path.sep, "/").replace(/^\.\//u, "");
const normalized = normalizeVitestConfigPath(config);
for (const [candidate, timeoutMs] of VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS) {
if (normalized === candidate || normalized.endsWith(`/${candidate}`)) {
if (matchesVitestConfigPath(normalized, candidate)) {
return timeoutMs;
}
}
return null;
}
function normalizeVitestConfigPath(config) {
return path.normalize(config).replaceAll(path.sep, "/").replace(/^\.\//u, "");
}
function matchesVitestConfigPath(normalized, candidate) {
return normalized === candidate || normalized.endsWith("/" + candidate);
}
function hasVitestOption(argv, option) {
for (const arg of argv) {
if (arg === "--") {
return false;
}
if (arg === option || arg.startsWith(option + "=") || arg.startsWith(option + ".")) {
return true;
}
}
return false;
}
function insertVitestTargets(argv, targets) {
const separatorIndex = argv.indexOf("--");
const insertionIndex = separatorIndex < 0 ? argv.length : separatorIndex;
return [...argv.slice(0, insertionIndex), ...targets, ...argv.slice(insertionIndex)];
}
/**
* Splits config-only Gateway server runs into fresh processes before the
* non-isolated module graph reaches the worker heap limit.
*/
export function resolveBoundedVitestInvocations(argv, options = {}) {
const config = resolveVitestConfigArg(argv);
const normalizedConfig = config === null ? "" : normalizeVitestConfigPath(config);
const env = options.env ?? process.env;
const cwd = options.cwd ?? process.cwd();
const mode = resolveExplicitVitestMode(argv);
if (
!matchesVitestConfigPath(normalizedConfig, GATEWAY_SERVER_VITEST_CONFIG) ||
mode === "watch" ||
(mode !== "run" && !isTruthyEnvValue(env.CI)) ||
hasNonRunVitestSubcommand(argv) ||
hasAlternateVitestRootArg(argv) ||
collectExplicitProjectRouterTargetArgs(argv, cwd).length > 0 ||
UNBOUNDED_CONFIG_ONLY_OPTIONS.some((option) => hasVitestOption(argv, option))
) {
return [argv];
}
const chunks = options.gatewayServerTargetChunks ?? createGatewayServerTestTargetChunks(cwd);
return chunks.length > 1 ? chunks.map((targets) => insertVitestTargets(argv, targets)) : [argv];
}
/**
* Builds spawn options for the primary Vitest child process.
*/
@@ -1115,9 +1177,11 @@ async function finishVitestProcess({ completion, getForwardedSignal }) {
if (exitSignal) {
writeFailedTrailer("vitest", signalExitCode(exitSignal));
process.kill(process.pid, exitSignal);
return;
return signalExitCode(exitSignal);
}
process.exitCode = code ?? 1;
const exitCode = code ?? 1;
process.exitCode = exitCode;
return exitCode;
}
async function main(argv = process.argv.slice(2), env = process.env) {
@@ -1146,8 +1210,7 @@ async function main(argv = process.argv.slice(2), env = process.env) {
}
const vitestArgs = resolveImplicitVitestArgs(argv);
const guardedVitestArgs = resolveExplicitTestFileNoPassArgs(vitestArgs);
const spawnEnv = resolveRunVitestSpawnEnv(env, guardedVitestArgs);
const invocations = resolveBoundedVitestInvocations(vitestArgs, { env });
let vitestCliEntry;
try {
vitestCliEntry = resolveVitestCliEntry();
@@ -1160,20 +1223,30 @@ async function main(argv = process.argv.slice(2), env = process.env) {
throw error;
}
await finishVitestProcess(
spawnWatchedVitestProcess({
pnpmArgs: [
"exec",
"node",
...resolveVitestNodeArgs(env),
vitestCliEntry,
...guardedVitestArgs,
],
spawnParams: resolveVitestSpawnParams(spawnEnv),
env: spawnEnv,
label: guardedVitestArgs.join(" "),
}),
);
for (let index = 0; index < invocations.length; index += 1) {
const guardedVitestArgs = resolveExplicitTestFileNoPassArgs(invocations[index]);
const spawnEnv = resolveRunVitestSpawnEnv(env, guardedVitestArgs);
if (invocations.length > 1) {
console.error("[vitest] Gateway server process " + (index + 1) + "/" + invocations.length);
}
const exitCode = await finishVitestProcess(
spawnWatchedVitestProcess({
pnpmArgs: [
"exec",
"node",
...resolveVitestNodeArgs(env),
vitestCliEntry,
...guardedVitestArgs,
],
spawnParams: resolveVitestSpawnParams(spawnEnv),
env: spawnEnv,
label: guardedVitestArgs.join(" "),
}),
);
if (exitCode !== 0) {
return;
}
}
}
if (import.meta.main) {
+7 -72
View File
@@ -86,6 +86,11 @@ import {
} from "./changed-lanes.mjs";
import { getChangedPathFacts } from "./lib/changed-path-facts.mjs";
import { createExtensionTestProcessTargetChunks } from "./lib/extension-test-plan.mjs";
import {
GATEWAY_SERVER_TEST_PROCESS_COUNT,
listGatewayServerTestTargets,
splitTestTargetChunks as splitTargetChunks,
} from "./lib/gateway-server-test-plan.mjs";
import { isCiLikeEnv, resolveLocalFullSuiteProfile } from "./lib/vitest-local-scheduling.mjs";
import {
DEFAULT_VITEST_NO_OUTPUT_HEARTBEAT_MS,
@@ -723,19 +728,6 @@ export function formatNoChangedTestTargetLines(skippedBroadFallbackPaths) {
}
const EXPLICIT_SOURCE_FULL_IMPORT_GRAPH_THRESHOLD = 12;
const GATEWAY_SERVER_FULL_SUITE_TARGET_CHUNK_COUNT = 4;
const GATEWAY_SERVER_BACKED_HTTP_TEST_TARGETS = new Set([
"src/gateway/embeddings-http.test.ts",
"src/gateway/models-http.test.ts",
"src/gateway/openai-http.test.ts",
"src/gateway/openresponses-http.test.ts",
"src/gateway/probe.auth.integration.test.ts",
]);
const GATEWAY_SERVER_EXCLUDED_TEST_TARGETS = new Set([
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
]);
function resolveTestProjectsVitestNoOutputTimeoutMs(config) {
const directRunnerTimeoutMs = resolveDefaultVitestNoOutputTimeoutMs(["run", "--config", config]);
return String(
@@ -776,63 +768,6 @@ function listRepoFilesRecursive(root, cwd) {
});
}
function listGatewayFilesFromGit(cwd) {
const result = spawnSync("git", ["ls-files", "--", "src/gateway"], {
cwd,
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
});
if (result.status !== 0) {
return null;
}
return result.stdout
.split("\n")
.map((line) => normalizePathPattern(line.trim()))
.filter((line) => line.length > 0);
}
function isGatewayServerFullSuiteTarget(relative) {
if (
GATEWAY_SERVER_EXCLUDED_TEST_TARGETS.has(relative) ||
relative.startsWith("src/gateway/server-methods/")
) {
return false;
}
return (
GATEWAY_SERVER_BACKED_HTTP_TEST_TARGETS.has(relative) ||
(relative.startsWith("src/gateway/") &&
path.posix.basename(relative).includes("server") &&
relative.endsWith(".test.ts"))
);
}
function resolveGatewayServerFullSuiteTargets(cwd) {
const gatewayDir = path.join(cwd, "src/gateway");
if (!fs.existsSync(gatewayDir)) {
return [];
}
return (listGatewayFilesFromGit(cwd) ?? listRepoFilesRecursive(gatewayDir, cwd))
.filter(isGatewayServerFullSuiteTarget)
.toSorted((a, b) => a.localeCompare(b));
}
function splitTargetChunks(targets, chunkCount) {
if (targets.length === 0) {
return [];
}
const normalizedChunkCount = Math.min(chunkCount, targets.length);
const baseSize = Math.floor(targets.length / normalizedChunkCount);
const remainder = targets.length % normalizedChunkCount;
const chunks = [];
let offset = 0;
for (let index = 0; index < normalizedChunkCount; index += 1) {
const chunkSize = baseSize + (index < remainder ? 1 : 0);
chunks.push(targets.slice(offset, offset + chunkSize));
offset += chunkSize;
}
return chunks;
}
let cachedBroadScriptTestTargets = null;
let cachedBroadScriptTestTargetsCwd = null;
@@ -3684,8 +3619,8 @@ export function buildFullSuiteVitestRunPlans(args, cwd = process.cwd()) {
chunks = splitTargetChunks(targets, chunkCount);
} else if (config === GATEWAY_SERVER_VITEST_CONFIG) {
chunks = splitTargetChunks(
resolveGatewayServerFullSuiteTargets(cwd),
GATEWAY_SERVER_FULL_SUITE_TARGET_CHUNK_COUNT,
listGatewayServerTestTargets(cwd),
GATEWAY_SERVER_TEST_PROCESS_COUNT,
);
} else if (config === EXTENSION_MATRIX_VITEST_CONFIG) {
chunks = createExtensionTestProcessTargetChunks(
+13 -27
View File
@@ -16,6 +16,8 @@ import {
embeddedAgentVitestProjectOwners,
} from "../vitest/vitest.agents-paths.mjs";
import { commandsLightTestFiles } from "../vitest/vitest.commands-light-paths.mjs";
import { isGatewayServerTestFile } from "../vitest/vitest.gateway-server-paths.mjs";
import { createGatewayServerVitestConfig } from "../vitest/vitest.gateway-server.config.ts";
import { createPluginsVitestConfig } from "../vitest/vitest.plugins.config.ts";
import { createToolingVitestConfig } from "../vitest/vitest.tooling.config.ts";
@@ -33,20 +35,6 @@ const PLUGIN_PRERELEASE_NPM_SPEC_TEST = "src/plugins/install.npm-spec.test.ts";
const PLUGIN_NPM_INSTALL_SECURITY_SCAN_TEST =
"src/plugins/npm-install-security-scan.release.test.ts";
const DEFAULT_NODE_TEST_RUNNER = "blacksmith-8vcpu-ubuntu-2404";
const GATEWAY_SERVER_BACKED_HTTP_TESTS = new Set([
"src/gateway/embeddings-http.test.ts",
"src/gateway/models-http.test.ts",
"src/gateway/openai-http.test.ts",
"src/gateway/openresponses-http.test.ts",
"src/gateway/probe.auth.integration.test.ts",
]);
const GATEWAY_SERVER_EXCLUDED_TESTS = new Set([
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
]);
function listTestFiles(rootDir: string): string[] {
const gitFiles = listGitTrackedFiles({ pathspecs: rootDir });
expect(gitFiles).not.toBeNull();
@@ -103,15 +91,6 @@ function listAllToolingTestFiles(): string[] {
}
}
function isGatewayServerTestFile(file: string): boolean {
return (
file.startsWith("src/gateway/") &&
!file.startsWith("src/gateway/server-methods/") &&
!GATEWAY_SERVER_EXCLUDED_TESTS.has(file) &&
(file.includes("server") || GATEWAY_SERVER_BACKED_HTTP_TESTS.has(file))
);
}
describe("scripts/lib/ci-node-test-plan.mjs", () => {
it("assigns one semantic Vitest cache writer without changing shard order", () => {
const full = createNodeTestShardBundles({ includeReleaseOnlyPluginShards: false });
@@ -850,7 +829,6 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
"agentic-control-plane-runtime",
"agentic-control-plane-runtime-config",
"agentic-control-plane-runtime-cron",
"agentic-control-plane-runtime-events",
"agentic-control-plane-runtime-network",
"agentic-control-plane-runtime-server",
"agentic-control-plane-runtime-shared-token",
@@ -880,9 +858,17 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
const controlPlaneShardFiles = controlPlaneShards
.flatMap((shard) => shard.includePatterns ?? [])
.toSorted((a, b) => a.localeCompare(b));
const expectedControlPlaneFiles = listTestFiles("src/gateway")
.filter(isGatewayServerTestFile)
.toSorted((a, b) => a.localeCompare(b));
const expectedControlPlaneFiles = listMatchedTestFiles(
createGatewayServerVitestConfig({
...process.env,
OPENCLAW_VITEST_INCLUDE_FILE: undefined,
}),
);
expect(
listTestFiles("src/gateway")
.filter(isGatewayServerTestFile)
.toSorted((a, b) => a.localeCompare(b)),
).toEqual(expectedControlPlaneFiles);
expect(controlPlaneShardFiles).toEqual(expectedControlPlaneFiles);
expect(new Set(controlPlaneShardFiles).size).toBe(controlPlaneShardFiles.length);
expect(cliShard).toEqual({
+85
View File
@@ -13,6 +13,7 @@ import {
TOOLING_EXCLUDED_TESTS,
VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS,
installVitestNoOutputWatchdog,
resolveBoundedVitestInvocations,
resolveDefaultVitestNoOutputTimeoutMs,
resolveDirectNodeVitestArgs,
resolveExplicitTestFileNoPassArgs,
@@ -194,6 +195,90 @@ describe("scripts/run-vitest", () => {
).toEqual(["extensions/linux-canvas", "src/node-host", "--isolate", "--", "--no-isolate"]);
});
it("bounds config-only Gateway server runs in fresh worker processes", () => {
const argv = [
"run",
"--config",
"test/vitest/vitest.gateway-server.config.ts",
"--reporter=verbose",
"--",
"-x",
];
expect(
resolveBoundedVitestInvocations(argv, {
env: {},
gatewayServerTargetChunks: [
["src/gateway/server-a.test.ts"],
["src/gateway/server-b.test.ts"],
],
}),
).toEqual([
[
"run",
"--config",
"test/vitest/vitest.gateway-server.config.ts",
"--reporter=verbose",
"src/gateway/server-a.test.ts",
"--",
"-x",
],
[
"run",
"--config",
"test/vitest/vitest.gateway-server.config.ts",
"--reporter=verbose",
"src/gateway/server-b.test.ts",
"--",
"-x",
],
]);
});
it("bounds implicit CI runs for absolute Gateway server config paths", () => {
expect(
resolveBoundedVitestInvocations(
["--config", "/repo/test/vitest/vitest.gateway-server.config.ts"],
{
env: { CI: "1" },
gatewayServerTargetChunks: [
["src/gateway/server-a.test.ts"],
["src/gateway/server-b.test.ts"],
],
},
),
).toHaveLength(2);
});
it.each([
["local watch default", ["--config", "test/vitest/vitest.gateway-server.config.ts"]],
["explicit watch", ["watch", "--config", "test/vitest/vitest.gateway-server.config.ts"]],
[
"explicit target",
[
"run",
"--config",
"test/vitest/vitest.gateway-server.config.ts",
"src/gateway/server-startup.test.ts",
],
],
[
"coverage output",
["run", "--config", "test/vitest/vitest.gateway-server.config.ts", "--coverage"],
],
["different config", ["run", "--config", "test/vitest/vitest.gateway-core.config.ts"]],
])("keeps %s as one direct Vitest invocation", (_label, argv) => {
expect(
resolveBoundedVitestInvocations(argv, {
env: {},
gatewayServerTargetChunks: [
["src/gateway/server-a.test.ts"],
["src/gateway/server-b.test.ts"],
],
}),
).toEqual([argv]);
});
it("routes explicit tooling tests through the tooling config", () => {
expect(resolveImplicitVitestArgs(["run", "test/scripts/run-vitest.test.ts"])).toEqual([
"run",
+1 -1
View File
@@ -4645,7 +4645,7 @@ describe("scripts/test-projects full-suite sharding", () => {
expect(gatewayPlans).toHaveLength(4);
expect(gatewayTargets.length).toBeGreaterThan(90);
expect(new Set(gatewayTargets).size).toBe(gatewayTargets.length);
expect(gatewayTargets).toContain("src/gateway/server-network-runtime.e2e.test.ts");
expect(gatewayTargets).not.toContain("src/gateway/server-network-runtime.e2e.test.ts");
expect(gatewayTargets).not.toContain("src/gateway/gateway.test.ts");
expect(Math.max(...gatewayChunkSizes) - Math.min(...gatewayChunkSizes)).toBeLessThanOrEqual(1);
const agentsCoreTargets = agentsCorePlans.flatMap((plan) => plan.forwardedArgs);
@@ -0,0 +1,4 @@
export const gatewayServerBackedHttpTestFiles: string[];
export const gatewayServerExcludedTestFiles: string[];
export function isGatewayServerBackedHttpTestFile(file: string): boolean;
export function isGatewayServerTestFile(file: string): boolean;
@@ -0,0 +1,39 @@
// Canonical file ownership for the non-isolated Gateway server Vitest project.
export const gatewayServerBackedHttpTestFiles = [
"src/gateway/embeddings-http.test.ts",
"src/gateway/models-http.test.ts",
"src/gateway/openai-http.test.ts",
"src/gateway/openresponses-http.test.ts",
"src/gateway/probe.auth.integration.test.ts",
];
export const gatewayServerExcludedTestFiles = [
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
];
const gatewayServerBackedHttpTestFileSet = new Set(gatewayServerBackedHttpTestFiles);
const gatewayServerExcludedTestFileSet = new Set(gatewayServerExcludedTestFiles);
export function isGatewayServerBackedHttpTestFile(file) {
return gatewayServerBackedHttpTestFileSet.has(file.replaceAll("\\", "/"));
}
export function isGatewayServerTestFile(file) {
const normalized = file.replaceAll("\\", "/");
if (
gatewayServerExcludedTestFileSet.has(normalized) ||
normalized.startsWith("src/gateway/server-methods/") ||
normalized.endsWith(".e2e.test.ts")
) {
return false;
}
const basename = normalized.slice(normalized.lastIndexOf("/") + 1);
return (
isGatewayServerBackedHttpTestFile(normalized) ||
(normalized.startsWith("src/gateway/") &&
basename.includes("server") &&
normalized.endsWith(".test.ts"))
);
}
+6 -15
View File
@@ -1,26 +1,17 @@
import {
gatewayServerBackedHttpTestFiles,
gatewayServerExcludedTestFiles,
} from "./vitest.gateway-server-paths.mjs";
// Vitest gateway server config wires the gateway server test shard.
import { createScopedVitestConfig } from "./vitest.scoped-config.ts";
const gatewayServerBackedHttpTests = [
"src/gateway/embeddings-http.test.ts",
"src/gateway/models-http.test.ts",
"src/gateway/openai-http.test.ts",
"src/gateway/openresponses-http.test.ts",
"src/gateway/probe.auth.integration.test.ts",
];
export function createGatewayServerVitestConfig(env?: Record<string, string | undefined>) {
return createScopedVitestConfig(
["src/gateway/**/*server*.test.ts", ...gatewayServerBackedHttpTests],
["src/gateway/**/*server*.test.ts", ...gatewayServerBackedHttpTestFiles],
{
dir: "src/gateway",
env,
exclude: [
"src/gateway/server-methods/**/*.test.ts",
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
],
exclude: ["src/gateway/server-methods/**/*.test.ts", ...gatewayServerExcludedTestFiles],
fileParallelism: false,
// Gateway child projects share one include file; preserve this project's ownership.
intersectIncludeFile: true,