





















@@ -1,7 +1,10 @@
11#!/usr/bin/env node
2233import path from "node:path";
4-import { resolveExtensionBatchPlan } from "./lib/extension-test-plan.mjs";
4+import {
5+listTrackedTestFilesForRoots,
6+resolveExtensionBatchPlan,
7+} from "./lib/extension-test-plan.mjs";
58import { isDirectScriptRun, runVitestBatch } from "./lib/vitest-batch-runner.mjs";
69710const FS_MODULE_CACHE_PATH_ENV_KEY = "OPENCLAW_VITEST_FS_MODULE_CACHE_PATH";
@@ -87,9 +90,62 @@ function orderPlanGroups(planGroups, parallelism) {
8790});
8891}
899293+function normalizeRelativePath(inputPath) {
94+return path
95+.relative(process.cwd(), path.resolve(process.cwd(), inputPath))
96+.split(path.sep)
97+.join("/");
98+}
99+100+function isExactExcludePath(inputPath) {
101+return !/[*!?[\]{}]/u.test(inputPath);
102+}
103+104+export function parseExactVitestExcludePaths(vitestArgs) {
105+const excludePaths = new Set();
106+for (let index = 0; index < vitestArgs.length; index += 1) {
107+const arg = vitestArgs[index];
108+if (arg === "--exclude") {
109+const value = vitestArgs[index + 1];
110+if (value && isExactExcludePath(value)) {
111+excludePaths.add(normalizeRelativePath(value));
112+}
113+index += 1;
114+continue;
115+}
116+const prefix = "--exclude=";
117+if (arg.startsWith(prefix)) {
118+const value = arg.slice(prefix.length);
119+if (value && isExactExcludePath(value)) {
120+excludePaths.add(normalizeRelativePath(value));
121+}
122+}
123+}
124+return excludePaths;
125+}
126+127+function resolveGroupTargets(group, exactExcludePaths) {
128+if (exactExcludePaths.size === 0) {
129+return group.roots;
130+}
131+132+const testFiles = listTrackedTestFilesForRoots(group.roots);
133+if (!testFiles) {
134+return group.roots;
135+}
136+137+return testFiles.filter((file) => !exactExcludePaths.has(file));
138+}
139+90140async function runPlanGroup(group, params) {
141+const targets = resolveGroupTargets(group, params.exactExcludePaths);
142+if (targets.length === 0) {
143+console.log(`[test-extension-batch] ${group.config}: no test files remain after excludes`);
144+return 0;
145+}
146+91147console.log(
92-`[test-extension-batch] ${group.config}: ${group.extensionIds.join(", ")} (${group.testFileCount} files)`,
148+`[test-extension-batch] ${group.config}: ${group.extensionIds.join(", ")} (${targets.length} targets)`,
93149);
94150return await params.runGroup({
95151args: params.vitestArgs,
@@ -100,13 +156,14 @@ async function runPlanGroup(group, params) {
100156groupIndex: params.groupIndex,
101157useDedicatedCache: params.useDedicatedCache,
102158}),
103-targets: group.roots,
159+ targets,
104160});
105161}
106162107163export async function runExtensionBatchPlan(batchPlan, params = {}) {
108164const env = params.env ?? process.env;
109165const vitestArgs = params.vitestArgs ?? [];
166+const exactExcludePaths = parseExactVitestExcludePaths(vitestArgs);
110167const runGroup = params.runGroup ?? runVitestBatch;
111168const parallelism = resolveExtensionBatchParallelism(batchPlan.planGroups.length, env);
112169const orderedGroups = orderPlanGroups(batchPlan.planGroups, parallelism);
@@ -130,6 +187,7 @@ export async function runExtensionBatchPlan(batchPlan, params = {}) {
130187 env,
131188 groupIndex,
132189 runGroup,
190+ exactExcludePaths,
133191 useDedicatedCache,
134192 vitestArgs,
135193});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。