Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 5bc6a32f6b720d811de85b189233f1b72a1e99a1
parent 9bc1d42e8f9efac3afe4f95beb21832facce7cc3
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Sun, 27 Sep 2026 01:02:11 -0400

homepage: HOMEPAGE_SUMMARY_FILE is ignored by a production build

Review fix. The e2e's override of the summary file was honoured by `next
build` too, so a variable left in a build shell could ship the fixture as the
homepage's numbers. summaryFile(env, publicFile) now reads it only when
NODE_ENV is not "production"; Playwright's `next dev` is development and keeps
it. summary.test.ts covers both, run by the homepage's new `test` script
(`tsx --test "app/**/*.test.ts"`, as the editor's unit tests).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Ahomepage/app/lib/summary.test.ts | 24++++++++++++++++++++++++
Mhomepage/app/lib/summary.ts | 23+++++++++++++++++------
Mhomepage/package.json | 1+
3 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/homepage/app/lib/summary.test.ts b/homepage/app/lib/summary.test.ts @@ -0,0 +1,24 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { summaryFile } from "./summary"; + +// Run with: +// pnpm --filter homepage test + +const PUBLIC = "/repo/homepage/public/homepage-summary.json"; + +test("a production build never reads HOMEPAGE_SUMMARY_FILE", () => { + assert.equal( + summaryFile({ NODE_ENV: "production", HOMEPAGE_SUMMARY_FILE: "/tmp/fixture.json" }, PUBLIC), + PUBLIC, + ); +}); + +test("outside production (the e2e's next dev) it names the file to read", () => { + assert.equal( + summaryFile({ NODE_ENV: "development", HOMEPAGE_SUMMARY_FILE: "/x/.e2e-summary.json" }, PUBLIC), + "/x/.e2e-summary.json", + ); + assert.equal(summaryFile({ NODE_ENV: "development" }, PUBLIC), PUBLIC); + assert.equal(summaryFile({ NODE_ENV: "development", HOMEPAGE_SUMMARY_FILE: "" }, PUBLIC), PUBLIC); +}); diff --git a/homepage/app/lib/summary.ts b/homepage/app/lib/summary.ts @@ -16,14 +16,12 @@ import type { HomepageSummary } from "yt-dlp-transcript-common/lib/homepageSumma // Read with `readFileSync` at module scope of a server component, mirroring // export/app/changelog/page.tsx. `output: "export"` means this runs at build, // never at request time. -// -// HOMEPAGE_SUMMARY_FILE names another file to read instead. Only the e2e sets -// it, to a copy of this one with fixture accents (playwright.config.ts). export function loadSummary(): HomepageSummary | null { try { - const file = - process.env.HOMEPAGE_SUMMARY_FILE || - path.join(process.cwd(), "public", "homepage-summary.json"); + const file = summaryFile( + process.env, + path.join(process.cwd(), "public", "homepage-summary.json"), + ); const parsed = JSON.parse( fs.readFileSync(file, "utf8"), ) as HomepageSummary; @@ -35,3 +33,16 @@ export function loadSummary(): HomepageSummary | null { return null; } } + +// The file loadSummary reads: `public/homepage-summary.json`, or the file +// HOMEPAGE_SUMMARY_FILE names — but ONLY outside a production build. The e2e's +// `next dev` points it at a copy with fixture accents (playwright.config.ts); +// `next build` runs with NODE_ENV=production and ignores it, so a variable left +// in a build shell can never ship a fixture as the homepage's numbers. +export function summaryFile( + env: Readonly<Record<string, string | undefined>>, + publicFile: string, +): string { + const override = env.NODE_ENV !== "production" ? env.HOMEPAGE_SUMMARY_FILE : undefined; + return override || publicFile; +} diff --git a/homepage/package.json b/homepage/package.json @@ -13,6 +13,7 @@ "build:nodata": "next build", "start": "serve out -l ${HOMEPAGE_PORT:-3031}", "lint": "eslint", + "test": "tsx --test \"app/**/*.test.ts\"", "e2e": "node ../scripts/queue-lock.mjs --ports HOMEPAGE_E2E_PORT:3040 -- playwright test", "e2e:ui": "playwright test --ui", "deploy": "tsx ../common/bin/archilyzer.ts deploy homepage"