返回 CodeWhale
derive-changelog.mjs
根目录 / web / scripts / derive-changelog.mjs
1 #!/usr/bin/env node
2 /**
3 * derive-changelog.mjs — emit `web/lib/changelog.generated.ts` from the
4 * repository CHANGELOG.md so the /changelog route and the docs release-truth
5 * band render the real release record, never a hand-typed copy.
6 *
7 * Runs at `npm run prebuild`, `npm run dev` and in the vitest global setup.
8 * The output is NOT tracked (web/.gitignore): a committed copy raced between
9 * merges — two PRs that each added a CHANGELOG line each regenerated it
10 * against their own base, git merged both to a stale item count, and main
11 * went red (twice on 2026-09-26). Deriving at build time removes the race.
12 */
13 import { readFileSync, writeFileSync, existsSync } from "node:fs";
14 import { resolve, dirname } from "node:path";
15 import { fileURLToPath } from "node:url";
16 import { parseChangelog, renderChangelogModule } from "./changelog-lib.mjs";
17
18 const __dirname = dirname(fileURLToPath(import.meta.url));
19 const REPO_ROOT = resolve(__dirname, "..", "..");
20 const SOURCE = resolve(REPO_ROOT, "CHANGELOG.md");
21 const TARGET = resolve(__dirname, "..", "lib", "changelog.generated.ts");
22
23 if (!existsSync(SOURCE)) {
24 console.error(`[derive-changelog] CHANGELOG.md not found at ${SOURCE}`);
25 process.exit(1);
26 }
27
28 const parsed = parseChangelog(readFileSync(SOURCE, "utf-8"));
29 const next = renderChangelogModule(parsed);
30 const current = existsSync(TARGET) ? readFileSync(TARGET, "utf-8") : null;
31 if (current !== next) {
32 writeFileSync(TARGET, next);
33 console.log(`[derive-changelog] wrote ${parsed.releases.length} releases → lib/changelog.generated.ts`);
34 } else {
35 console.log(`[derive-changelog] lib/changelog.generated.ts is current (${parsed.releases.length} releases)`);
36 }
37
37 lines Plain Text