mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
Four independent cuts into the 2-4 hour full run, none touching the contract "a mutant must turn its guard red": - guardNeedsBundle: rollup runs only for guards that open the built bundle (demo/ smokes, golden captures, bundle:sync) — 68 of 253 registry entries. Unit and backend guards never read dist/ as a build artifact (verified against every test that mentions dist/**: they read the git checkout or synthetic files), so 185 mutants skip the most expensive step entirely. - seedTestBuild + incremental tsc: the mutant worktree starts from the main tree's warm test-build/ and .tsbuildinfo; tsc compares file hashes, not mtimes, so the fresh checkout stays warm and only the mutated delta is recompiled. This also speeds up the long guards that run tsc themselves. - --changed[=range]: run only mutants whose patch files are touched by the diff (origin/dev..HEAD by default). An empty selection is an honest success with an explicit message — the full registry remains the pre-release contract, per the workflow comment. - --shard=i/n: deterministic interleaved slices; the workflow runs a 4-way matrix, and a warm test-build step feeds every shard. Interleaving spreads the expensive browser mutants across shards instead of clumping them. Measured per mutant on this machine: unit 12-13 s (was ~50-70 s), backend 6 s, browser 32 s (unchanged — the bundle is genuinely needed there). Full run estimate drops to ~70 sequential minutes, ~20 on four shards. Unit coverage: guard classification on real registry shapes, a floor on both classes so the split cannot silently collapse, changed-selection semantics, and shard completeness/disjointness with an anti-clumping bound. Issue: #332 User-Visible: no
88 lines
3.8 KiB
YAML
88 lines
3.8 KiB
YAML
name: Мутационный гейт
|
||
|
||
# Реестр известных поломок (issue #85): каждый мутант ломает продуктовый код
|
||
# известным способом, и объявленный тест ОБЯЗАН на этом покраснеть. Тест,
|
||
# оставшийся зелёным на сломанном коде, ничего не защищает — он лишь выглядит
|
||
# защитой, и это хуже его отсутствия.
|
||
#
|
||
# Прогон дорогой, поэтому он не входит в Validate и не идёт на каждый push.
|
||
# Его место — перед стабильным релизом (PROCESS.md §8) и раз в неделю по
|
||
# расписанию, чтобы дрейф тестов не копился до релиза. Дешёвая половина —
|
||
# «якоря патчей живы, guard-файлы существуют» — идёт с обычными юнитами:
|
||
# test/mutation-gate.test.mjs.
|
||
#
|
||
# #332: бандл собирается только мутантам с браузерным гвардом (guardNeedsBundle),
|
||
# компиляция тестов в worktree стартует с тёплого test-build (инкрементальный
|
||
# tsc), а реестр режется на четыре чересполосных шарда — полный прогон
|
||
# укладывается в десятки минут вместо часов. Локальный дифф-режим:
|
||
# node scripts/mutation-gate.mjs --changed origin/dev..HEAD
|
||
|
||
on:
|
||
workflow_dispatch:
|
||
inputs:
|
||
ref:
|
||
description: Git ref whose mutation guards must be proved
|
||
required: false
|
||
default: dev
|
||
schedule:
|
||
# Понедельник, 05:20 UTC — до начала рабочего дня владельца.
|
||
- cron: '20 5 * * 1'
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
concurrency:
|
||
group: mutation-gate
|
||
cancel-in-progress: true
|
||
|
||
jobs:
|
||
mutants:
|
||
name: "Мутанты: каждый обязан красить тесты (шард ${{ matrix.shard }} из 4)"
|
||
runs-on: ubuntu-latest
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
shard: [1, 2, 3, 4]
|
||
# Шард ~64 мутантов × свой guard; бандл собирают только браузерные гварды.
|
||
# Час — потолок против зависшего Chromium.
|
||
timeout-minutes: 60
|
||
steps:
|
||
- uses: actions/checkout@v7
|
||
with:
|
||
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || 'dev' }}
|
||
fetch-depth: 0
|
||
|
||
- uses: actions/setup-node@v7
|
||
with:
|
||
node-version: 22
|
||
cache: npm
|
||
|
||
- run: npm ci
|
||
|
||
- uses: actions/setup-python@v7
|
||
with:
|
||
python-version: '3.13'
|
||
|
||
- name: Установить backend test dependencies
|
||
run: pip install pytest voluptuous pytest-homeassistant-custom-component home-assistant-frontend
|
||
|
||
- name: Кэш браузеров Playwright
|
||
id: pw
|
||
uses: actions/cache@v6
|
||
with:
|
||
path: ~/.cache/ms-playwright
|
||
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
|
||
|
||
- name: Установить Chromium
|
||
if: steps.pw.outputs.cache-hit != 'true'
|
||
run: npx playwright install --with-deps chromium
|
||
|
||
- name: Реестр применим к текущему коду
|
||
run: node scripts/mutation-gate.mjs --check
|
||
|
||
- name: Тёплый test-build для инкрементальной компиляции мутантов
|
||
run: npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs
|
||
|
||
- name: Каждый тест ловит свою поломку
|
||
run: node scripts/mutation-gate.mjs --shard=${{ matrix.shard }}/4
|