diff --git a/.github/workflows/mutation-gate.yml b/.github/workflows/mutation-gate.yml index 984bf18a..013c48a2 100644 --- a/.github/workflows/mutation-gate.yml +++ b/.github/workflows/mutation-gate.yml @@ -5,11 +5,12 @@ name: Мутационный гейт # оставшийся зелёным на сломанном коде, ничего не защищает — он лишь выглядит # защитой, и это хуже его отсутствия. # -# Прогон дорогой, поэтому он не входит в Validate и не идёт на каждый push. -# Его место — перед стабильным релизом (PROCESS.md §8) и раз в неделю по -# расписанию, чтобы дрейф тестов не копился до релиза. Дешёвая половина — -# «якоря патчей живы, guard-файлы существуют» — идёт с обычными юнитами: -# test/mutation-gate.test.mjs. +# Прогон дорогой и проверяет не продукт, а тесты, поэтому он не входит ни в +# Validate, ни в цикл разработки, ни в релизный гейт (#513, решение владельца +# 09.09): каждую ночь по расписанию, отказ — issue с отчётом (#472). +# Мутанты, задетые диффом, конвейер ревью гоняет отдельно на кандидате (#510). +# Дешёвая половина — «якоря патчей живы, guard-файлы существуют» — идёт с +# обычными юнитами: test/mutation-gate.test.mjs. # # #332: бандл собирается только мутантам с браузерным гвардом (guardNeedsBundle), # компиляция тестов в worktree стартует с тёплого test-build (инкрементальный @@ -25,14 +26,15 @@ on: required: false default: dev schedule: - # Понедельник, 05:20 UTC — до начала рабочего дня владельца. - - cron: '20 5 * * 1' + # Каждую ночь, 01:00 UTC (04:00 MSK) — после суток правок и до ночного + # полного Validate (nightly.yml, 02:30 UTC), чтобы не делить раннеры (#513). + - cron: '0 1 * * *' permissions: contents: read # Группа зависит от события (#472). Прежде она была одна на всё, и ручной -# запуск перед релизом отменял идущий по расписанию — так 24.08 погиб +# запуск (отладка гейта) отменял идущий по расписанию — так 24.08 погиб # еженедельный прогон, а отменённый в списке выглядит «не красным». Поймать # отмену изнутри нельзя: вместе с прогоном отменяются и не начавшиеся job, # включая любой репортёр. Значит отмену надо не ловить, а не допускать. @@ -111,8 +113,8 @@ jobs: if-no-files-found: warn retention-days: 30 - # Адресат у отказа (#472). Только по расписанию: ручные прогоны перед - # релизом падают по замыслу, их результат владелец смотрит сам — issue на + # Адресат у отказа (#472). Только по расписанию: ручной dispatch остаётся + # для отладки самого гейта, его результат смотрят в прогоне — issue на # каждый такой отказ был бы шумом, который снова перестанут читать. # # Права job-уровня ЗАМЕНЯЮТ права workflow, а не дополняют (прецедент — diff --git a/docs/TESTING.md b/docs/TESTING.md index 77d558fe..3aaf5a85 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -30,7 +30,9 @@ Проверка: `node scripts/mutation-gate.mjs --check` — якоря патчей живы; полный прогон — workflow `mutation-gate.yml` (четыре чересполосных шарда, -`--shard=i/4`), перед стабильным релизом и по понедельникам. Дешёвая половина +`--shard=i/4`) каждую ночь по расписанию (01:00 UTC); в цикле разработки и в +релизном гейте он не участвует — проверяет тесты, а не продукт; отказ сам +заводит issue с отчётом (#472, #513). Дешёвая половина идёт с юнитами: `test/mutation-gate.test.mjs`. Локально для дельты задачи — `node scripts/mutation-gate.mjs --changed origin/dev..HEAD`: гоняются только мутанты, чьи patch-файлы или **входы гарда** задеты диффом (#332, #475, #492). diff --git a/scripts/mutation-gate.mjs b/scripts/mutation-gate.mjs index cb2608e4..625fbafd 100644 --- a/scripts/mutation-gate.mjs +++ b/scripts/mutation-gate.mjs @@ -22,8 +22,9 @@ // worktree → патч → сборка бандла → бандл в demo/srv/assets → тест. Тест, // оставшийся зелёным, — это провал гейта, а не успех теста. // -// Прогон дорогой (пересборка бандла на мутанта), поэтому его место — перед -// стабильным релизом (.github/workflows/mutation-gate.yml), не на каждой бете. +// Прогон дорогой (пересборка бандла на мутанта) и проверяет тесты, а не +// продукт, поэтому его место — ночное расписание (.github/workflows/ +// mutation-gate.yml, #513), вне цикла разработки и релиза; отказ — issue. // Дешёвая часть — «патчи применимы, guard-файлы существуют» — живёт в // test/mutation-gate.test.mjs и идёт с обычными юнитами: реестр, отставший от // кода, хуже отсутствующего, потому что выглядит защитой. diff --git a/test/mutation-gate.test.mjs b/test/mutation-gate.test.mjs index b21dbf35..2dfdcf98 100644 --- a/test/mutation-gate.test.mjs +++ b/test/mutation-gate.test.mjs @@ -260,6 +260,12 @@ const validateWorkflowText = readWorkflowFile( new URL('../.github/workflows/validate.yml', import.meta.url), 'utf8', ); +test('#513 AC1: полный мутационный прогон идёт каждую ночь, не раз в неделю и не перед релизом', () => { + assert.match(mutationWorkflow, /- cron: '0 1 \* \* \*'/, 'ежедневно 01:00 UTC'); + assert.ok(!/cron: '[^']*\* [0-6]'/.test(mutationWorkflow), 'недельного расписания (день недели) быть не должно'); + assert.ok(!mutationWorkflow.includes('перед стабильным релизом'), 'полный прогон — не шаг релиза'); +}); + test('#472 AC1: у расписания и ручного запуска разные concurrency-группы', () => { assert.match(mutationWorkflow, /group: mutation-gate-\$\{\{ github\.event_name \}\}/); });