test: split contract vitest shards

This commit is contained in:
Peter Steinberger
2026-04-21 02:54:47 +01:00
parent 525e66e513
commit 8d747d20b8
16 changed files with 233 additions and 64 deletions

View File

@@ -59,6 +59,28 @@ describe("scripts/test-projects changed-target routing", () => {
]);
});
it("routes contract roots to separate contract shards", () => {
const plans = buildVitestRunPlans([
"src/channels/plugins/contracts/channel-catalog.contract.test.ts",
"src/plugins/contracts/loader.contract.test.ts",
]);
expect(plans).toEqual([
{
config: "test/vitest/vitest.contracts-channel-surface.config.ts",
forwardedArgs: [],
includePatterns: ["src/channels/plugins/contracts/channel-catalog.contract.test.ts"],
watchMode: false,
},
{
config: "test/vitest/vitest.contracts-plugin.config.ts",
forwardedArgs: [],
includePatterns: ["src/plugins/contracts/loader.contract.test.ts"],
watchMode: false,
},
]);
});
it("keeps the broad changed run for shared test helpers", () => {
expect(
resolveChangedTargetArgs(["--changed", "origin/main"], process.cwd(), () => [
@@ -567,7 +589,11 @@ describe("scripts/test-projects full-suite sharding", () => {
"test/vitest/vitest.unit-support.config.ts",
"test/vitest/vitest.boundary.config.ts",
"test/vitest/vitest.tooling.config.ts",
"test/vitest/vitest.contracts.config.ts",
"test/vitest/vitest.contracts-channel-surface.config.ts",
"test/vitest/vitest.contracts-channel-config.config.ts",
"test/vitest/vitest.contracts-channel-registry.config.ts",
"test/vitest/vitest.contracts-channel-session.config.ts",
"test/vitest/vitest.contracts-plugin.config.ts",
"test/vitest/vitest.bundled.config.ts",
"test/vitest/vitest.infra.config.ts",
"test/vitest/vitest.hooks.config.ts",

View File

@@ -5,7 +5,10 @@ import bundledConfig from "./vitest/vitest.bundled.config.ts";
import { createCommandsLightVitestConfig } from "./vitest/vitest.commands-light.config.ts";
import { createCommandsVitestConfig } from "./vitest/vitest.commands.config.ts";
import baseConfig, { rootVitestProjects } from "./vitest/vitest.config.ts";
import { createContractsVitestConfig } from "./vitest/vitest.contracts.config.ts";
import {
createContractsVitestConfig,
pluginContractPatterns,
} from "./vitest/vitest.contracts-shared.ts";
import { createGatewayVitestConfig } from "./vitest/vitest.gateway.config.ts";
import { createPluginSdkLightVitestConfig } from "./vitest/vitest.plugin-sdk-light.config.ts";
import { sharedVitestConfig } from "./vitest/vitest.shared.config.ts";
@@ -31,18 +34,18 @@ describe("projects vitest config", () => {
expect(createCommandsVitestConfig().test.pool).toBe("threads");
expect(createPluginSdkLightVitestConfig().test.pool).toBe("threads");
expect(createUnitFastVitestConfig().test.pool).toBe("threads");
expect(createContractsVitestConfig().test.pool).toBe("forks");
expect(createContractsVitestConfig(pluginContractPatterns).test.pool).toBe("forks");
});
it("keeps the contracts lane on the non-isolated fork runner by default", () => {
const config = createContractsVitestConfig();
it("keeps contract shards on the non-isolated fork runner by default", () => {
const config = createContractsVitestConfig(pluginContractPatterns);
expect(config.test.pool).toBe("forks");
expect(config.test.isolate).toBe(false);
expect(normalizeConfigPath(config.test.runner)).toBe("test/non-isolated-runner.ts");
});
it("narrows the contracts lane to targeted contract files", () => {
const config = createContractsVitestConfig({}, [
const config = createContractsVitestConfig(pluginContractPatterns, {}, [
"node",
"vitest",
"run",

View File

@@ -13,7 +13,11 @@ export const rootVitestProjects = [
"test/vitest/vitest.unit.config.ts",
"test/vitest/vitest.infra.config.ts",
"test/vitest/vitest.boundary.config.ts",
"test/vitest/vitest.contracts.config.ts",
"test/vitest/vitest.contracts-channel-surface.config.ts",
"test/vitest/vitest.contracts-channel-config.config.ts",
"test/vitest/vitest.contracts-channel-registry.config.ts",
"test/vitest/vitest.contracts-channel-session.config.ts",
"test/vitest/vitest.contracts-plugin.config.ts",
"test/vitest/vitest.bundled.config.ts",
"test/vitest/vitest.gateway-core.config.ts",
"test/vitest/vitest.gateway-client.config.ts",

View File

@@ -0,0 +1,6 @@
import {
channelConfigContractPatterns,
createContractsVitestConfig,
} from "./vitest.contracts-shared.ts";
export default createContractsVitestConfig(channelConfigContractPatterns);

View File

@@ -0,0 +1,6 @@
import {
channelRegistryContractPatterns,
createContractsVitestConfig,
} from "./vitest.contracts-shared.ts";
export default createContractsVitestConfig(channelRegistryContractPatterns);

View File

@@ -0,0 +1,6 @@
import {
channelSessionContractPatterns,
createContractsVitestConfig,
} from "./vitest.contracts-shared.ts";
export default createContractsVitestConfig(channelSessionContractPatterns);

View File

@@ -0,0 +1,6 @@
import {
channelSurfaceContractPatterns,
createContractsVitestConfig,
} from "./vitest.contracts-shared.ts";
export default createContractsVitestConfig(channelSurfaceContractPatterns);

View File

@@ -0,0 +1,3 @@
import { createContractsVitestConfig, pluginContractPatterns } from "./vitest.contracts-shared.ts";
export default createContractsVitestConfig(pluginContractPatterns);

View File

@@ -0,0 +1,69 @@
import { defineConfig } from "vitest/config";
import { loadPatternListFromEnv, narrowIncludePatternsForCli } from "./vitest.pattern-file.ts";
import { nonIsolatedRunnerPath, sharedVitestConfig } from "./vitest.shared.config.ts";
const base = sharedVitestConfig as Record<string, unknown>;
const baseTest = sharedVitestConfig.test ?? {};
export const channelSurfaceContractPatterns = [
"src/channels/plugins/contracts/channel-catalog.contract.test.ts",
"src/channels/plugins/contracts/channel-import-guardrails.test.ts",
"src/channels/plugins/contracts/group-policy.fallback.contract.test.ts",
"src/channels/plugins/contracts/outbound-payload.contract.test.ts",
"src/channels/plugins/contracts/*-shard-a.contract.test.ts",
"src/channels/plugins/contracts/*-shard-e.contract.test.ts",
];
export const channelConfigContractPatterns = [
"src/channels/plugins/contracts/plugins-core.authorize-config-write.policy.contract.test.ts",
"src/channels/plugins/contracts/plugins-core.authorize-config-write.targets.contract.test.ts",
"src/channels/plugins/contracts/plugins-core.catalog.entries.contract.test.ts",
"src/channels/plugins/contracts/*-shard-b.contract.test.ts",
"src/channels/plugins/contracts/*-shard-f.contract.test.ts",
];
export const channelRegistryContractPatterns = [
"src/channels/plugins/contracts/plugins-core.catalog.paths.contract.test.ts",
"src/channels/plugins/contracts/plugins-core.loader.contract.test.ts",
"src/channels/plugins/contracts/plugins-core.registry.contract.test.ts",
"src/channels/plugins/contracts/*-shard-c.contract.test.ts",
"src/channels/plugins/contracts/*-shard-g.contract.test.ts",
];
export const channelSessionContractPatterns = [
"src/channels/plugins/contracts/plugins-core.resolve-config-writes.contract.test.ts",
"src/channels/plugins/contracts/registry.contract.test.ts",
"src/channels/plugins/contracts/session-binding.registry-backed.contract.test.ts",
"src/channels/plugins/contracts/*-shard-d.contract.test.ts",
"src/channels/plugins/contracts/*-shard-h.contract.test.ts",
];
export const pluginContractPatterns = ["src/plugins/contracts/**/*.test.ts"];
export function loadContractsIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createContractsVitestConfig(
includePatterns: string[],
env: Record<string, string | undefined> = process.env,
argv: string[] = process.argv,
) {
const cliIncludePatterns = narrowIncludePatternsForCli(includePatterns, argv);
return defineConfig({
...base,
test: {
...baseTest,
isolate: false,
// Contract shards intentionally run non-isolated and load broad registries.
// Use forks so full-suite parallel runs do not hit worker-thread heap limits.
pool: "forks",
runner: nonIsolatedRunnerPath,
setupFiles: baseTest.setupFiles ?? [],
include: loadContractsIncludePatternsFromEnv(env) ?? cliIncludePatterns ?? includePatterns,
passWithNoTests: true,
},
});
}

View File

@@ -1,41 +0,0 @@
import { defineConfig } from "vitest/config";
import { loadPatternListFromEnv, narrowIncludePatternsForCli } from "./vitest.pattern-file.ts";
import { nonIsolatedRunnerPath, sharedVitestConfig } from "./vitest.shared.config.ts";
const base = sharedVitestConfig as Record<string, unknown>;
const baseTest = sharedVitestConfig.test ?? {};
const contractIncludePatterns = [
"src/channels/plugins/contracts/**/*.test.ts",
"src/plugins/contracts/**/*.test.ts",
];
export function loadContractsIncludePatternsFromEnv(
env: Record<string, string | undefined> = process.env,
): string[] | null {
return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env);
}
export function createContractsVitestConfig(
env: Record<string, string | undefined> = process.env,
argv: string[] = process.argv,
) {
const cliIncludePatterns = narrowIncludePatternsForCli(contractIncludePatterns, argv);
return defineConfig({
...base,
test: {
...baseTest,
isolate: false,
// The contracts shard intentionally runs non-isolated and loads hundreds of
// contract files. Use forks so full-suite parallel runs do not hit
// Vitest worker-thread heap limits.
pool: "forks",
runner: nonIsolatedRunnerPath,
setupFiles: baseTest.setupFiles ?? [],
include:
loadContractsIncludePatternsFromEnv(env) ?? cliIncludePatterns ?? contractIncludePatterns,
passWithNoTests: true,
},
});
}
export default createContractsVitestConfig();

View File

@@ -134,7 +134,12 @@ export const sharedVitestConfig = {
"test/vitest/vitest.bundled.config.ts",
"test/vitest/vitest.cli.config.ts",
"vitest.config.ts",
"test/vitest/vitest.contracts.config.ts",
"test/vitest/vitest.contracts-shared.ts",
"test/vitest/vitest.contracts-channel-surface.config.ts",
"test/vitest/vitest.contracts-channel-config.config.ts",
"test/vitest/vitest.contracts-channel-registry.config.ts",
"test/vitest/vitest.contracts-channel-session.config.ts",
"test/vitest/vitest.contracts-plugin.config.ts",
"test/vitest/vitest.cron.config.ts",
"test/vitest/vitest.daemon.config.ts",
"test/vitest/vitest.e2e.config.ts",

View File

@@ -40,7 +40,13 @@ export const fullSuiteVitestShards = [
{
config: "test/vitest/vitest.full-core-contracts.config.ts",
name: "core-contracts",
projects: ["test/vitest/vitest.contracts.config.ts"],
projects: [
"test/vitest/vitest.contracts-channel-surface.config.ts",
"test/vitest/vitest.contracts-channel-config.config.ts",
"test/vitest/vitest.contracts-channel-registry.config.ts",
"test/vitest/vitest.contracts-channel-session.config.ts",
"test/vitest/vitest.contracts-plugin.config.ts",
],
},
{
config: "test/vitest/vitest.full-core-bundled.config.ts",