mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-28 20:46:57 +02:00
254 lines
7.7 KiB
JavaScript
254 lines
7.7 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { spawnPnpmRunner } from "./pnpm-runner.mjs";
|
|
|
|
const LIVE_TEST_SUFFIX = ".live.test.ts";
|
|
|
|
export const RELEASE_LIVE_TEST_SHARDS = Object.freeze([
|
|
"native-live-src-agents",
|
|
"native-live-src-gateway-core",
|
|
"native-live-src-gateway-profiles",
|
|
"native-live-src-gateway-backends",
|
|
"native-live-test",
|
|
"native-live-extensions-a-k",
|
|
"native-live-extensions-l-n",
|
|
"native-live-extensions-openai",
|
|
"native-live-extensions-o-z-other",
|
|
"native-live-extensions-xai",
|
|
"native-live-extensions-media-audio",
|
|
"native-live-extensions-media-music-google",
|
|
"native-live-extensions-media-music-minimax",
|
|
"native-live-extensions-media-video",
|
|
]);
|
|
|
|
export const LIVE_TEST_SHARDS = Object.freeze([
|
|
...RELEASE_LIVE_TEST_SHARDS,
|
|
"native-live-extensions-o-z",
|
|
"native-live-extensions-media",
|
|
"native-live-extensions-media-music",
|
|
]);
|
|
|
|
function walkFiles(rootDir) {
|
|
const files = [];
|
|
if (!fs.existsSync(rootDir)) {
|
|
return files;
|
|
}
|
|
const stack = [rootDir];
|
|
while (stack.length > 0) {
|
|
const current = stack.pop();
|
|
const entries = fs.readdirSync(current, { withFileTypes: true });
|
|
for (const entry of entries) {
|
|
const fullPath = path.join(current, entry.name);
|
|
if (entry.isDirectory()) {
|
|
if (
|
|
entry.name === "node_modules" ||
|
|
entry.name === "dist" ||
|
|
entry.name === "vendor" ||
|
|
entry.name === "fixtures"
|
|
) {
|
|
continue;
|
|
}
|
|
stack.push(fullPath);
|
|
continue;
|
|
}
|
|
if (entry.isFile()) {
|
|
files.push(fullPath);
|
|
}
|
|
}
|
|
}
|
|
return files;
|
|
}
|
|
|
|
export function collectAllLiveTestFiles(repoRoot = process.cwd()) {
|
|
return ["src", "test", "extensions"]
|
|
.flatMap((dir) => walkFiles(path.join(repoRoot, dir)))
|
|
.map((file) => path.relative(repoRoot, file).split(path.sep).join("/"))
|
|
.filter((file) => file.endsWith(LIVE_TEST_SUFFIX))
|
|
.toSorted((a, b) => a.localeCompare(b));
|
|
}
|
|
|
|
function extensionKey(file) {
|
|
const relative = file.slice("extensions/".length);
|
|
return relative.split("/", 1)[0]?.toLowerCase() ?? "";
|
|
}
|
|
|
|
function isExtensionInRange(file, start, end) {
|
|
if (!file.startsWith("extensions/")) {
|
|
return false;
|
|
}
|
|
const key = extensionKey(file);
|
|
if (!key) {
|
|
return false;
|
|
}
|
|
const first = key[0];
|
|
return first >= start && first <= end;
|
|
}
|
|
|
|
function isGatewayBackendLiveTest(file) {
|
|
return (
|
|
file === "src/gateway/gateway-acp-bind.live.test.ts" ||
|
|
file === "src/gateway/gateway-cli-backend.live.test.ts" ||
|
|
file === "src/gateway/gateway-codex-bind.live.test.ts" ||
|
|
file === "src/gateway/gateway-codex-harness.live.test.ts"
|
|
);
|
|
}
|
|
|
|
function isGatewayProfilesLiveTest(file) {
|
|
return file === "src/gateway/gateway-models.profiles.live.test.ts";
|
|
}
|
|
|
|
function isExtensionMediaLiveTest(file) {
|
|
return (
|
|
file === "extensions/music-generation-providers.live.test.ts" ||
|
|
file === "extensions/minimax/minimax.live.test.ts" ||
|
|
file === "extensions/openai/openai-tts.live.test.ts" ||
|
|
file === "extensions/video-generation-providers.live.test.ts" ||
|
|
file === "extensions/volcengine/tts.live.test.ts" ||
|
|
file === "extensions/vydra/vydra.live.test.ts"
|
|
);
|
|
}
|
|
|
|
function isExtensionMediaMusicLiveTest(file) {
|
|
return file === "extensions/music-generation-providers.live.test.ts";
|
|
}
|
|
|
|
function isExtensionMediaVideoLiveTest(file) {
|
|
return file === "extensions/video-generation-providers.live.test.ts";
|
|
}
|
|
|
|
function isExtensionMediaAudioLiveTest(file) {
|
|
return (
|
|
isExtensionMediaLiveTest(file) &&
|
|
!isExtensionMediaMusicLiveTest(file) &&
|
|
!isExtensionMediaVideoLiveTest(file)
|
|
);
|
|
}
|
|
|
|
function isXaiLiveTest(file) {
|
|
return file.startsWith("extensions/xai/");
|
|
}
|
|
|
|
export function selectLiveShardFiles(shard, files = collectAllLiveTestFiles()) {
|
|
switch (shard) {
|
|
case "native-live-src-agents":
|
|
return files.filter((file) => file.startsWith("src/agents/"));
|
|
case "native-live-src-gateway":
|
|
return files.filter(
|
|
(file) => file.startsWith("src/gateway/") || file.startsWith("src/crestodian/"),
|
|
);
|
|
case "native-live-src-gateway-core":
|
|
return files.filter(
|
|
(file) =>
|
|
(file.startsWith("src/gateway/") || file.startsWith("src/crestodian/")) &&
|
|
!isGatewayBackendLiveTest(file) &&
|
|
!isGatewayProfilesLiveTest(file),
|
|
);
|
|
case "native-live-src-gateway-profiles":
|
|
return files.filter(isGatewayProfilesLiveTest);
|
|
case "native-live-src-gateway-backends":
|
|
return files.filter(isGatewayBackendLiveTest);
|
|
case "native-live-test":
|
|
return files.filter((file) => file.startsWith("test/"));
|
|
case "native-live-extensions-a-k":
|
|
return files.filter((file) => isExtensionInRange(file, "a", "k"));
|
|
case "native-live-extensions-l-n":
|
|
return files.filter(
|
|
(file) =>
|
|
isExtensionInRange(file, "l", "n") &&
|
|
!file.startsWith("extensions/openai/") &&
|
|
!isExtensionMediaLiveTest(file),
|
|
);
|
|
case "native-live-extensions-openai":
|
|
return files.filter(
|
|
(file) => file.startsWith("extensions/openai/") && !isExtensionMediaLiveTest(file),
|
|
);
|
|
case "native-live-extensions-o-z":
|
|
return files.filter(
|
|
(file) =>
|
|
isExtensionInRange(file, "o", "z") &&
|
|
!file.startsWith("extensions/openai/") &&
|
|
!isExtensionMediaLiveTest(file),
|
|
);
|
|
case "native-live-extensions-o-z-other":
|
|
return files.filter(
|
|
(file) =>
|
|
isExtensionInRange(file, "o", "z") &&
|
|
!file.startsWith("extensions/openai/") &&
|
|
!isExtensionMediaLiveTest(file) &&
|
|
!isXaiLiveTest(file),
|
|
);
|
|
case "native-live-extensions-xai":
|
|
return files.filter(isXaiLiveTest);
|
|
case "native-live-extensions-media":
|
|
return files.filter(isExtensionMediaLiveTest);
|
|
case "native-live-extensions-media-audio":
|
|
return files.filter(isExtensionMediaAudioLiveTest);
|
|
case "native-live-extensions-media-music":
|
|
case "native-live-extensions-media-music-google":
|
|
case "native-live-extensions-media-music-minimax":
|
|
return files.filter(isExtensionMediaMusicLiveTest);
|
|
case "native-live-extensions-media-video":
|
|
return files.filter(isExtensionMediaVideoLiveTest);
|
|
case "native-live-extensions-l-z":
|
|
return files.filter((file) => isExtensionInRange(file, "l", "z"));
|
|
default:
|
|
throw new Error(
|
|
`Unknown live test shard '${shard}'. Expected one of: ${LIVE_TEST_SHARDS.join(", ")}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function usage() {
|
|
console.error(`Usage: node scripts/test-live-shard.mjs <${LIVE_TEST_SHARDS.join("|")}> [--list]`);
|
|
}
|
|
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
const args = process.argv.slice(2);
|
|
const shard = args.find((arg) => !arg.startsWith("-"));
|
|
const listOnly = args.includes("--list");
|
|
if (!shard) {
|
|
usage();
|
|
process.exit(2);
|
|
}
|
|
|
|
let files;
|
|
try {
|
|
files = selectLiveShardFiles(shard);
|
|
} catch (error) {
|
|
console.error(error instanceof Error ? error.message : String(error));
|
|
usage();
|
|
process.exit(2);
|
|
}
|
|
if (files.length === 0) {
|
|
console.error(`Live test shard '${shard}' selected no files.`);
|
|
process.exit(2);
|
|
}
|
|
|
|
if (listOnly) {
|
|
for (const file of files) {
|
|
console.log(file);
|
|
}
|
|
process.exit(0);
|
|
}
|
|
|
|
console.log(`[test:live:shard] ${shard}: ${files.length} file(s)`);
|
|
const child = spawnPnpmRunner({
|
|
stdio: "inherit",
|
|
pnpmArgs: ["test:live", "--", ...files],
|
|
env: process.env,
|
|
});
|
|
child.on("exit", (code, signal) => {
|
|
if (signal) {
|
|
process.kill(process.pid, signal);
|
|
return;
|
|
}
|
|
process.exit(code ?? 1);
|
|
});
|
|
child.on("error", (error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|
|
}
|