117 lines
5.6 KiB
YAML
117 lines
5.6 KiB
YAML
work_item: ORCH-093
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-09
|
||
model_used: claude-opus-4-8
|
||
title: "Ретрай транзиентных merge-ошибок Gitea (405/5xx) + гард already-in-main"
|
||
framework: pytest
|
||
scope: >
|
||
Покрывает src/merge_gate.py::merge_pr (retry-loop + классификация транзиент/терминал) и
|
||
ensure_open_pr (гард «ветка уже в main»), новые флаги src/config.py (ORCH_MERGE_RETRY_*) и
|
||
обработку already-in-main в stage_engine._handle_merge_verify. Вне покрытия: реальная сеть Gitea,
|
||
STAGE_TRANSITIONS/QG_CHECKS, схема БД.
|
||
notes: >
|
||
httpx мокается monkeypatch'ем (по образцу tests/test_merge_gate.py / test_orch073_merge_pr.py):
|
||
последовательности ответов на POST /pulls/{n}/merge и GET /pulls/{n}. time.sleep патчится в no-op,
|
||
чтобы backoff не замедлял тесты. git-операции гарда (rev-list/merge-base) мокаются через
|
||
monkeypatch subprocess.run. Полный регресс tests/ должен оставаться зелёным; считается регрессом
|
||
любое падение существующих test_merge_gate*/test_merge_verify*/test_orch073*.
|
||
|
||
tests:
|
||
- id: TC-01
|
||
type: unit
|
||
description: "merge_pr: POST даёт 405,405,200 -> возвращает (True, merged PR #n); ровно 3 POST; ложного False нет (AC-1)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-02
|
||
type: unit
|
||
description: "merge_pr: POST даёт 503 (5xx), затем 200 -> ретрай -> (True, ...) (AC-1)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-03
|
||
type: unit
|
||
description: "merge_pr: POST бросает httpx Timeout/сетевую ошибку в 1-й попытке, затем 200 -> ретрай -> (True, ...); never-raise (AC-1, AC-6)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-04
|
||
type: unit
|
||
description: "merge_pr: реальный конфликт 409 + GET /pulls/{n} mergeable=False -> (False, ...) без доп. POST (терминал, быстрый HOLD) (AC-2)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-05
|
||
type: unit
|
||
description: "merge_pr: неоднозначный 409 + GET /pulls/{n} mergeable=True -> классифицирован как транзиент -> ретрай -> 200 -> (True, ...) (AC-2)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-06
|
||
type: unit
|
||
description: "merge_pr: 403 (нет прав) -> немедленно (False, ...) без ретрая (терминал) (AC-2)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-07
|
||
type: unit
|
||
description: "merge_pr: 405 на всех N попытках -> (False, 'merge failed after N attempts: HTTP 405') с понятным reason (AC-3)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-08
|
||
type: unit
|
||
description: "merge_pr: kill-switch merge_retry_enabled=False -> ровно один POST (one-shot, как сейчас) при 405 -> (False, ...) (AC-5, AC-3)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-09
|
||
type: unit
|
||
description: "ensure_open_pr: открытого code-PR нет, rev-list --count origin/main..branch == 0 -> ('already-in-main', ...); POST /pulls НЕ вызывается (AC-4)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-10
|
||
type: unit
|
||
description: "ensure_open_pr: открытого PR нет, есть невлитые коммиты (count>0) -> создаёт PR ('created', ...) (регресс прежнего поведения) (AC-4)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-11
|
||
type: unit
|
||
description: "ensure_open_pr: git-ошибка проверки гарда -> never-raise, безопасный кортеж, без падения (AC-6)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-12
|
||
type: unit
|
||
description: "merge_pr/ensure_open_pr: любая непойманная httpx/parse ошибка -> (False/failed, ...) кортеж, исключение не пробрасывается (never-raise) (AC-6)"
|
||
module: tests/test_merge_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-13
|
||
type: unit
|
||
description: "config: дефолты merge_retry_enabled/merge_retry_max_attempts/backoff_base/backoff_max присутствуют и читаются из ORCH_MERGE_RETRY_* env (AC-5)"
|
||
module: tests/test_config.py
|
||
expected: PASS
|
||
|
||
- id: TC-14
|
||
type: integration
|
||
description: "_handle_merge_verify: ensure_open_pr -> 'already-in-main' пропускает merge_pr, verify_merged_to_main (SHA-in-main) подтверждает -> задача доходит до done без мусорного PR (AC-4)"
|
||
module: tests/test_merge_verify.py
|
||
expected: PASS
|
||
|
||
- id: TC-15
|
||
type: integration
|
||
description: "_handle_merge_verify: merge_pr исчерпал ретраи (False) и SHA-in-main не подтверждён -> HOLD + alert (ORCH-071/081 как прежде), задача удержана на deploy, не done (AC-3)"
|
||
module: tests/test_merge_verify.py
|
||
expected: PASS
|
||
|
||
- id: TC-16
|
||
type: integration
|
||
description: "_handle_merge_verify happy-path: транзиент 405x2->200 в merge_pr -> SHA-in-main подтверждён -> done без ложного HOLD (end-to-end под-гейта deploy->done) (AC-1)"
|
||
module: tests/test_merge_verify.py
|
||
expected: PASS
|