ci: the bundle budget keeps real headroom and reports the trend (#352)

v1.69.0-beta.1 shipped at 255 993 B gzip against a 256 000 B ceiling —
seven bytes of headroom turned the gate into a lottery where the unlucky
last commit goes red, not the one that grew the bundle (5740324b was
exactly that fix; and today's dev already measures 256 012 B, so the old
ceiling would be red right now on an untouched tree).

The ceiling moves to 282 000 B — a deliberate ~10% allowance over the
calibration fact, recorded next to the constant: the budget guards the
CLASS of regression (tens of kilobytes from an accidental dependency or an
eager dictionary), not every byte. Every run now prints the fact, the
budget and the headroom, and CI adds the same row to the step summary so
the trend is visible long before the wall.

The lazy-ru idea from the issue (biggest single cut, ~25 KB gzip) is left
out deliberately: it changes what Russian users see on first paint and
deserves its own decision, not a ride-along.

Issue: #352
User-Visible: no
This commit is contained in:
Codex
2026-08-28 13:55:31 +03:00
parent dd0936258c
commit 93177cb74c
+29 -4
View File
@@ -3,7 +3,16 @@ import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
export const INITIAL_VIEW_GZIP_BUDGET = 256_000;
// #352: the budget guards the CLASS of regression — tens of kilobytes from
// an accidentally imported dependency or an eagerly bundled dictionary —
// not every byte. v1.69.0-beta.1 shipped at 255 993 B gzip against a
// 256 000 B ceiling: seven bytes of headroom turned the gate into a
// lottery where the unlucky LAST commit goes red, not the one that grew
// the bundle (5740324b was exactly that). The ceiling therefore keeps a
// deliberate ~10% allowance over the measured fact; the fact and headroom
// are printed on every run so the trend is visible long before the wall.
// Measured fact at calibration (v1.69.0-beta.1): 255 993 B gzip.
export const INITIAL_VIEW_GZIP_BUDGET = 282_000;
export function assertBundleBudget(manifest, budget = INITIAL_VIEW_GZIP_BUDGET) {
if (manifest?.schema !== 1 || !Array.isArray(manifest.files)) {
@@ -41,9 +50,25 @@ if (import.meta.url === pathToFileURL(process.argv[1] || '').href) {
try {
const manifest = JSON.parse(readFileSync(resolve('dist/houseplan-assets.json'), 'utf8'));
const result = assertBundleBudget(manifest);
console.log(`initial View: ${result.initialViewGzipBytes} B gzip`);
console.log(`lazy editor: ${result.lazyEditorGzipBytes} B gzip`);
console.log(`lazy locale: ${result.lazyLocaleGzipBytes} B gzip`);
const headroom = INITIAL_VIEW_GZIP_BUDGET - result.initialViewGzipBytes;
const lines = [
`initial View: ${result.initialViewGzipBytes} B gzip`
+ ` (budget ${INITIAL_VIEW_GZIP_BUDGET} B, headroom ${headroom} B)`,
`lazy editor: ${result.lazyEditorGzipBytes} B gzip`,
`lazy locale: ${result.lazyLocaleGzipBytes} B gzip`,
];
for (const line of lines) console.log(line);
// #352: the trend belongs where humans look — the run summary.
if (process.env.GITHUB_STEP_SUMMARY) {
const { appendFileSync } = await import('node:fs');
appendFileSync(process.env.GITHUB_STEP_SUMMARY, [
'### Бюджет бандла',
`| граф | gzip | бюджет | запас |`,
`|---|---|---|---|`,
`| initial View | ${result.initialViewGzipBytes} B | ${INITIAL_VIEW_GZIP_BUDGET} B | ${headroom} B |`,
'',
].join('\n'));
}
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);