90 lines
2.9 KiB
JavaScript
90 lines
2.9 KiB
JavaScript
/**
|
|
* Pre-build script that extracts the current version's release notes
|
|
* from CHANGELOG.md and writes them as JSON for the web app to import.
|
|
*
|
|
* Version resolution order:
|
|
* 1. KANDEV_VERSION env var (set by CI)
|
|
* 2. `git describe --tags --abbrev=0` (local dev with tags)
|
|
* 3. "dev" fallback
|
|
*/
|
|
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
import { execSync } from "node:child_process";
|
|
import { join, dirname } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const WEB_ROOT = join(__dirname, "..");
|
|
const REPO_ROOT = join(WEB_ROOT, "..", "..");
|
|
const OUTPUT_DIR = join(WEB_ROOT, "generated");
|
|
const OUTPUT_FILE = join(OUTPUT_DIR, "release-notes.json");
|
|
const CHANGELOG_PATH = join(REPO_ROOT, "CHANGELOG.md");
|
|
|
|
const FALLBACK = { version: "dev", date: "", notes: "" };
|
|
|
|
function getVersion() {
|
|
if (process.env.KANDEV_VERSION) {
|
|
return process.env.KANDEV_VERSION.replace(/^v/, "");
|
|
}
|
|
try {
|
|
const tag = execSync("git describe --tags --abbrev=0", {
|
|
encoding: "utf-8",
|
|
stdio: ["pipe", "pipe", "pipe"],
|
|
}).trim();
|
|
return tag.replace(/^v/, "");
|
|
} catch {
|
|
return "dev";
|
|
}
|
|
}
|
|
|
|
function extractVersionNotes(changelog, version) {
|
|
// Split on ## headings and find the section for our version
|
|
const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
const headerPattern = new RegExp(`^## ${escapedVersion}(?:\\s*-\\s*(\\S+))?\\s*$`, "m");
|
|
const headerMatch = changelog.match(headerPattern);
|
|
if (!headerMatch) return null;
|
|
|
|
const date = headerMatch[1] || "";
|
|
const sectionStart = headerMatch.index + headerMatch[0].length;
|
|
const rest = changelog.slice(sectionStart);
|
|
|
|
// Find the next ## heading (or end of string)
|
|
const nextHeading = rest.search(/^## /m);
|
|
const body = nextHeading === -1 ? rest : rest.slice(0, nextHeading);
|
|
const notes = body.trim();
|
|
|
|
return { date, notes };
|
|
}
|
|
|
|
function main() {
|
|
mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
const version = getVersion();
|
|
|
|
if (version === "dev") {
|
|
writeFileSync(OUTPUT_FILE, JSON.stringify(FALLBACK, null, 2) + "\n");
|
|
console.log("[release-notes] dev mode — wrote fallback");
|
|
return;
|
|
}
|
|
|
|
let changelog;
|
|
try {
|
|
changelog = readFileSync(CHANGELOG_PATH, "utf-8");
|
|
} catch {
|
|
writeFileSync(OUTPUT_FILE, JSON.stringify(FALLBACK, null, 2) + "\n");
|
|
console.log("[release-notes] CHANGELOG.md not found — wrote fallback");
|
|
return;
|
|
}
|
|
|
|
const extracted = extractVersionNotes(changelog, version);
|
|
if (!extracted) {
|
|
writeFileSync(OUTPUT_FILE, JSON.stringify({ version, date: "", notes: "" }, null, 2) + "\n");
|
|
console.log(`[release-notes] version ${version} not found in CHANGELOG.md — wrote empty notes`);
|
|
return;
|
|
}
|
|
|
|
const result = { version, date: extracted.date, notes: extracted.notes };
|
|
writeFileSync(OUTPUT_FILE, JSON.stringify(result, null, 2) + "\n");
|
|
console.log(`[release-notes] extracted notes for v${version}`);
|
|
}
|
|
|
|
main();
|