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.14' - name: Установить backend test dependencies run: | # Точные версии — в tests_backend/requirements.txt (#392): без них # резолвер выбирает набор сам, и «зелёный backend» значит разное # в разные дни. pip install -r tests_backend/requirements.txt pip list --format=columns | grep -Ei 'homeassistant|voluptuous|^pytest ' - 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