Files
pikasTech-unidesk/scripts/native/cicd/apply-platform-infra-public-edge-archive.mjs
T
2026-07-18 17:59:04 +02:00

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);
}