75 lines
3.0 KiB
JavaScript
75 lines
3.0 KiB
JavaScript
#!/usr/bin/env bun
|
|
|
|
import { spawnSync } from "node:child_process";
|
|
import { readFileSync, realpathSync } from "node:fs";
|
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
|
|
const options = parseOptions(process.argv.slice(2));
|
|
const sourceRoot = realpathSync(options.sourceRoot);
|
|
const archiveRoot = dirname(sourceRoot);
|
|
const markerCommit = readFileSync(join(archiveRoot, ".unidesk-source-commit"), "utf8").trim();
|
|
if (markerCommit !== options.sourceCommit) fail("archive source commit marker 不匹配");
|
|
const ancestryFile = join(archiveRoot, ".unidesk-source-ancestors");
|
|
const ancestors = readFileSync(ancestryFile, "utf8").split(/\r?\n/u).filter(Boolean);
|
|
if (!ancestors.includes(options.sourceCommit) || ancestors.some((value) => !/^[0-9a-f]{40}$/u.test(value))) fail("archive ancestry proof 无效");
|
|
const configPath = resolve(sourceRoot, options.config);
|
|
if (!configPath.startsWith(`${sourceRoot}/`)) fail("--config 必须位于 source archive 内");
|
|
|
|
const result = spawnSync("bun", [
|
|
"scripts/cli.ts",
|
|
"platform-infra",
|
|
"public-edge",
|
|
"reconcile",
|
|
"--config",
|
|
configPath,
|
|
"--target",
|
|
options.target,
|
|
"--authority",
|
|
options.authority,
|
|
"--source-commit",
|
|
options.sourceCommit,
|
|
"--ancestry-file",
|
|
ancestryFile,
|
|
"--confirm",
|
|
], {
|
|
cwd: sourceRoot,
|
|
env: { ...process.env, UNIDESK_PUBLIC_EDGE_RECONCILE: "1", UNIDESK_TRANS_REPO_ROOT: sourceRoot },
|
|
stdio: "inherit",
|
|
timeout: 120_000,
|
|
});
|
|
process.exit(result.status ?? 1);
|
|
|
|
function parseOptions(args) {
|
|
const values = new Map();
|
|
let confirm = false;
|
|
for (let index = 0; index < args.length; index += 1) {
|
|
const arg = args[index];
|
|
if (arg === "--confirm") {
|
|
confirm = true;
|
|
continue;
|
|
}
|
|
if (!["--source-root", "--source-commit", "--authority", "--config", "--target"].includes(arg)) fail(`不支持的参数:${arg}`);
|
|
const value = args[index + 1];
|
|
if (value === undefined || value.startsWith("--")) fail(`${arg} 需要参数`);
|
|
values.set(arg.slice(2), value);
|
|
index += 1;
|
|
}
|
|
const sourceRoot = values.get("source-root");
|
|
const sourceCommit = values.get("source-commit");
|
|
const authority = values.get("authority");
|
|
const config = values.get("config");
|
|
const target = values.get("target");
|
|
if (!confirm) fail("必须显式传入 --confirm");
|
|
if (typeof sourceRoot !== "string" || !isAbsolute(sourceRoot)) fail("--source-root 必须是绝对路径");
|
|
if (typeof sourceCommit !== "string" || !/^[0-9a-f]{40}$/u.test(sourceCommit)) fail("--source-commit 必须是 40 位 commit");
|
|
if (typeof authority !== "string" || authority.length === 0) fail("缺少 --authority");
|
|
if (typeof config !== "string" || isAbsolute(config)) fail("--config 必须是 archive 内相对路径");
|
|
if (typeof target !== "string" || target.length === 0) fail("缺少 --target");
|
|
return { sourceRoot, sourceCommit, authority, config, target };
|
|
}
|
|
|
|
function fail(message) {
|
|
process.stderr.write(`${JSON.stringify({ ok: false, action: "platform-infra-public-edge-archive-reconcile", error: message, valuesPrinted: false })}\n`);
|
|
process.exit(1);
|
|
}
|