40 lines
2.6 KiB
JavaScript
40 lines
2.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
const notesPath = path.join(repoRoot, "docs/web/RELEASE_NOTES.md");
|
|
const notes = fs.readFileSync(notesPath, "utf8");
|
|
const packageJson = JSON.parse(fs.readFileSync(path.join(repoRoot, "web/package.json"), "utf8"));
|
|
const engine = JSON.parse(fs.readFileSync(path.join(repoRoot, "web/app/public/engine-manifest.json"), "utf8"));
|
|
const ledger = JSON.parse(fs.readFileSync(path.join(repoRoot, "docs/status/parity-ledger.json"), "utf8"));
|
|
|
|
assert.match(notes, new RegExp(`^# Web Blender Modeler V1 ${packageJson.version.replaceAll(".", "\\.")} Release Notes`, "m"));
|
|
assert.match(notes, new RegExp(`engine\\s+\`${engine.releaseId.replaceAll(".", "\\.")}\``));
|
|
for (const capability of ["\.blend", "undo", "redo", "OffscreenCanvas", "single-thread", "pthread", "OPFS", "10M geometry", "8K textures", "SBOM"]) {
|
|
assert.match(notes, new RegExp(capability, "i"), `release notes omit verified capability: ${capability}`);
|
|
}
|
|
for (const boundary of ["LOCAL_EXACT", "LOCAL_BOUNDED", "SERVER", "EXCLUDED", "Chromium-only", "not a browser port"]) {
|
|
assert.ok(notes.includes(boundary), `release notes omit capability boundary: ${boundary}`);
|
|
}
|
|
const releaseReady = ledger.families.filter((family) => family.releaseStatus === "READY").length;
|
|
const parityBlocked = ledger.families.filter((family) => family.parityStatus === "BLOCKED").length;
|
|
assert.equal(releaseReady, 12);
|
|
assert.equal(parityBlocked, 12);
|
|
assert.ok(notes.includes(`All ${releaseReady} V1 family release slices are \`READY\``));
|
|
assert.match(notes, new RegExp(`all ${parityBlocked} complete Blender 5\\.2 family parity states are\\s+\`BLOCKED\``));
|
|
|
|
const links = [...notes.matchAll(/\[[^\]]+\]\(([^)]+)\)/g)].map((match) => match[1]);
|
|
assert.ok(links.length >= 5, "release notes do not link the capability and operations sources");
|
|
for (const link of links) {
|
|
assert.doesNotMatch(link, /^(?:https?:|\/)/, `release notes contain an external or absolute link: ${link}`);
|
|
const source = link === "V1_SCOPE.md"
|
|
? path.join(repoRoot, "docs/WEB_BLENDER_MODELER_V1_SCOPE.md")
|
|
: link === "parity-ledger.json"
|
|
? path.join(repoRoot, "docs/status/parity-ledger.json")
|
|
: path.join(repoRoot, "docs/web", link);
|
|
assert.ok(fs.statSync(source).isFile(), `release note link is unresolved: ${link}`);
|
|
}
|
|
process.stdout.write(`rc-release-notes-ok version=${packageJson.version} ready=${releaseReady} parityBlocked=${parityBlocked} links=${links.length}\n`);
|