Files
modelstudioai__cli/tools/release/lib/validate.mjs
2026-07-25 08:43:38 +08:00

84 lines
2.4 KiB
JavaScript

import { readFileSync } from "fs";
import { join } from "path";
import { PACKAGES, ROOT, readPackageJson } from "./packages.mjs";
const README_FILES = ["README.md", "README.zh.md"];
export function assertReadmeSync() {
for (const file of README_FILES) {
const rootBuf = readFileSync(join(ROOT, file));
const cliBuf = readFileSync(join(ROOT, "packages/cli", file));
if (!rootBuf.equals(cliBuf)) {
throw new Error(
`${file} differs between root and packages/cli. ` +
`Sync them manually (e.g. \`cp ${file} packages/cli/${file}\`).`,
);
}
}
}
export function loadAndValidatePackages({ packages } = {}) {
const pkgs = packages ?? PACKAGES;
const internalNames = new Set(pkgs.map((p) => p.name));
const jsonByKey = new Map();
for (const pkg of pkgs) {
const json = readPackageJson(pkg);
if (json.name !== pkg.name) {
throw new Error(`${pkg.dir} name must be ${pkg.name}, got ${json.name}`);
}
jsonByKey.set(pkg.key, json);
}
const coreJson = jsonByKey.get("core");
const cliJson = jsonByKey.get("cli");
const version = coreJson.version;
for (const pkg of pkgs) {
const json = jsonByKey.get(pkg.key);
if (json.version !== version) {
throw new Error(
`all package versions must match ${version} (bailian-cli-core), ` +
`but ${pkg.name} is ${json.version}.`,
);
}
for (const [dep, range] of Object.entries(json.dependencies ?? {})) {
if (internalNames.has(dep) && range !== "workspace:*") {
throw new Error(
`${pkg.name} dependency on ${dep} must be "workspace:*", got ${String(range)}.`,
);
}
}
}
return { coreJson, cliJson };
}
const RESERVED_CHANNELS = new Set([
"latest",
"manifest", // would collide with manifest.json at the OSS prefix root
"beta",
"alpha",
"next",
"rc",
"canary",
"dev",
]);
const CHANNEL_FORMAT = /^[a-z][a-z0-9-]{1,30}$/;
export function assertChannel(channel) {
if (!channel || typeof channel !== "string") {
throw new Error("channel is required");
}
if (!CHANNEL_FORMAT.test(channel)) {
throw new Error(
`channel "${channel}" must match ${CHANNEL_FORMAT} (lowercase letters/digits/dashes, start with a letter, 2-31 chars).`,
);
}
if (RESERVED_CHANNELS.has(channel)) {
throw new Error(
`channel "${channel}" is reserved (${[...RESERVED_CHANNELS].join(", ")}); pick a different name.`,
);
}
}