Files
orchestrator/docs/architecture/adr/adr-0016-ensure-open-pr-before-merge-verify.md

4.8 KiB
Raw Blame History

ADR-0016: ensure_open_pr — гарантированный код-PR перед merge-verify (ORCH-082)

Статус

Accepted — амендмент к adr-0013 и adr-0014. Детально: docs/work-items/ORCH-082/06-adr/ADR-001-ensure-open-pr-before-merge-verify.md.

Контекст

Merge-verify (ORCH-071/073) — под-гейт ребра deploy → done: детерминированно мержит код-PR в main (merge_pr) и подтверждает merge только по «SHA-в-main» (verify_merged_to_main, ORCH-073). На деплое ORCH-074 (08.06) merge_pr вернул ("False", "no open PR"): у ветки не было открытого PR с head==branch И base=="main". Защита ORCH-073 верно удержала задачу (HOLD, не ложный done), но это лечило следствие.

Первопричина (код-аудит): PR создаётся в конвейере единственной функцией launcher._ensure_pr, вызываемой только на developer-пути и только при свежем worktree-коммите. Любой сценарий без свежего developer-коммита (бойнс без правок, повторный прогон, ручное восстановление ветки/main — случай ORCH-074) оставляет ветку без код-PR. Инвариант «к merge-verify у ветки есть открытый код-PR» в конвейере отсутствовал → блокер автономного деплоя (ORCH-54).

Решение

Аддитивно обеспечить инвариант внутри того же под-гейта, ПЕРЕД merge_pr, не трогая машину стадий:

  1. Новый leaf-актор merge_gate.ensure_open_pr(repo, branch) -> (status, detail) (never-raise): GET …/pulls?state=open с фильтром head.ref==branch И base.ref=="main" (идентичен merge_pr/ORCH-073 FR-3 — авто-docs-PR не считается код-PR) → ("existed", N); иначе POST …/pulls("created", N); гонка «PR exists» → повторный GET → existed (без дублей); любая ошибка → ("failed", reason).
  2. Врезка в _handle_merge_verify ПОСЛЕ резолва validated_revision и ПЕРЕД merge_pr: created|existed → штатно к merge_pr; failed → честный HOLD+alert через новый helper _hold_pr_create_failed (текст «PR создать не удалось» — отличим от not-merged HOLD), задача остаётся на deploy, БЕЗ отката на development.
  3. Kill-switch merge_verify_autocreate_pr_enabled (дефолт True); область — merge_verify_applies (self-hosting / merge_verify_repos). False → поведение ORCH-074 1:1.
  4. launcher._ensure_pr рекомендуется делегировать в ensure_open_pr (единый код создания PR), сохранив прежний триггер «только developer-путь».

Последствия

  • Защита ORCH-073 неприкосновенна и приоритетна: подтверждение merge остаётся ТОЛЬКО verify_merged_to_main (SHA-в-main) + check_main_regression. Создание PR устраняет лишь ложный HOLD «no open PR», но не маскирует реально невлитый код (тот → HOLD как прежде).
  • Без миграций: идемпотентность выводится из Gitea (наличие открытого PR), схема БД не меняется — restart-safe; повторный заход (reaper/reconciler/re-approve) → existed, дублей нет.
  • Инварианты целы: STAGE_TRANSITIONS, QG_CHECKS, схема БД, check_deploy_status, exit-коды хука, merge-gate (ORCH-043), image-freshness (ORCH-058) — без изменений; main не push/force-push; never-raise на всём пути.
  • Наблюдаемость: один однозначный исход в логах на проход — created / existed / failed; HOLD по failed текстуально отличим от HOLD not-merged.
  • Минус: код-PR может создаваться после прохождения гейтов — безопасно, т.к. гейты валидируют код ветки, а merge-verify идёт ПОСЛЕ всех гейтов; PR — лишь механизм слияния, ревью не обходится.