From f54dd981295ae00d5a1a1113509021606051fd32 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Tue, 18 Aug 2026 02:34:45 +0200 Subject: [PATCH] test(release): lock the VERSION file and RELEASE_NOTES[0] together (E1 S4, DX-6) A vitest that fails the gate when the newest release-notes entry's version diverges from the repo-root VERSION file (the two hand-edited version sources), plus a no-duplicate-versions check. Catches the "bumped one, forgot the other" release mistake. --- frontend/src/lib/releaseNotes.test.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 frontend/src/lib/releaseNotes.test.ts diff --git a/frontend/src/lib/releaseNotes.test.ts b/frontend/src/lib/releaseNotes.test.ts new file mode 100644 index 00000000..1a0bfa13 --- /dev/null +++ b/frontend/src/lib/releaseNotes.test.ts @@ -0,0 +1,21 @@ +import { readFileSync } from "node:fs"; + +import { describe, expect, it } from "vitest"; + +import { RELEASE_NOTES } from "./releaseNotes"; + +// DX-6: the app version is hand-maintained in two places that MUST agree — the repo-root VERSION file +// (the single source baked into the image + served at /api/version) and the newest RELEASE_NOTES entry +// (what the in-app "What's new" shows). A release that bumps one but forgets the other ships a wrong +// changelog or a mismatched banner. This locks them together so the gate catches the drift. +describe("release version consistency", () => { + it("RELEASE_NOTES[0].version matches the VERSION file", () => { + const version = readFileSync(new URL("../../../VERSION", import.meta.url), "utf-8").trim(); + expect(RELEASE_NOTES[0]?.version).toBe(version); + }); + + it("release notes are ordered newest-first with unique versions", () => { + const versions = RELEASE_NOTES.map((r) => r.version); + expect(new Set(versions).size).toBe(versions.length); // no duplicate version entries + }); +});