From 1a8a51f2d91c0afa4e407ea227ee53860082241d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 10:38:47 +0300 Subject: [PATCH] =?UTF-8?q?fix(gates):=20=D0=BA=D0=BB=D1=8E=D1=87=20=D1=81?= =?UTF-8?q?=D0=BC=D0=BE=D0=BA=D0=BE=D0=B2=20=D0=BF=D0=BE=D0=BA=D1=80=D1=8B?= =?UTF-8?q?=D0=B2=D0=B0=D0=B5=D1=82=20=D0=BE=D1=81=D0=BD=D0=B0=D1=81=D1=82?= =?UTF-8?q?=D0=BA=D1=83=20=D0=B8=20=D0=BF=D1=80=D0=BE=D0=B1=D1=8B=20=D0=B3?= =?UTF-8?q?=D0=B0=D1=80=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Прогон #2371 (ee678352) добавил в demo/guard/verify-guard.mjs пробу гарда benchmark — и job «Смоки в браузере» была ПРОПУЩЕНА как переиспользованная. Причина в HARNESS.smoke: ключ держал ровно demo/smoke_*.mjs, а `demo/serve.mjs`, `demo/guard/**` и benchmark, который проба запускает, в него не входили. Файл исполняется только в этой job, его правка её ключ не меняла — проба уехала в dev, ни разу не запустившись. Пропущенная проверка выглядит точно как пройденная: это тот же дефект, против которого заведён #430, только этажом выше — не тест не умеет падать, а job не запускается. Заодно это значит, что правки #404 в serve.mjs и любой из четырёх проб гарда всё это время могли быть реюзнуты. Критерий ключа теперь один и читаемый: всё, что job исполняет. Benchmark'и берутся все, а не по имени, — любой может быть подключён к пробам позже, и лишний прогон дешевле молчания. demo/fixtures/** не добавлен: он в корпусе sourceFingerprint, который уже подмешан в ключ. Тест проверяет обе половины: файлы попадают в оснастку И правка каждого меняет ключ. На прежнем предикате он краснеет (проверено). Гейты: npm test 1791 tests, 1790 pass, 0 fail. Этот коммит меняет ключ смоков, поэтому job со смоками на нём прогонится по-настоящему — вместе с той пробой, ради которой всё и затевалось. Issue: #430 User-Visible: no --- scripts/gate-reuse.mjs | 23 ++++++++++++++++++++++- test/gate-reuse.test.mjs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/scripts/gate-reuse.mjs b/scripts/gate-reuse.mjs index cc106bbe..68ed8a7c 100644 --- a/scripts/gate-reuse.mjs +++ b/scripts/gate-reuse.mjs @@ -34,8 +34,29 @@ import { sourceFingerprint } from './source-fingerprint.mjs'; */ export const HARNESS = { smoke: { + // Всё, что job «Смоки в браузере» ИСПОЛНЯЕТ, а не только сами смоки (#430). + // + // До этой задачи ключ держал ровно `demo/smoke_*.mjs`. Из него выпадали: + // `demo/serve.mjs` — сама оснастка, включая гард исключений; `demo/guard/**` + // — отрицательные пробы этого гарда и запускающий их `verify-guard.mjs`; + // benchmark, который одна из проб запускает с `--guard-probe`. + // + // Стоило это ровно того, чего и должно было. Прогон #2371 (ee678352) + // добавлял в `verify-guard.mjs` пробу гарда benchmark — и job со смоками + // была ПРОПУЩЕНА как переиспользованная: правка файла, который исполняется + // только в ней, её ключ не меняла. Проба уехала в `dev`, ни разу не + // запустившись. Пропущенная проверка выглядит точно как пройденная — и это + // тот же дефект, против которого заведён весь #430. + // + // Benchmark'и берутся все, а не по имени: любой из них может быть подключён + // к пробам позже, а платить за лишний прогон дешевле, чем за молчание. + // `demo/fixtures/**` в ключ не входит — он в корпусе `sourceFingerprint`, + // который уже подмешан в ключ строкой выше. roots: ['demo'], - keep: (rel) => /^demo\/smoke_[^/]+\.mjs$/.test(rel), + keep: (rel) => /^demo\/smoke_[^/]+\.mjs$/.test(rel) + || rel === 'demo/serve.mjs' + || /^demo\/guard\//.test(rel) + || /^demo\/benchmark_[^/]+\.mjs$/.test(rel), }, golden: { // demo/golden/** целиком: и сценарии, и эталоны — эталон тоже вход diff --git a/test/gate-reuse.test.mjs b/test/gate-reuse.test.mjs index ccd033a5..3f1fbe81 100644 --- a/test/gate-reuse.test.mjs +++ b/test/gate-reuse.test.mjs @@ -176,6 +176,38 @@ test('the CLI prints the key and writes it to GITHUB_OUTPUT', (t) => { } }); +test('#430 ключ смоков покрывает всё, что эта job исполняет', () => { + // Прогон #2371 (ee678352) добавил в verify-guard.mjs пробу гарда benchmark, + // и job со смоками была пропущена как переиспользованная: файл исполняется + // только там, а в её ключ не входил. Проба уехала в dev, не запустившись ни + // разу. Здесь закреплено, что так больше не выйдет. + const { dir, put } = makeTree(); + try { + put('demo/serve.mjs', '// harness\n'); + put('demo/guard/verify-guard.mjs', '// probes\n'); + put('demo/guard/guard_tail_exception.mjs', '// probe\n'); + put('demo/benchmark_backdrop_decode.mjs', '// benchmark\n'); + const files = harnessFiles(dir, 'smoke'); + for (const rel of [ + 'demo/serve.mjs', + 'demo/guard/verify-guard.mjs', + 'demo/guard/guard_tail_exception.mjs', + 'demo/benchmark_backdrop_decode.mjs', + ]) { + assert.ok(files.includes(rel), `${rel} вне ключа смоков — его правка будет реюзнута`); + } + // И ключ обязан меняться от правки каждого из них: список файлов сам по + // себе ничего не гарантирует, если хэш их не читает. + for (const rel of files) { + const before = reuseKey(dir, 'smoke'); + put(rel, '// changed\n'); + assert.notEqual(reuseKey(dir, 'smoke'), before, `${rel}: правка не меняет ключ`); + } + } finally { + rmSync(dir, { recursive: true, force: true }); + } +}); + test('HARNESS keeps scripts/** out of the keys on purpose', () => { // Инфраструктурная работа правит scripts/** постоянно. Если бы каталог // целиком попал в ключ, переиспользование не срабатывало бы никогда — ровно