fix(ci): give nightly mutation shards headroom and report cancellation accurately

Split the full registry into ten shards without increasing the one-hour
limit. Preserve summary and step outcome separately so cancellation after
194/194 remains red without claiming the summary was missing.

Issue: #795
User-Visible: no
This commit is contained in:
Matysh
2026-10-05 11:04:29 +03:00
parent 865312e0b0
commit aef02229c6
5 changed files with 88 additions and 37 deletions
+17 -18
View File
@@ -8,15 +8,14 @@ name: "Мутационный гейт · тело (#623)"
# Прогон дорогой и проверяет не продукт, а тесты, поэтому он не входит ни в
# Validate, ни в цикл разработки, ни в релизный гейт (#513, решение владельца
# 09.09): каждую ночь по расписанию, отказ — issue с отчётом (#472).
# Мутанты, задетые диффом, конвейер ревью и слияние гоняют отдельно на своём
# кандидате (#510); кандидат беты, `full=true` и ночной Validate их не
# запрашивают (#601) — ночью достаточно этого полного реестра.
# С #709 ревью, слияние, кандидат беты, `full=true` и ночной Validate
# мутантов не запрашивают — ночью достаточно этого полного реестра.
# Дешёвая половина — «якоря патчей живы, guard-файлы существуют» — идёт с
# обычными юнитами: test/mutation-gate.test.mjs.
#
# #332: бандл собирается только мутантам с браузерным гвардом (guardNeedsBundle),
# компиляция тестов в worktree стартует с тёплого test-build (инкрементальный
# tsc), а реестр режется на четыре чересполосных шарда — полный прогон
# tsc), а реестр режется на чересполосные шарды — полный прогон
# укладывается в десятки минут вместо часов. Локальный дифф-режим:
# node scripts/mutation-gate.mjs --changed origin/dev..HEAD
#
@@ -110,20 +109,20 @@ jobs:
fi
mutants:
name: "Мутанты: каждый обязан красить тесты (шард ${{ matrix.shard }} из 6)"
name: "Мутанты: каждый обязан красить тесты (шард ${{ matrix.shard }} из 10)"
needs: material
if: needs.material.outputs.reuse != 'true'
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4, 5, 6]
# Шесть чересполосных шардов (#604): при четырёх шард нёс ~203 мутанта из
# 810 и рос с реестром — 42 мин 10.09, 57 мин 20.09, 61 мин 21.09, и шард
# 2/4 был снят по потолку без единого FAIL. Делитель тот же, что у
# `changed_mutants` в Validate; число шардов повторяется в `--shard=i/6`,
# `--shards=6` и имени job — тест `mutation-gate.test.mjs` держит их
# равными. Бандл собирают только браузерные гварды. Час — потолок против
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# #795: ночь 05.10 (1164 мутанта) заняла 42–60 мин на шести шардах;
# четвёртый отменён по потолку. Десять шардов оставляют 116–117 мутантов
# вместо 194. Оценка по длительностям той ночи — максимум около 39 мин
# с запасом на setup; это прогноз, фактическое время проверяет следующая ночь.
# Матрицу, делители runner/evidence и имя job держит mutation-gate.test.mjs.
# Бандл собирают только браузерные гварды. Час — потолок против
# зависшего Chromium, а не бюджет шарда: шард, упёршийся в него, — сигнал
# снова делить, и отчёт (#472) называет такой шард прерванным, не «ok».
timeout-minutes: 60
@@ -178,7 +177,7 @@ jobs:
run: |
mkdir -p artifacts/mutation-shard-${{ matrix.shard }}
set -o pipefail
node scripts/mutation-gate.mjs --shard=${{ matrix.shard }}/6 2>&1 | tee artifacts/mutation-shard-${{ matrix.shard }}/mutation-shard-${{ matrix.shard }}.log
node scripts/mutation-gate.mjs --shard=${{ matrix.shard }}/10 2>&1 | tee artifacts/mutation-shard-${{ matrix.shard }}/mutation-shard-${{ matrix.shard }}.log
# Исход шага едет в evidence (#604): снятый по timeout-minutes шаг даёт
# `cancelled`, и агрегатор отвергает такой шард как неполный — лог без
# строк FAIL сам по себе зелёным не считается.
@@ -191,7 +190,7 @@ jobs:
--tree=${{ needs.material.outputs.tree }} \
--workflow-sha=${{ job.workflow_sha }} \
--run-id=${{ github.run_id }} --run-attempt=${{ github.run_attempt }} \
--shard=${{ matrix.shard }} --shards=6 \
--shard=${{ matrix.shard }} --shards=10 \
--outcome=${{ steps.gate.outcome }}
- name: Сохранить лог и identity шарда
if: always()
@@ -202,7 +201,7 @@ jobs:
if-no-files-found: warn
retention-days: 30
# Результат нельзя приписывать material, пока не доказаны все шесть шардов —
# Результат нельзя приписывать material, пока не доказаны все десять шардов —
# каждый с identity и с дошедшим до конца прогоном (#549, #604).
# always() нужен при красном мутанте: лог красного шарда всё равно evidence.
evidence:
@@ -228,13 +227,13 @@ jobs:
- name: Проверить полноту и identity
run: |
node scripts/mutation-gate-report.mjs --verify-only \
--logs=artifacts/mutation-logs --shards=6 \
--logs=artifacts/mutation-logs --shards=10 \
--sha=${{ needs.material.outputs.sha }} \
--tree=${{ needs.material.outputs.tree }} \
--workflow-sha=${{ job.workflow_sha }} \
--run-id=${{ github.run_id }} --run-attempt=${{ github.run_attempt }}
# #620: маркер пишется ТОЛЬКО после зелёного агрегатора — все шесть шардов
# #620: маркер пишется ТОЛЬКО после зелёного агрегатора — все десять шардов
# доказаны на одном material. Красный или неполный прогон маркера не оставляет,
# и следующая ночь гонит реестр заново.
green_marker:
@@ -306,7 +305,7 @@ jobs:
run: |
mkdir -p artifacts
node scripts/mutation-gate-report.mjs \
--require-evidence --logs=artifacts/mutation-logs --shards=6 \
--require-evidence --logs=artifacts/mutation-logs --shards=10 \
--sha=${{ needs.material.outputs.sha }} \
--tree=${{ needs.material.outputs.tree }} \
--workflow-sha=${{ job.workflow_sha }} \