4.8 KiB
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, не трогая машину
стадий:
- Новый 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). - Врезка в
_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. - Kill-switch
merge_verify_autocreate_pr_enabled(дефолтTrue); область —merge_verify_applies(self-hosting /merge_verify_repos).False→ поведение ORCH-074 1:1. 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 — лишь механизм слияния, ревью не обходится.