test: isolate bundled plugin coverage from unit

This commit is contained in:
Peter Steinberger
2026-04-03 10:56:55 +01:00
parent 64755c52f2
commit 55e43cbc7f
21 changed files with 629 additions and 89 deletions

View File

@@ -139,7 +139,7 @@ if (rawCli.showHelp) {
" --plan Print the resolved execution plan and exit",
" --ci-manifest Print the planner-backed CI execution manifest as JSON and exit",
" --explain <file> Explain how a file is classified and run, then exit",
" --surface <name> Select a surface: unit, extensions, channels, contracts, gateway",
" --surface <name> Select a surface: unit, bundled, extensions, channels, contracts, gateway",
" --files <pattern> Add targeted files or path patterns (repeatable)",
" --mode <ci|local> Override runtime mode",
" --profile <name> Override execution intent: normal, max, serial",

View File

@@ -1,7 +1,10 @@
import fs from "node:fs";
import path from "node:path";
import { channelTestPrefixes } from "../../vitest.channel-paths.mjs";
import { isUnitConfigTestFile } from "../../vitest.unit-paths.mjs";
import {
isBundledPluginDependentUnitTestFile,
isUnitConfigTestFile,
} from "../../vitest.unit-paths.mjs";
import {
BUNDLED_PLUGIN_PATH_PREFIX,
BUNDLED_PLUGIN_ROOT_DIR,
@@ -111,7 +114,9 @@ export function loadTestCatalog() {
}
let surface = "base";
if (isUnitConfigTestFile(normalizedFile)) {
if (isBundledPluginDependentUnitTestFile(normalizedFile)) {
surface = "bundled";
} else if (isUnitConfigTestFile(normalizedFile)) {
surface = "unit";
} else if (contractTestPrefixes.some((prefix) => normalizedFile.startsWith(prefix))) {
surface = "contracts";
@@ -206,6 +211,7 @@ export function loadTestCatalog() {
export const testSurfaces = [
"unit",
"bundled",
"extensions",
"channels",
"contracts",

View File

@@ -1,5 +1,9 @@
import path from "node:path";
import { isUnitConfigTestFile } from "../../vitest.unit-paths.mjs";
import {
bundledPluginDependentUnitTestFiles,
isBundledPluginDependentUnitTestFile,
isUnitConfigTestFile,
} from "../../vitest.unit-paths.mjs";
import { BUNDLED_PLUGIN_PATH_PREFIX } from "../lib/bundled-plugin-paths.mjs";
import {
loadChannelTimingManifest,
@@ -112,14 +116,21 @@ const normalizeSurfaces = (values = []) => [
),
];
const EXPLICIT_PLAN_SURFACES = new Set(["unit", "extensions", "channels", "contracts", "gateway"]);
const EXPLICIT_PLAN_SURFACES = new Set([
"unit",
"bundled",
"extensions",
"channels",
"contracts",
"gateway",
]);
const FAILURE_POLICIES = new Set(["fail-fast", "collect-all"]);
const validateExplicitSurfaces = (surfaces) => {
const invalidSurfaces = surfaces.filter((surface) => !EXPLICIT_PLAN_SURFACES.has(surface));
if (invalidSurfaces.length > 0) {
throw new Error(
`Unsupported --surface value(s): ${invalidSurfaces.join(", ")}. Supported surfaces: unit, extensions, channels, contracts, gateway.`,
`Unsupported --surface value(s): ${invalidSurfaces.join(", ")}. Supported surfaces: unit, bundled, extensions, channels, contracts, gateway.`,
);
}
};
@@ -135,6 +146,9 @@ const buildRequestedSurfaces = (request, env) => {
if (!skipDefaultRuns) {
surfaces.push("unit");
}
if (env.OPENCLAW_TEST_INCLUDE_BUNDLED === "1") {
surfaces.push("bundled");
}
if (env.OPENCLAW_TEST_INCLUDE_EXTENSIONS === "1") {
surfaces.push("extensions");
}
@@ -264,6 +278,11 @@ const resolveEntryTimingEstimator = (entry, context) => {
context.unitTimingManifest.files[file]?.durationMs ??
context.unitTimingManifest.defaultDurationMs;
}
if (config === "vitest.bundled.config.ts") {
return (file) =>
context.unitTimingManifest.files[file]?.durationMs ??
context.unitTimingManifest.defaultDurationMs;
}
if (config === "vitest.channels.config.ts") {
return (file) =>
context.channelTimingManifest.files[file]?.durationMs ??
@@ -348,6 +367,9 @@ const resolveMaxWorkersForUnit = (unit, context) => {
if (unit.surface === "extensions") {
return budget.extensionWorkers;
}
if (unit.surface === "bundled") {
return budget.unitSharedWorkers;
}
if (unit.surface === "channels") {
return budget.channelSharedWorkers ?? budget.unitSharedWorkers;
}
@@ -392,6 +414,11 @@ const withIncludeFileEnv = (context, unitId, files) => ({
OPENCLAW_VITEST_INCLUDE_FILE: context.writeTempJsonArtifact(unitId, files),
});
const withBundledPluginsDisabled = (unitEnv) => ({
...unitEnv,
OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1",
});
const resolveUnitHeavyFileGroups = (context) => {
const { env, runtime, executionBudget, catalog, unitTimingManifest, unitMemoryHotspotManifest } =
context;
@@ -509,6 +536,7 @@ const buildDefaultUnits = (context, request) => {
const selectedSurfaces = buildRequestedSurfaces(request, env);
const selectedSurfaceSet = new Set(selectedSurfaces);
const unitOnlyRun = selectedSurfaceSet.size === 1 && selectedSurfaceSet.has("unit");
const bundledOnlyRun = selectedSurfaceSet.size === 1 && selectedSurfaceSet.has("bundled");
const channelsOnlyRun = selectedSurfaceSet.size === 1 && selectedSurfaceSet.has("channels");
const contractsOnlyRun = selectedSurfaceSet.size === 1 && selectedSurfaceSet.has("contracts");
const extensionsOnlyRun = selectedSurfaceSet.size === 1 && selectedSurfaceSet.has("extensions");
@@ -631,10 +659,12 @@ const buildDefaultUnits = (context, request) => {
batch,
context,
),
env: withIncludeFileEnv(
context,
`vitest-unit-fast-include-${String(laneIndex + 1)}-${String(batchIndex + 1)}`,
batch,
env: withBundledPluginsDisabled(
withIncludeFileEnv(
context,
`vitest-unit-fast-include-${String(laneIndex + 1)}-${String(batchIndex + 1)}`,
batch,
),
),
args: [
"vitest",
@@ -657,6 +687,7 @@ const buildDefaultUnits = (context, request) => {
surface: "unit",
isolate: true,
estimatedDurationMs: estimateUnitDurationMs(file),
env: withBundledPluginsDisabled(),
args: [
"vitest",
"run",
@@ -683,6 +714,7 @@ const buildDefaultUnits = (context, request) => {
surface: "unit",
isolate: false,
estimatedDurationMs: files.reduce((sum, file) => sum + estimateUnitDurationMs(file), 0),
env: withBundledPluginsDisabled(),
args: [
"vitest",
"run",
@@ -704,6 +736,7 @@ const buildDefaultUnits = (context, request) => {
surface: "unit",
isolate: true,
estimatedDurationMs: estimateUnitDurationMs(file),
env: withBundledPluginsDisabled(),
args: [
"vitest",
"run",
@@ -724,6 +757,7 @@ const buildDefaultUnits = (context, request) => {
id: "unit-pinned",
surface: "unit",
isolate: false,
env: withBundledPluginsDisabled(),
args: [
"vitest",
"run",
@@ -739,6 +773,23 @@ const buildDefaultUnits = (context, request) => {
}
}
if (selectedSurfaceSet.has("bundled")) {
units.push(
createExecutionUnit(context, {
id: "bundled",
surface: "bundled",
isolate: false,
serialPhase: bundledOnlyRun ? undefined : "bundled",
estimatedDurationMs: bundledPluginDependentUnitTestFiles.reduce(
(sum, file) => sum + estimateUnitDurationMs(file),
0,
),
args: ["vitest", "run", "--config", "vitest.bundled.config.ts", ...noIsolateArgs],
reasons: ["bundled-surface"],
}),
);
}
if (selectedSurfaceSet.has("channels")) {
for (const file of catalog.channelIsolatedFiles) {
units.push(
@@ -951,6 +1002,17 @@ const createTargetedUnit = (context, classification, filters) => {
...filters,
];
}
if (owner === "bundled") {
return [
"vitest",
"run",
"--config",
"vitest.bundled.config.ts",
...(classification.isolated ? ["--pool=forks"] : []),
...context.noIsolateArgs,
...filters,
];
}
if (owner === "base-pinned") {
return [
"vitest",
@@ -1040,6 +1102,7 @@ const createTargetedUnit = (context, classification, filters) => {
surface: classification.legacyBasePinned ? "base" : classification.surface,
isolate: classification.isolated || owner === "base-pinned",
args,
env: owner === "unit" ? withBundledPluginsDisabled() : undefined,
reasons: classification.reasons,
});
};
@@ -1250,6 +1313,13 @@ const estimateTopLevelEntryDurationMs = (unit, context) => {
context.unitTimingManifest.defaultDurationMs)
);
}
if (isBundledPluginDependentUnitTestFile(file)) {
return (
totalMs +
(context.unitTimingManifest.files[file]?.durationMs ??
context.unitTimingManifest.defaultDurationMs)
);
}
if (context.catalog.channelTestPrefixes.some((prefix) => file.startsWith(prefix))) {
return (
totalMs +
@@ -1374,6 +1444,12 @@ export function buildCIExecutionManifest(scopeInput = {}, options = {}) {
const checksFastInclude = nodeEligible
? [
{
check_name: "checks-fast-bundled",
runtime: "node",
task: "bundled",
command: "pnpm test:bundled",
},
...createShardMatrixEntries({
checkNamePrefix: "checks-fast-extensions",
runtime: "node",