ci: закрепить образ раннера, таймауты job и некруглые cron (#658)

`ubuntu-latest` с 19.10.2026 переезжает на Ubuntu 26, а golden, скриншоты
документации и перф-бюджеты сняты на текущем образе: все 43 job на раннере
теперь явно на `ubuntu-24.04`, один образ на все workflow. 26 job получили
`timeout-minutes` по наблюдённой длительности с запасом; гейт релиза — 180,
больше суммы собственных ожиданий (60 + 60 + 45). Расписания ушли с круглых
минут (ночь 02:17, мутанты 00:43, метрики 05:23, полный перф 04:11), ночь
пишет в summary сдвиг старта и предупреждает, если он больше часа.

test/workflow-hygiene.test.mjs держит все три правила по тексту workflow
(разбор `parseJobSettings` в scripts/workflow-jobs.mjs) и исполняет шаг
сдвига старта настоящим bash; порядок осознанного подъёма образа —
docs/DEVELOPMENT.md.

Issue: #658
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
This commit is contained in:
Claude
2026-09-27 13:57:21 +03:00
parent 6fc789e4c8
commit bdac4b4fdc
22 changed files with 302 additions and 54 deletions
+30
View File
@@ -479,6 +479,36 @@ Two of these are branches upstream, not releases — `home-assistant/actions`
branch head was read. They have no tags to follow; the only honest record is
"this commit, read on this day".
## Moving the runner image (#658)
Every job that runs on a GitHub runner names an explicit image version in
`runs-on:`, and all workflows name the same one; `test/workflow-hygiene.test.mjs`
rejects a floating label such as `ubuntu-latest` and any drift between files.
The reason is the evidence tied to the image: golden baselines, documentation
screenshots and performance budgets were captured on it with the pinned
Playwright/Chromium (#455, #557), and Chromium's system libraries come from the
image itself (the install steps deliberately skip `--with-deps`). A floating
label moves under that evidence — `ubuntu-latest` becomes Ubuntu 26 from
2026-10-19 (actions/runner-images#14748) — and would turn a day with no change
into mass golden `different` and a red performance smoke.
Move the image on purpose, as its own infra issue:
1. change `runs-on:` in every workflow in one commit;
2. capture golden in CI on the new image and accept the differences with
review (`npm run golden:accept -- --reviewed …`), re-capture the documentation
screenshots (`demo/docs/capture.mjs`);
3. run the full Validate and `performance.yml`, and recalibrate a budget only
with measured evidence next to the number (the #483 and #675 pattern);
4. mirror the thin callers into `main` (see `workflow_sync` in `validate.yml`)
and remember that `release.yml`, `performance.yml` and the other files `main`
executes pick the new image up only with the next stable promotion.
The same test requires `timeout-minutes` on every runner job (at most 180; the
default is 360) and keeps `cron` off minutes 0/15/30/45, which GitHub's
scheduler delays by hours. A job that waits for other runs, such as the release
gate, gets a timeout above the sum of its own waits and says so in a comment.
## What the review model is allowed to do (#556)
The `model_review` job is the only untrusted stage of the review pipeline: it