6.4 KiB
6.4 KiB
Lessons Learned — 2026-06-07: замыкание автономности self-deploy (5 задач в прод)
Итог
За одну сессию закрыты в прод 5 задач, завершающих автономный self-deploy эпика ORCH-54:
| Задача | Что | Прод-коммит |
|---|---|---|
| ORCH-58 | provenance retag-guard (свежесть staging-образа перед BUILD-ONCE) | 094b5e2 |
| ORCH-60 | reconciler не трогает escalated/Blocked/Needs-Input | d4c6cc0 |
| ORCH-61 | фикс петли deploy-staging (staging_verdict: waive sandbox-infra FAILs C9a/C9b) | e18947d |
| ORCH-21 | post-deploy мониторинг прода + auto-rollback (self-hosting=alert-only) | f85e449 |
| ORCH-65 | job-reaper + stale merge-lease reclaim + idempotent merge | bb03350 |
Главное: после ORCH-60/61 конвейер впервые провёз задачи (ORCH-21/65) через deploy-staging автономно без отката; после ORCH-65 (job-reaper в проде) зомби-job и зависшие merge-lease лечатся сами. Последняя ручная точка автономного деплоя закрыта.
Класс багов: «процесс умер — ресурс захвачен навсегда» (ORCH-65)
Три связанных отказа, все воспроизвелись на ORCH-58/60/61/21:
- zombie jobs: агент завершился/умер, строка jobs осталась running. requeue_running_jobs() спасает только на старте процесса; зомби без рестарта не лечился → при concurrency=1 встаёт конвейер ВСЕХ проектов. (jobs 236/239/242/254/265 — все зомби за сессию.)
- stale merge-lease: merge-gate берёт .merge-lease-.json, делает rebase+re-test green, а на финальном merge процесс умирает с зажатым lease → merge не докатывается.
- неидемпотентный merge: re-drive повторно пытается слить уже слитый PR. Фикс: фоновый job_reaper (паттерн reconciler, dead_ticks streak + мёртвый pid + exit_code, атомарный reap-claim, never-raise, kill-switch, снимок в /queue) + проактивный lease-reclaim по pid + guard pr_already_merged ПЕРЕД merge.
Петля deploy-staging (ORCH-61) — ДВЕ причины
- ложный check_staging_status FAILED: staging_check падает на C9a/C9b (sandbox e2e branch + analyst-job-in-queue), т.к. bot-токены SANDBOX-проекта не настроены — НЕ регресс кода.
- no-changes для action-стадий (деплой = рестарт/retag, не правка → коммитить нечего). Фикс: staging_verdict waive sandbox-infra-only FAILs.
Инфра-каскад от переполненного диска (инцидент дня)
- Частые build-once/--build-staging пересборки за день забили docker build cache до 11 ГБ → диск 100% → CI red (No space left).
- ДАЖЕ после чистки диска Gitea осталась в сломанном состоянии: внутренняя queue (/data/gitea/queues/common/*.log) залипла → post-receive hook 500 → actions tasks НЕ создаются, CI не триггерится вовсе (статус пустой, не failure). runner при этом online+idle.
- Лечение: docker builder prune -af + рестарт Gitea (queue распускается → CI ожил).
Уроки
- Self-hosting safety (сквозной принцип): прод-орк обслуживает ВСЕ проекты. Нельзя авто- откатывать/рестартить self в рамках задачи; нельзя пушить main. ORCH-21 post-deploy для self-hosting = alert-only, авто-rollback только для не-self репо.
- TDD без доводки (повтор ORCH-58 и ORCH-65 v1): тесты есть, реализация/wiring не подключены к боевому пути → мёртвый код + врущая дока. Reviewer обязан грепать вызовы из прод-кода, не только наличие функции.
- Concurrency-баги ловятся итеративно: ORCH-65 3 прохода reviewer (мёртвый guard → race condition side-effects-before-claim → approve) — каждый раз НОВЫЙ реальный дефект, не зацикливание. Atomic-claim ДО side-effects — обязательное правило.
- При красном CI + зелёных локальных тестах — ПЕРВЫМ делом df -h / и docker system df, не копаться в коде. После disk-full обязателен рестарт Gitea (queue залипает).
- Bootstrap-разрыв: задача про автономность деплоя не может задеплоить себя автономно, пока её механизм не в проде. Последний прод-деплой каждого такого фикса — вручную.
- Перед прод-retag (build-once SOURCE_IMAGE=staging): проверить revision-label staging- образа == целевой main HEAD, иначе guard fail-closed (by design). Если != → пересобрать --build-staging GIT_SHA=.
Ручная доводка прод-deploy (схема до ORCH-65 в проде)
cancel zombie job → park task In Progress → merge PR (Gitea pulls/{n}/merge Do=merge, CI green) → --build-staging GIT_SHA=
(проставит label) → rollback-снимок → --deploy с EXPECTED_REVISION= (guard сверит → retag → health 200) → Plane Done + UPDATE tasks stage=done.Follow-up (Backlog)
- ORCH-62: авто-prune docker build cache (cron/daemon.json defaultKeepStorage).
- ORCH-63: мониторинг диска mva154 + алерт >85%.
- ORCH-64: починить NTP/часы mva154 (ушли ~+3ч от UTC).
Осталось в эпике ORCH-54
ORCH-22 (security-гейт), ORCH-59 (Confirm Deploy статус), ORCH-23 (budget circuit-breaker), P2: ORCH-57, ORCH-51.