mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 14:01:24 +08:00
ci(release): apply exact extension batch excludes
This commit is contained in:
@@ -70,7 +70,9 @@ function isPathInsideRepo(relativePath) {
|
||||
}
|
||||
|
||||
function isSkippedTrackedTestFile(relativePath) {
|
||||
return relativePath.split("/").some((segment) => segment === "dist" || segment === "node_modules");
|
||||
return relativePath
|
||||
.split("/")
|
||||
.some((segment) => segment === "dist" || segment === "node_modules");
|
||||
}
|
||||
|
||||
function listTrackedTestFiles(rootPath) {
|
||||
@@ -99,6 +101,18 @@ function listTrackedTestFiles(rootPath) {
|
||||
);
|
||||
}
|
||||
|
||||
export function listTrackedTestFilesForRoots(roots) {
|
||||
const files = [];
|
||||
for (const root of roots) {
|
||||
const trackedFiles = listTrackedTestFiles(path.join(repoRoot, root));
|
||||
if (!trackedFiles) {
|
||||
return null;
|
||||
}
|
||||
files.push(...trackedFiles);
|
||||
}
|
||||
return [...new Set(files)].toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
function countTestFiles(rootPath) {
|
||||
const trackedFiles = listTrackedTestFiles(rootPath);
|
||||
if (trackedFiles) {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import path from "node:path";
|
||||
import { resolveExtensionBatchPlan } from "./lib/extension-test-plan.mjs";
|
||||
import {
|
||||
listTrackedTestFilesForRoots,
|
||||
resolveExtensionBatchPlan,
|
||||
} from "./lib/extension-test-plan.mjs";
|
||||
import { isDirectScriptRun, runVitestBatch } from "./lib/vitest-batch-runner.mjs";
|
||||
|
||||
const FS_MODULE_CACHE_PATH_ENV_KEY = "OPENCLAW_VITEST_FS_MODULE_CACHE_PATH";
|
||||
@@ -87,9 +90,62 @@ function orderPlanGroups(planGroups, parallelism) {
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeRelativePath(inputPath) {
|
||||
return path
|
||||
.relative(process.cwd(), path.resolve(process.cwd(), inputPath))
|
||||
.split(path.sep)
|
||||
.join("/");
|
||||
}
|
||||
|
||||
function isExactExcludePath(inputPath) {
|
||||
return !/[*!?[\]{}]/u.test(inputPath);
|
||||
}
|
||||
|
||||
export function parseExactVitestExcludePaths(vitestArgs) {
|
||||
const excludePaths = new Set();
|
||||
for (let index = 0; index < vitestArgs.length; index += 1) {
|
||||
const arg = vitestArgs[index];
|
||||
if (arg === "--exclude") {
|
||||
const value = vitestArgs[index + 1];
|
||||
if (value && isExactExcludePath(value)) {
|
||||
excludePaths.add(normalizeRelativePath(value));
|
||||
}
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
const prefix = "--exclude=";
|
||||
if (arg.startsWith(prefix)) {
|
||||
const value = arg.slice(prefix.length);
|
||||
if (value && isExactExcludePath(value)) {
|
||||
excludePaths.add(normalizeRelativePath(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return excludePaths;
|
||||
}
|
||||
|
||||
function resolveGroupTargets(group, exactExcludePaths) {
|
||||
if (exactExcludePaths.size === 0) {
|
||||
return group.roots;
|
||||
}
|
||||
|
||||
const testFiles = listTrackedTestFilesForRoots(group.roots);
|
||||
if (!testFiles) {
|
||||
return group.roots;
|
||||
}
|
||||
|
||||
return testFiles.filter((file) => !exactExcludePaths.has(file));
|
||||
}
|
||||
|
||||
async function runPlanGroup(group, params) {
|
||||
const targets = resolveGroupTargets(group, params.exactExcludePaths);
|
||||
if (targets.length === 0) {
|
||||
console.log(`[test-extension-batch] ${group.config}: no test files remain after excludes`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[test-extension-batch] ${group.config}: ${group.extensionIds.join(", ")} (${group.testFileCount} files)`,
|
||||
`[test-extension-batch] ${group.config}: ${group.extensionIds.join(", ")} (${targets.length} targets)`,
|
||||
);
|
||||
return await params.runGroup({
|
||||
args: params.vitestArgs,
|
||||
@@ -100,13 +156,14 @@ async function runPlanGroup(group, params) {
|
||||
groupIndex: params.groupIndex,
|
||||
useDedicatedCache: params.useDedicatedCache,
|
||||
}),
|
||||
targets: group.roots,
|
||||
targets,
|
||||
});
|
||||
}
|
||||
|
||||
export async function runExtensionBatchPlan(batchPlan, params = {}) {
|
||||
const env = params.env ?? process.env;
|
||||
const vitestArgs = params.vitestArgs ?? [];
|
||||
const exactExcludePaths = parseExactVitestExcludePaths(vitestArgs);
|
||||
const runGroup = params.runGroup ?? runVitestBatch;
|
||||
const parallelism = resolveExtensionBatchParallelism(batchPlan.planGroups.length, env);
|
||||
const orderedGroups = orderPlanGroups(batchPlan.planGroups, parallelism);
|
||||
@@ -130,6 +187,7 @@ export async function runExtensionBatchPlan(batchPlan, params = {}) {
|
||||
env,
|
||||
groupIndex,
|
||||
runGroup,
|
||||
exactExcludePaths,
|
||||
useDedicatedCache,
|
||||
vitestArgs,
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import { buildVitestBatchPnpmArgs } from "../../scripts/lib/vitest-batch-runner.mjs";
|
||||
import {
|
||||
parseExtensionIds,
|
||||
parseExactVitestExcludePaths,
|
||||
resolveExtensionBatchParallelism,
|
||||
runExtensionBatchPlan,
|
||||
} from "../../scripts/test-extension-batch.mjs";
|
||||
@@ -626,6 +627,46 @@ describe("scripts/test-extension.mjs", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("expands extension batch roots before applying exact Vitest excludes", async () => {
|
||||
const runGroup = vi.fn<() => Promise<number>>().mockResolvedValue(0);
|
||||
await runExtensionBatchPlan(
|
||||
{
|
||||
extensionCount: 1,
|
||||
extensionIds: ["codex"],
|
||||
estimatedCost: 1,
|
||||
hasTests: true,
|
||||
planGroups: [
|
||||
{
|
||||
config: "test/vitest/vitest.extensions.config.ts",
|
||||
estimatedCost: 1,
|
||||
extensionIds: ["codex"],
|
||||
roots: [bundledPluginRoot("codex")],
|
||||
testFileCount: 1,
|
||||
},
|
||||
],
|
||||
testFileCount: 1,
|
||||
},
|
||||
{
|
||||
runGroup,
|
||||
vitestArgs: ["--exclude", "extensions/codex/src/app-server/run-attempt.test.ts"],
|
||||
},
|
||||
);
|
||||
|
||||
const runParams = requireFirstMockArg<RunGroupParams>(runGroup);
|
||||
expect(runParams.targets).not.toContain("extensions/codex/src/app-server/run-attempt.test.ts");
|
||||
expect(runParams.targets).toContain("extensions/codex/src/app-server/client.test.ts");
|
||||
});
|
||||
|
||||
it("detects exact Vitest excludes in extension batch args", () => {
|
||||
expect([
|
||||
...parseExactVitestExcludePaths([
|
||||
"--exclude",
|
||||
"extensions/codex/src/app-server/run-attempt.test.ts",
|
||||
]),
|
||||
]).toEqual(["extensions/codex/src/app-server/run-attempt.test.ts"]);
|
||||
expect([...parseExactVitestExcludePaths(["--exclude=extensions/**/*.test.ts"])]).toEqual([]);
|
||||
});
|
||||
|
||||
it("treats extensions without tests as a no-op by default", () => {
|
||||
const extensionId = findExtensionWithoutTests();
|
||||
const stdout = runScript([extensionId]);
|
||||
|
||||
Reference in New Issue
Block a user