mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
fix: verify demo bundle freshness for smokes too
Golden runs, benchmarks and documentation captures each called assertFreshDemoBundle; the smoke launcher never did, so all ~128 smokes could silently test a stale demo/srv/assets bundle. On #234 that cost a round of analysis: three assertions went red and a fourth went green, because the old code was wrong in two places that agreed with each other, and a mixed result reads as a logic defect rather than a stale artefact. launch() now runs the check once for every smoke, against the repository root rather than the serving root — demo/srv has no src/** to fingerprint. HP_ALLOW_STALE_BUNDLE=1 skips it for debugging and warns out loud, because a guard that says nothing when it steps aside is the silent success this project keeps removing. A mutation entry proves the call cannot quietly disappear. Issue: #236 User-Visible: no
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { resolve } from 'node:path';
|
||||
import test from 'node:test';
|
||||
import { assertFreshDemoBundle } from '../demo/bundle-freshness.mjs';
|
||||
import {
|
||||
ALLOW_STALE_BUNDLE,
|
||||
assertFreshDemoBundle,
|
||||
assertFreshDemoBundleUnlessAllowed,
|
||||
} from '../demo/bundle-freshness.mjs';
|
||||
import { sourceFingerprint } from '../scripts/source-fingerprint.mjs';
|
||||
|
||||
const fixtureRoot = () => {
|
||||
@@ -55,3 +59,56 @@ test('bundle freshness uses the target tree fingerprint contract', async () => {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('the launcher gate refuses a stale bundle by default (#236)', async () => {
|
||||
// Смок против несвежего бандла не падает честно: на #234 три проверки
|
||||
// покраснели, а четвёртая ПРОШЛА, потому что старый код одинаково врал в двух
|
||||
// местах, которые сверялись друг с другом. Такой результат читается как
|
||||
// дефект логики и отправляет искать причину не туда.
|
||||
const root = fixtureRoot();
|
||||
try {
|
||||
const stale = { evaluate: async () => 'fingerprint-of-an-older-tree' };
|
||||
await assert.rejects(
|
||||
() => assertFreshDemoBundleUnlessAllowed(stale, root, {}),
|
||||
/stale/,
|
||||
);
|
||||
const fresh = { evaluate: async () => sourceFingerprint(root) };
|
||||
assert.equal(
|
||||
await assertFreshDemoBundleUnlessAllowed(fresh, root, {}),
|
||||
sourceFingerprint(root),
|
||||
);
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('the escape hatch skips the gate but never silently (#236)', async () => {
|
||||
const root = fixtureRoot();
|
||||
const warnings = [];
|
||||
const realWarn = console.warn;
|
||||
console.warn = (...args) => warnings.push(args.join(' '));
|
||||
try {
|
||||
const stale = { evaluate: async () => 'stale' };
|
||||
const result = await assertFreshDemoBundleUnlessAllowed(
|
||||
stale, root, { [ALLOW_STALE_BUNDLE]: '1' },
|
||||
);
|
||||
assert.equal(result, null, 'пропуск возвращает null, а не выдуманный фингерпринт');
|
||||
assert.equal(warnings.length, 1, 'пропуск обязан быть слышен');
|
||||
assert.match(warnings[0], new RegExp(ALLOW_STALE_BUNDLE));
|
||||
assert.match(warnings[0], /#236/);
|
||||
} finally {
|
||||
console.warn = realWarn;
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('the smoke launcher enforces the gate on the repository root (#236)', async () => {
|
||||
// Контракт места вызова: гейт живёт в общем лаунчере, поэтому защита есть у
|
||||
// всех ~128 смоков без правки каждого. И считает фингерпринт по корню
|
||||
// репозитория, а не по каталогу раздачи demo/srv, где нет src/**.
|
||||
const source = readFileSync(
|
||||
new URL('../demo/serve.mjs', import.meta.url), 'utf8',
|
||||
);
|
||||
assert.match(source, /assertFreshDemoBundleUnlessAllowed\(page, REPO_ROOT\)/);
|
||||
assert.match(source, /const REPO_ROOT = dirname\(dirname\(/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user