Files
proxycast/scripts/local-ci.mjs
T
2026-04-13 02:50:53 +08:00

200 lines
4.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
import { spawnSync } from "node:child_process";
import process from "node:process";
import { planQualityTasks } from "./quality-task-planner.mjs";
const options = parseArgs(process.argv.slice(2));
const rootDir = process.cwd();
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
const cargoCommand = process.platform === "win32" ? "cargo.exe" : "cargo";
const BRIDGE_REASON_LABELS = {
bridge_contracts: "bridge/contracts",
bridge_runtime: "DevBridge / mock / bridge runtime",
fallback_full_suite: "兜底全量",
full_suite: "full 模式",
harness_cleanup_contract: "harness cleanup contract",
workflow_full_suite: "workflow 全量",
};
function parseArgs(argv) {
const result = {
full: false,
staged: false,
base: "",
help: false,
};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
if (arg === "--full") {
result.full = true;
continue;
}
if (arg === "--staged") {
result.staged = true;
continue;
}
if (arg === "--base" && argv[index + 1]) {
result.base = String(argv[index + 1]).trim();
index += 1;
continue;
}
if (arg === "--help" || arg === "-h") {
result.help = true;
}
}
return result;
}
function printHelp() {
console.log(`
Lime 本地校验入口
用法:
npm run verify:local
npm run verify:local -- --staged
npm run verify:local -- --base origin/main
npm run verify:local:full
选项:
--full 忽略改动检测,执行全量本地校验
--staged 仅基于已暂存文件判断要跑的检查
--base REF 基于指定基线计算改动文件
-h, --help 显示帮助
`);
}
function runCommand(command, args) {
console.log(`\n[local-ci] > ${command} ${args.join(" ")}`);
const result = spawnSync(command, args, {
cwd: rootDir,
stdio: "inherit",
env: process.env,
});
if (typeof result.status === "number" && result.status !== 0) {
process.exit(result.status);
}
if (result.error) {
throw result.error;
}
}
function printSummary(changedFiles, tasks) {
console.log("[local-ci] 模式:", options.full ? "full" : "smart");
if (!options.full) {
console.log("[local-ci] 检测到改动文件数:", changedFiles.length);
if (changedFiles.length > 0) {
const preview = changedFiles.slice(0, 12);
for (const file of preview) {
console.log(`[local-ci] - ${file}`);
}
if (changedFiles.length > preview.length) {
console.log(
`[local-ci] ... 其余 ${changedFiles.length - preview.length} 个文件省略`,
);
}
}
}
if (tasks.docsOnly) {
console.log("[local-ci] 当前仅检测到文档改动,跳过本地代码校验。");
return;
}
console.log("[local-ci] 计划执行:");
if (tasks.integrity) {
console.log("[local-ci] - 一致性校验");
}
if (tasks.frontend) {
console.log("[local-ci] - 前端校验");
}
if (tasks.bridge) {
const bridgeReasonLabels = Array.isArray(tasks.bridgeReasons)
? tasks.bridgeReasons
.map((reason) => BRIDGE_REASON_LABELS[reason] ?? reason)
.filter(Boolean)
: [];
console.log(
bridgeReasonLabels.length > 0
? `[local-ci] - bridge 校验(${bridgeReasonLabels.join(" / ")})`
: "[local-ci] - bridge 校验",
);
}
if (tasks.guiSmoke) {
console.log("[local-ci] - GUI 冒烟");
}
if (tasks.rust) {
console.log("[local-ci] - Rust 校验");
}
if (tasks.fallback) {
console.log("[local-ci] - 未检测到改动,执行全量兜底校验");
}
}
function runSelectedTasks(tasks) {
if (tasks.docsOnly) {
return;
}
if (tasks.integrity) {
runCommand(npmCommand, ["run", "verify:app-version"]);
}
if (tasks.frontend) {
runCommand(npmCommand, ["run", "lint"]);
runCommand(npmCommand, ["run", "typecheck"]);
runCommand(npmCommand, ["test"]);
}
if (tasks.bridge) {
if (!tasks.frontend) {
runCommand(npmCommand, ["run", "test:bridge"]);
}
runCommand(npmCommand, ["run", "test:contracts"]);
}
if (tasks.rust) {
runCommand(cargoCommand, [
"test",
"--manifest-path",
"src-tauri/Cargo.toml",
]);
if (options.full) {
runCommand(cargoCommand, [
"clippy",
"--manifest-path",
"src-tauri/Cargo.toml",
]);
}
}
if (tasks.guiSmoke) {
runCommand(npmCommand, ["run", "verify:gui-smoke"]);
}
}
function main() {
if (options.help) {
printHelp();
return;
}
const { changedFiles, tasks } = planQualityTasks({
base: options.base,
cwd: rootDir,
full: options.full,
staged: options.staged,
});
printSummary(changedFiles, tasks);
runSelectedTasks(tasks);
console.log("\n[local-ci] 本地校验完成。");
}
main();