Files
houseplan-card/docs/reviews/CODE-REVIEW-658-r1.md
T
2026-09-27 11:13:18 +00:00

13 KiB
Raw Blame History

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