From ac8eac60343c9712c4fdcb73e3d9542ce75f4dbf Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 27 Sep 2026 11:13:18 +0000 Subject: [PATCH] docs: review document for #658 Issue: #658 User-Visible: no --- docs/reviews/CODE-REVIEW-658-r1.md | 162 +++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 docs/reviews/CODE-REVIEW-658-r1.md diff --git a/docs/reviews/CODE-REVIEW-658-r1.md b/docs/reviews/CODE-REVIEW-658-r1.md new file mode 100644 index 00000000..e76b2aaa --- /dev/null +++ b/docs/reviews/CODE-REVIEW-658-r1.md @@ -0,0 +1,162 @@ +# CODE-REVIEW-658-r1 + +Материал раунда: `git log --oneline origin/dev..HEAD` / `git diff origin/dev...HEAD`, +SHA `bdac4b4fdc88c7c3a48604163636a3c031830b63` (рабочая копия на нём). Заход r1, +блокирующих циклов израсходовано 0 из 4. + +## Скоуп + +Issue #658, класс B (`.github/workflows/*.yml`, `test/**`, +`scripts/workflow-jobs.mjs`) + C (`docs/DEVELOPMENT.md`, `PROCESS.md`, +`docs/TESTING.md`). Три хрупких места CI-обвязки: + +1. `ubuntu-latest` → `ubuntu-24.04` во всех job на раннере (аудит: 43 места, + issue называет 44 — расхождение в самом тексте issue, не в коде; итоговый + коммит верно пишет «43»). +2. `timeout-minutes` на 26 job, у которых его не было. +3. Cron-расписания `_nightly`, `mutation-gate`, `process-metrics` (и заодно + `performance.yml`) сдвинуты с круглых минут; `_nightly` получил шаг + предупреждения о сдвиге старта > 60 мин. + +Один squash-коммит `bdac4b4f`, трейлеры `Issue: #658` и `User-Visible: no` +корректны (изменение не видно пользователю продукта — чисто инфраструктурное). +При `User-Visible: no` правка обоих changelog не требуется — не сделана, +верно. + +## Как проверялось + +Зелёный Validate уже подтверждён на этом SHA +(https://github.com/Matysh/houseplan-card/actions/runs/36314264957), поэтому +`npx tsc --noEmit`, `npm test` целиком и `npm run build` со сверкой бандла не +перегонялись — они там уже прошли на этом материале. Диф не трогает `src/**`, +`node scripts/check-docs.mjs` не требуется. + +Прогнано лично в этом раунде (диф — чисто CI-обвязка + тесты обвязки; ни один +из штатных смоук/golden/backend/invariants-гейтов не применим, так как diff не +трогает `src/**`, `custom_components/**/*.py` и геометрию): + +- `node --test test/workflow-hygiene.test.mjs` — все 5 тестов зелёные. +- Свойство «тест умеет падать» проверено мутацией **в памяти**, без изменения + файлов репозитория (через прямой вызов `parseJobSettings` на модифицированном + тексте `validate.yml`): + - вернул `runs-on: preflight` на `ubuntu-latest` → тест «образ закреплён» + находит `floating: ['preflight']`; + - убрал `timeout-minutes: 15` у `preflight` → тест «у каждой job есть + timeout» находит `missing: ['preflight']`. + Обе мутации красят соответствующую проверку — доказательство не голословно. +- Прочитан код `parseJobSettings` (`scripts/workflow-jobs.mjs:134-165`): + разбирает только объявленные job-уровневые скаляры на отступе 4 после + `jobs:`, комментарии и содержимое шагов (`run: |`) корректно исключены + (`isBlank` фильтрует строки с `#`, отступ шагов больше 4). Проверено чтением, + не исполнением, для полноты покрытия всех 19 файлов workflow — сам разбор + подтверждён мутацией выше. +- Прочитан и вручную протрассирован bash-шаг «Сдвиг старта ночи против + расписания» (`_nightly.yml`): для входа `SCHEDULE='17 2 * * *'`, + `NOW_EPOCH` в районе 07:47 UTC даёт `lag=330` и警告; при пересечении полуночи + (`NOW` вскоре после 00:00, план вечера предыдущих суток) корректно вычитает + сутки. Это же покрыто автотестом `test/workflow-hygiene.test.mjs:99-125`, + который реально исполняет скрипт через `bash -c`, а не пересказывает его — + запуск подтверждён (см. выше, все 5 тестов ok). +- Сверены количества: `git diff … | grep -c '^+.*timeout-minutes:'` = 26, + `grep -c '^-.*timeout-minutes:'` = 0 — ровно 26 добавленных таймаутов без + удалений, как заявлено в AC2. +- Проверено `grep -rn "runs-on:.*ubuntu-latest"` по всем `.github/workflows/` + после диффа — совпадений нет (одно вхождение строки `ubuntu-latest` в + `_process.yml:946` — исторический комментарий про поведение установщика + Claude Code, не значение `runs-on`). +- Числа таймаута release-гейта прослежены до источника: `release-gate.mjs` + (`waitForGreenWorkflow`, `timeoutMs = 60 * 60 * 1000` — 60 мин, вызывается + дважды: Validate и `performance.yml`) и `e2e-gate.mjs` + (`VALIDATE_APPEAR_MS + VALIDATE_TOTAL_MS` = 3 + 45 = 48 мин, в комментарии + округлено до «45» — округление в консервативную сторону, неравенство + 60+60+48=168 < 180 всё равно верно). +- Сверены упоминания времени вне workflow-файлов: `PROCESS.md` и + `docs/TESTING.md` обновлены с «01:00 UTC» на «00:43 UTC» синхронно с + `mutation-gate.yml`; `test/mutation-gate.test.mjs` AC1 обновлён на новый + cron той же строкой. Остальные упоминания старых времён (`docs/reviews/ + CODE-REVIEW-513-*`, `CODE-REVIEW-637-*`) — исторические документы прошлых + раундов, не подлежат правке. +- Заголовок `## Moving the runner image (#658)` в `docs/DEVELOPMENT.md:482` + сверен посимвольно с regex теста + (`/^## Moving the runner image \(#658\)$/m`) — совпадает. + +## AC · чем доказан · чем краснеет + +| AC | Чем доказан | Чем краснеет | +|---|---|---| +| 1. Единый `ubuntu-24.04` во всех job, тест по тексту, запись в DEVELOPMENT.md | `test/workflow-hygiene.test.mjs` тест 2 (образ закреплён, один на все workflow, заголовок раздела найден) | Мутация «вернуть `ubuntu-latest` у одной job» → `floating` непусто (проверено выше в памяти) | +| 2. `timeout-minutes` на 26 job, тест «у каждой есть» | `test/workflow-hygiene.test.mjs` тест 3 | Мутация «убрать одну строку timeout-minutes» → `missing` непусто (проверено выше) | +| 3. Cron на некруглых минутах + предупреждение о сдвиге > 60 мин | `test/workflow-hygiene.test.mjs` тесты 4 и 5 (второй реально исполняет bash-шаг) | Тест 4: мутация cron на `30 2 * * *` регексом `% 15 === 0` красит `round`; тест 5 явно проверяет границу 60/61 мин (assert on/off) и переход через полночь | + +Все три AC — защитные по духу (гарды против регресса инфраструктуры), таблица +заполнена по каждому с named-мутацией и результатом, пустых столбцов нет. + +## Находки + +Нет. High: 0, Medium: 0, Low: 0. + +Отдельно отмечено (не находка, а расхождение исходного текста issue, не +кода): issue называет 44 места с `ubuntu-latest`, фактический аудит и +итоговый коммит — 43; расхождение не влияет на полноту исправления (сошлись +все места, что нашёл grep по факту). + +## Что проверено и корректно + +- Все 19 файлов `.github/workflows/*.yml` без плавающего `ubuntu-latest` в + `runs-on` (кроме одного текстового упоминания в комментарии, не влияющего + на исполнение). +- 26 добавленных `timeout-minutes`, без удалений; значения по ориентирам из + issue где они менялись (frontend 40, backend 30, golden 45, preflight 15, + proof 10, релиз/паблиш 20–30) — совпадают; там, где ориентир не совпадает + (например `smoke` шард — 20, а не рекомендованные 45), это уже + существовавшее до этой задачи значение, issue называет их «ориентирами», не + жёстким контрактом, и не требует их менять. +- Таймаут `gate` в `release.yml` (180 мин) арифметически больше суммы + собственных ожиданий (60+60+48), с чем ссылается комментарий в коде. +- Шаг обнаружения сдвига старта ночи корректно обрабатывает переход через + полночь и границу 60/61 мин, что подтверждено исполнением реального + bash-кода в тесте. +- Тонкие вызывающие workflow (`process.yml`, `process-reconcile.yml`, + `process-resume.yml`) корректно не входят в проверку `runs-on`/ + `timeout-minutes` — это `uses:`-обёртки без job на раннере, фильтр + `!job.uses` в тесте это учитывает верно. +- Числа синхронизированы вне workflow-файлов: `PROCESS.md`, `docs/TESTING.md`, + `test/mutation-gate.test.mjs` — один источник (сам `mutation-gate.yml`) и + везде отражено одно и то же новое время. +- Не-скоуп соблюдён: пересъёмки golden/скриншотов и `performance.yml` на + зеркалах (#656 п.4) в диффе нет — и не должно быть. + +## Чего не проверял + +- Полные `npx tsc --noEmit`, `npm test` (весь набор), `npm run build` + + сверку трёх копий бандла — не перегонял лично; засчитан зелёный Validate на + этом же SHA (см. ссылку выше), это ровно то, что просит §8 при подтверждённом + зелёном прогоне на материале. +- Смоки, `golden:verify`, `pytest tests_backend`, `npm run invariants` — + сознательно не прогонял: диф не трогает `src/**` в части рантайма, рендера, + Python или геометрии, а `smoke-select.mjs` по такому диффу (только + `.github/workflows`, `test/`, `scripts/workflow-jobs.mjs`, `docs/*.md`) не + даёт релевантных прямых совпадений — гейты вне применимости диффа, не + пропущенный гейт. +- Performance-профили (`performance.yml` полностью) — в AC не названы, + сознательно не прогонял. +- Реальный прогон изменённых workflow на GitHub Actions (сработает ли новый + cron, действительно ли `ubuntu-24.04` доступен раннерам, реальный тайминг + job) — по определению недоступен ревьюеру до мержа; риск принят как + стандартный для инфраструктурных PR такого рода, дополнительно снижен тем, + что `ubuntu-24.04` — текущий образ (не новый), т.е. runs-on меняется на уже + используемый ярлык, а не на непроверенный. + +--- + + + +## Материал раунда + +- Ветка: `issue/658-ci-hygiene`, коммит `bdac4b4fdc88` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `4e64019b42ae355cda84b020a188621551b5783a` + ``` + git log --all --format='%H %T' | grep 4e64019b42ae + ``` +- Тело issue: `0549b5bbf10a565d31c5ec6d826d7c35dc07fdbadf8f56b04f2a29f3eb11189a` +- Вердикт конвейера: `green` · High 0