mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
docs: input manifest and exact-candidate merge in TESTING.md and PROCESS.md
Issue: #492 User-Visible: no
This commit is contained in:
+22
@@ -933,6 +933,28 @@ S7-code-review → код-ревью → слияние в dev → S8-merged л
|
||||
ветки и пушем автор мог запушить коммит, и слепой `--force` потерял бы его молча.
|
||||
Расхождение lease — падение прогона, а не предупреждение.
|
||||
|
||||
**В `dev` уезжает точный кандидат, и только проверенный** (#492,
|
||||
`scripts/merge-candidate.mjs`). Ревью длится десятки минут, `dev` за это время
|
||||
двигается; ребейз после вердикта даёт дерево, которого никто не видел, — а чистый
|
||||
ребейз ничего не доказывает: соседняя правка в `dev` меняет поведение без единого
|
||||
конфликта. Шаг слияния поэтому:
|
||||
|
||||
- сверяет вершину ветки с материалом ревью (#312) — иначе `S6-in-progress`;
|
||||
- если `dev` не двигался — push с `--force-with-lease` на текущую вершину;
|
||||
- если двигался — ребейз (конфликт — `S6-in-progress`, как раньше), сравнение
|
||||
patch-id проверенного и получившегося диффа (различие — `S7-code-review`: вердикт
|
||||
к другому диффу не применим, §7.2), публикация кандидата в ветку задачи, ожидание
|
||||
зелёного Validate **на этом SHA** и только затем push в `dev` с lease на ту
|
||||
вершину, поверх которой кандидат собран. Отклонённый lease — `dev` двинулся снова
|
||||
— новая попытка; после третьей — `S6-in-progress` с комментарием;
|
||||
- красный Validate на кандидате или прогон, не появившийся за три минуты, —
|
||||
`S6-in-progress` с ссылкой; `S8-merged` ставится только после push.
|
||||
|
||||
Проверка кандидата — обычный Validate ветки: лёгкий набор плюс диффозависимые
|
||||
гейты. Тяжёлые гейты остаются за кандидатом релиза (#479): слияние не превращает
|
||||
каждое движение `dev` в двадцатиминутный прогон, а проверяет ровно то, что
|
||||
проверил бы пуш той же дельты.
|
||||
|
||||
Поэтому зелёное код-ревью с неудавшимся слиянием ведёт не в `S8-merged`, а в
|
||||
`S6-in-progress`: работа действительно вернулась к автору, только осталась не
|
||||
правка кода, а ребейз. Вердикт при этом в силе, переделывать нечего. После ребейза
|
||||
|
||||
+52
-5
@@ -33,18 +33,65 @@
|
||||
`--shard=i/4`), перед стабильным релизом и по понедельникам. Дешёвая половина
|
||||
идёт с юнитами: `test/mutation-gate.test.mjs`. Локально для дельты задачи —
|
||||
`node scripts/mutation-gate.mjs --changed origin/dev..HEAD`: гоняются только
|
||||
мутанты, чьи patch-файлы или файлы гарда задеты диффом (#332, #475). Бандл
|
||||
собирается только мутантам с браузерным гвардом; компиляция тестов в worktree
|
||||
стартует с тёплого `test-build/` основного дерева.
|
||||
мутанты, чьи patch-файлы или **входы гарда** задеты диффом (#332, #475, #492).
|
||||
Входы гарда — это не только файлы, названные в команде: обёртка
|
||||
(`scripts/*-guard.mjs`) объявляет запускаемые тесты в `export const
|
||||
GUARD_INPUTS` (умолчание `backend-test-guard.mjs` —
|
||||
`tests_backend/test_ha_import_export.py`, действует без третьего аргумента), а
|
||||
от каждого файла гарда берётся замыкание импортов и путей: смок тянет
|
||||
`demo/serve.mjs`, compat-хелперы и фикстуры, pytest-модуль — `conftest.py`.
|
||||
`src/**` в замыкание не входит — это сторона патча (§6.4 ТЗ #492). Дифф,
|
||||
трогающий сам реестр, дополнительно отбирает добавленные и изменённые
|
||||
определения относительно реестра базы (`git show <base>:scripts/mutation-gate.mjs`).
|
||||
Бандл собирается только мутантам с браузерным гвардом; компиляция тестов в
|
||||
worktree стартует с тёплого `test-build/` основного дерева.
|
||||
|
||||
В CI `changed_mutants` добавляет `--ledger=<файл>` — журнал пойманных
|
||||
свидетелей (#481): после каждого пойманного мутанта в файл пишется отпечаток
|
||||
его входов (файлы патча и гарда, объявление мутанта; строка версии продукта
|
||||
нормализована), и мутант с тем же отпечатком в следующем прогоне не гоняется.
|
||||
его входов (файлы патча, все входы гарда по замыканию выше, объявление мутанта;
|
||||
строка версии продукта нормализована), и мутант с тем же отпечатком в следующем
|
||||
прогоне не гоняется.
|
||||
Журнал живёт в кэше Actions по шарду, сохраняется при любом исходе шага, так
|
||||
что отменённый пуш или таймаут не пропадают даром. Полный прогон и `--id`
|
||||
журнал не читают; `--ledger` без `--changed` — ошибка.
|
||||
|
||||
## Manifest входов: какие job запускать и что хешировать (#492)
|
||||
|
||||
Один модуль, `scripts/check-inputs.mjs`, объявляет каждую проверку Validate
|
||||
(`preflight`, `frontend`, `changed_mutants`, `integration`, `smoke`, `golden`,
|
||||
`performance_smoke`, `backend`) через корни и точки входа, а остальное
|
||||
вычисляет: от точек входа берётся замыкание — импорты транзитивно, строковые
|
||||
пути как листья, каталог по строке — все текстовые файлы под ним. Из этого
|
||||
manifest читают и `classify-changes.mjs` (job `changes`: job запускается,
|
||||
если дифф задел хотя бы один её вход), и `gate-reuse.mjs` (ключ реюза =
|
||||
хеш содержимого всех входов job). Два места не могут разойтись: до #492 у
|
||||
бэкенда ключ не знал relay, converter и schema, а golden/perf — `serve.mjs`,
|
||||
`demo.html` и compat-хелперов.
|
||||
|
||||
Правила, которые стоит знать:
|
||||
|
||||
- `validate.yml` — вход toolchain каждой job: правка workflow гоняет всё;
|
||||
- `src/**` — вход только браузерных job; backend от UI не зависит, а
|
||||
`custom_components/houseplan/manifest.json` (версия) держит правило «кандидат
|
||||
релиза прогоняет всё» и для него;
|
||||
- **неизвестный исполняемый вход** — файл под `scripts/`, `demo/`, `test/`,
|
||||
`tests_backend/`, `.github/`, `custom_components/`, `src/`, которого нет в
|
||||
manifest ни одной проверки, — расширяет прогон до полного набора и называется
|
||||
в summary. Лист покрытия (`node scripts/check-inputs.mjs --coverage`,
|
||||
`test/check-inputs.test.mjs`) требует, чтобы каждый такой файл был чьим-то
|
||||
входом либо стоял в `NOT_AN_INPUT` с причиной: новый скрипт без записи —
|
||||
красный юнит, не вечное расширение прогонов;
|
||||
- `--check=<job>` печатает входы, `--why=<файл>` — цепочку, по которой файл
|
||||
стал входом.
|
||||
|
||||
Отрицательные пробы (`test/gate-reuse.test.mjs`, `test/classify-changes.test.mjs`,
|
||||
`test/check-inputs.test.mjs`) держат представителей каждой категории входов и
|
||||
обратную пробу для UI ↔ backend; мутанты `manifest-drops-workflow-input`,
|
||||
`classify-unknown-input-is-unaffected`, `reuse-backend-hashes-ui`,
|
||||
`guard-inputs-ignore-wrapper-defaults`, `registry-diff-not-selected`,
|
||||
`merge-pushes-unvalidated-candidate`, `merge-ignores-lease-rejection`,
|
||||
`nightly-does-not-wait` держат сам протокол.
|
||||
|
||||
Чистые Python-контракты канонизации, которым не нужен Home Assistant, находятся
|
||||
в `tests_backend/test_coordinate_canonicalization_pure.py`. Они обязаны реально
|
||||
исполняться в локальном `pytest tests_backend`, а не исчезать за module-level
|
||||
|
||||
Reference in New Issue
Block a user