Files
orchestrator/docs/history/LESSONS_2026-06-07_autonomy-closure.md
2026-06-07 19:24:49 +03:00

6.4 KiB
Raw Blame History

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) — ДВЕ причины

  1. ложный check_staging_status FAILED: staging_check падает на C9a/C9b (sandbox e2e branch + analyst-job-in-queue), т.к. bot-токены SANDBOX-проекта не настроены — НЕ регресс кода.
  2. 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 ожил).

Уроки

  1. Self-hosting safety (сквозной принцип): прод-орк обслуживает ВСЕ проекты. Нельзя авто- откатывать/рестартить self в рамках задачи; нельзя пушить main. ORCH-21 post-deploy для self-hosting = alert-only, авто-rollback только для не-self репо.
  2. TDD без доводки (повтор ORCH-58 и ORCH-65 v1): тесты есть, реализация/wiring не подключены к боевому пути → мёртвый код + врущая дока. Reviewer обязан грепать вызовы из прод-кода, не только наличие функции.
  3. Concurrency-баги ловятся итеративно: ORCH-65 3 прохода reviewer (мёртвый guard → race condition side-effects-before-claim → approve) — каждый раз НОВЫЙ реальный дефект, не зацикливание. Atomic-claim ДО side-effects — обязательное правило.
  4. При красном CI + зелёных локальных тестах — ПЕРВЫМ делом df -h / и docker system df, не копаться в коде. После disk-full обязателен рестарт Gitea (queue залипает).
  5. Bootstrap-разрыв: задача про автономность деплоя не может задеплоить себя автономно, пока её механизм не в проде. Последний прод-деплой каждого такого фикса — вручную.
  6. Перед прод-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.