92 lines
3.0 KiB
JavaScript
92 lines
3.0 KiB
JavaScript
import { execFileSync } from "node:child_process";
|
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { dirname, resolve } from "node:path";
|
|
|
|
import { frozenPackages, frozenRuntime } from "./frozen-versions.mjs";
|
|
|
|
function readJson(path) {
|
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
}
|
|
|
|
function installedPackage(manifestPath, packageName) {
|
|
const packagePath = resolve(
|
|
dirname(manifestPath),
|
|
"node_modules",
|
|
...packageName.split("/"),
|
|
"package.json",
|
|
);
|
|
return readJson(packagePath);
|
|
}
|
|
|
|
export function verifyFrozenDependencies() {
|
|
const problems = [];
|
|
const packages = {};
|
|
|
|
for (const [manifestPath, sections] of Object.entries(frozenPackages)) {
|
|
const manifest = readJson(manifestPath);
|
|
packages[manifest.name] = {};
|
|
|
|
for (const [section, expected] of Object.entries(sections)) {
|
|
for (const [name, version] of Object.entries(expected)) {
|
|
const declared = manifest[section]?.[name];
|
|
if (declared !== version) {
|
|
problems.push(`${manifestPath} ${section}.${name}: declared ${declared ?? "missing"}, expected ${version}`);
|
|
continue;
|
|
}
|
|
|
|
const installed = installedPackage(manifestPath, name);
|
|
packages[manifest.name][name] = installed.version;
|
|
if (installed.name !== name) {
|
|
problems.push(`${manifestPath} ${name}: linked package name is ${installed.name ?? "missing"}`);
|
|
} else if (!version.startsWith("workspace:") && installed.version !== version) {
|
|
problems.push(`${manifestPath} ${name}: installed ${installed.version}, expected ${version}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const packageManager = readJson("package.json").packageManager;
|
|
const pnpmVersion = process.platform === "win32"
|
|
? execFileSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/s", "/c", "pnpm --version"], {
|
|
encoding: "utf8",
|
|
}).trim()
|
|
: execFileSync("pnpm", ["--version"], { encoding: "utf8" }).trim();
|
|
const runtimeChecks = {
|
|
arch: process.arch,
|
|
node: process.version.slice(1),
|
|
os: process.platform,
|
|
packageManager,
|
|
pnpm: pnpmVersion,
|
|
};
|
|
|
|
for (const key of ["arch", "node", "os", "pnpm"]) {
|
|
if (runtimeChecks[key] !== frozenRuntime[key]) {
|
|
problems.push(`${key}: running ${runtimeChecks[key]}, expected ${frozenRuntime[key]}`);
|
|
}
|
|
}
|
|
if (packageManager !== `pnpm@${frozenRuntime.pnpm}`) {
|
|
problems.push(`packageManager: declared ${packageManager}, expected pnpm@${frozenRuntime.pnpm}`);
|
|
}
|
|
|
|
return {
|
|
packages,
|
|
problems,
|
|
runtime: runtimeChecks,
|
|
status: problems.length === 0 ? "passed" : "failed",
|
|
};
|
|
}
|
|
|
|
const snapshot = verifyFrozenDependencies();
|
|
const evidenceDirectory = process.env.DADA_EVIDENCE_DIR;
|
|
|
|
if (evidenceDirectory) {
|
|
mkdirSync(evidenceDirectory, { recursive: true });
|
|
writeFileSync(
|
|
resolve(evidenceDirectory, "dependency-tree.json"),
|
|
`${JSON.stringify({ schema_version: "1.0", ...snapshot }, null, 2)}\n`,
|
|
);
|
|
}
|
|
|
|
console.log(JSON.stringify(snapshot, null, 2));
|
|
if (snapshot.problems.length > 0) process.exit(1);
|