154 lines
7.8 KiB
YAML
154 lines
7.8 KiB
YAML
work_item: ORCH-088
|
||
title: "Serial gate (Этап 1: пакетный автономный режим, serial e2e)"
|
||
scope: "FR-1..FR-5 only. Merge-queue / pre-merge rebase / phases A/B/C / ORCH-83 — out of scope."
|
||
framework: pytest
|
||
|
||
# Принципы тестирования:
|
||
# - чистую логику gate/freeze покрываем unit-тестами на leaf-функциях (без сети/БД где можно);
|
||
# - claim-gate и e2e-последовательность — integration на временной SQLite-БД;
|
||
# - все тесты детерминированы (без реальных Plane/Gitea/прод вызовов — мокируются);
|
||
# - проверяем оба направления kill-switch (вкл/выкл) и never-raise.
|
||
|
||
tests:
|
||
# ---------- FR-1 / AC-1: gate закрыт при активной задаче ----------
|
||
- id: TC-01
|
||
type: unit
|
||
description: "claim_next_job НЕ выбирает analyst-job новой задачи B, если в репо есть задача A со stage!='done' (gate закрыт)"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-02
|
||
type: unit
|
||
description: "serial_gate_applies(repo): enabled + пустой CSV → True для зарегистрированного репо; CSV с членством → True; репо вне CSV → False"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-03
|
||
type: unit
|
||
description: "Job'ы УЖЕ активной задачи (architect/developer/.../deployer) gate'ом НЕ блокируются — единственная активная задача свободно идёт по конвейеру"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
# ---------- FR-1/2 / AC-2: автостарт следующей по достижении done ----------
|
||
- id: TC-04
|
||
type: integration
|
||
description: "После перевода A.stage='done' claim_next_job выбирает analyst-job ожидающей B того же репо (gate открылся автоматически)"
|
||
module: tests/test_serial_gate_e2e.py
|
||
expected: PASS
|
||
|
||
- id: TC-05
|
||
type: integration
|
||
description: "Очередь из 3 задач одного репо обрабатывается строго по одной: пока A не done, ни B, ни C не стартуют; порядок FIFO по jobs.id"
|
||
module: tests/test_serial_gate_e2e.py
|
||
expected: PASS
|
||
|
||
# ---------- FR-4 / AC-3: restart-safe ----------
|
||
- id: TC-06
|
||
type: integration
|
||
description: "Активная задача определяется из БД (tasks.repo + stage!='done'), не из in-memory — после пересоздания воркера/состояния gate остаётся закрытым при A.stage<done"
|
||
module: tests/test_serial_gate_e2e.py
|
||
expected: PASS
|
||
|
||
- id: TC-07
|
||
type: integration
|
||
description: "Freeze переживает рестарт: выставленный в БД freeze читается после пересоздания состояния; следующая задача не стартует"
|
||
module: tests/test_serial_gate_freeze.py
|
||
expected: PASS
|
||
|
||
# ---------- FR-3 / AC-4: per-repo ----------
|
||
- id: TC-08
|
||
type: unit
|
||
description: "Активная задача в orchestrator (stage<done) НЕ блокирует claim analyst-job задачи в enduro-trails (gate фильтруется по repo)"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-09
|
||
type: unit
|
||
description: "Freeze репо orchestrator не влияет на claim/старт задач enduro-trails"
|
||
module: tests/test_serial_gate_freeze.py
|
||
expected: PASS
|
||
|
||
# ---------- FR-5 / AC-5: rollback-freeze + алерт ----------
|
||
- id: TC-10
|
||
type: unit
|
||
description: "post-deploy вердикт DEGRADED → выставляется durable per-repo freeze (запись в БД) + вызывается Telegram-алерт (send_telegram замокан, проверяется вызов)"
|
||
module: tests/test_serial_gate_freeze.py
|
||
expected: PASS
|
||
|
||
- id: TC-11
|
||
type: integration
|
||
description: "При активном freeze репо claim_next_job НЕ выбирает analyst-job следующей задачи, даже если нет задач stage<done (деградировавшая уже done — BR-7)"
|
||
module: tests/test_serial_gate_freeze.py
|
||
expected: PASS
|
||
|
||
- id: TC-12
|
||
type: integration
|
||
description: "Ручное снятие freeze → следующая задача стартует на ближайшем цикле; freeze помечается cleared в БД"
|
||
module: tests/test_serial_gate_freeze.py
|
||
expected: PASS
|
||
|
||
# ---------- FR-1 / AC-6: нет stale-base ----------
|
||
- id: TC-13
|
||
type: integration
|
||
description: "Ветка B не создаётся (ни Gitea-ветка, ни worktree), пока gate закрыт — _create_gitea_branch/ensure_worktree для B не вызывается при A.stage<done"
|
||
module: tests/test_serial_gate_branch.py
|
||
expected: PASS
|
||
|
||
- id: TC-14
|
||
type: integration
|
||
description: "После A.stage='done' (A влита в main) база ветки B = origin/main с кодом A: git merge-base --is-ancestor <sha A> <base B> истинно (на временном git-репо)"
|
||
module: tests/test_serial_gate_branch.py
|
||
expected: PASS
|
||
|
||
# ---------- AC-7: kill-switch / нулевая регрессия ----------
|
||
- id: TC-15
|
||
type: unit
|
||
description: "serial_gate_enabled=False → claim_next_job SQL/поведение идентичны исходным (gate инертен); B стартует независимо от A"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-16
|
||
type: unit
|
||
description: "Репо вне serial_gate_repos (CSV непуст) → gate не применяется к этому репо"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
# ---------- AC-8 / AC-9: never-raise ----------
|
||
- id: TC-17
|
||
type: unit
|
||
description: "Ошибка БД при вычислении gate в claim → перехвачена, залогирована, claim не падает (fail-OPEN: claim продолжается)"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-18
|
||
type: unit
|
||
description: "Ошибка при определении freeze → fail-CLOSED: следующая не стартует при невозможности подтвердить отсутствие freeze"
|
||
module: tests/test_serial_gate_freeze.py
|
||
expected: PASS
|
||
|
||
# ---------- AC-10: наблюдаемость ----------
|
||
- id: TC-19
|
||
type: unit
|
||
description: "serial_gate snapshot() возвращает {enabled, repos, per-repo active_task, waiting, frozen}; never-raise при ошибке → минимальный словарь"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-20
|
||
type: integration
|
||
description: "GET /queue содержит аддитивный блок serial_gate и НЕ меняет существующие ключи (counts/max_concurrency/reconcile/reaper/post_deploy/task_deps/recent)"
|
||
module: tests/test_queue_endpoint.py
|
||
expected: PASS
|
||
|
||
# ---------- AC-11: инварианты ----------
|
||
- id: TC-21
|
||
type: unit
|
||
description: "STAGE_TRANSITIONS и реестр QG_CHECKS не изменены (снимок ключей совпадает с эталоном); новых QG-проверок нет"
|
||
module: tests/test_serial_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-22
|
||
type: unit
|
||
description: "Миграция freeze-хранилища идемпотентна: повторный вызов init_db/_ensure не падает и не дублирует структуру"
|
||
module: tests/test_serial_gate_freeze.py
|
||
expected: PASS
|