analyst(ET): auto-commit from analyst run_id=189
This commit is contained in:
109
docs/work-items/ORCH-036/01-brd.md
Normal file
109
docs/work-items/ORCH-036/01-brd.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# BRD — ORCH-36: Исполняемый самодеплой (стадия deploy дёргает хост-хук, Вариант B)
|
||||
|
||||
Work Item: ORCH-036
|
||||
Stage: analysis
|
||||
Автор: analyst
|
||||
Дата: 2026-06-06
|
||||
|
||||
## 1. Контекст и проблема
|
||||
|
||||
Стадия `deploy` конвейера сейчас **«бумажная»**. На ней deployer-агент (LLM) только
|
||||
пишет `docs/work-items/<wi>/14-deploy-log.md` с `deploy_status: SUCCESS|FAILED`, а QG
|
||||
`check_deploy_status` (`src/qg/checks.py:464`) парсит этот вердикт и пускает `deploy → done`.
|
||||
**Реального docker-деплоя нет** — продакшен орка катается руками (Стрим).
|
||||
|
||||
Хост-хук `scripts/orchestrator-deploy-hook.sh` **уже существует** (ORCH-34) и умеет:
|
||||
захват PREV_IMG → `git pull` → рестарт сервиса → health-check (10×6с = 60с) →
|
||||
авто-rollback при провале health, с корректным exit-code. Дефолты — STAGING-безопасные;
|
||||
прод включается через override env (`TARGET_SERVICE`, `TARGET_PORT`, `TARGET_IMAGE`,
|
||||
`COMPOSE_PROFILE`).
|
||||
|
||||
**Главная мина (self-hosting):** прод-контейнер `orchestrator` (8500) — ОДИН на все
|
||||
проекты, и в нём же бежит сам deployer-агент. Deployer не может синхронно рестартить
|
||||
контейнер, в котором живёт (`docker compose up -d orchestrator` убьёт его процесс на
|
||||
середине). Реальный рестарт self-репо обязан делать ВНЕШНИЙ хост-хук (вне контейнера),
|
||||
который срабатывает ПОСЛЕ выхода агента. Рубильник — снаружи; орк только ИНИЦИИРУЕТ.
|
||||
|
||||
## 2. Цель
|
||||
|
||||
Превратить стадию `deploy` в РЕАЛЬНЫЙ самодеплой: после зелёного `deploy-staging`-гейта
|
||||
конвейер вызывает хост-хук с прод-параметрами, хук промоутит образ в прод (8500) с
|
||||
health-чеком и авто-rollback. Результат хука (exit-code) маппится в `deploy_status`.
|
||||
**На старте — с ОБЯЗАТЕЛЬНЫМ ручным approve** (`DEPLOY_REQUIRE_MANUAL_APPROVE=true`):
|
||||
прод не трогается без явного «go» Владельца.
|
||||
|
||||
## 3. Ценность для бизнеса
|
||||
|
||||
- Уходит последний ручной шаг конвейера (прод-деплой Стрим) → шаг к автономному внедрению (эпик ORCH-54).
|
||||
- `deploy_status: SUCCESS` становится **доказанным** (реальный health-ok), а не декларацией LLM.
|
||||
- Гарантия build-once: «что протестировали на staging — то и в проде» (тот же образ, без пересборки).
|
||||
- Прод никогда не остаётся в нерабочем состоянии: авто-rollback + health-таймаут.
|
||||
|
||||
## 4. Заинтересованные стороны
|
||||
|
||||
| Роль | Интерес |
|
||||
|------|---------|
|
||||
| Владелец (Слава/Стрим) | Контроль через ручной approve; уведомления о каждом промоуте/откате |
|
||||
| Проект enduro-trails | Прод-орк не должен падать (общий инстанс) — групповой риск |
|
||||
| Конвейер ORCH | Стадия `deploy` исполняемая, гейты не сломаны |
|
||||
|
||||
## 5. Объём (scope)
|
||||
|
||||
### В объёме
|
||||
1. Исполнение реального прод-деплоя из стадии `deploy` через хост-хук (ssh / detached на хосте).
|
||||
2. Обязательный ручной approve-гейт ПОСЛЕ зелёного staging и ДО прод-рестарта (флаг включён).
|
||||
3. Маппинг exit-code хука → `deploy_status: SUCCESS|FAILED` (реальный, не бумажный).
|
||||
4. Уведомления (Plane-коммент + Telegram) на каждый промоут и откат.
|
||||
5. Build-once: перетегирование образа, прошедшего staging, без пересборки.
|
||||
6. Обновление `deployer.md` и `INFRA.md` (документация = golden source).
|
||||
7. Для НЕ-self репо (enduro-trails и др.) — деплой по ssh на их хост (поведение не ломается).
|
||||
|
||||
### Вне объёма (явно)
|
||||
- **Включение полного авто** (`DEPLOY_REQUIRE_MANUAL_APPROVE: true → false`) — отдельная задача,
|
||||
ТОЛЬКО после набора метрик доверия (см. §7). В этой задаче флаг НЕ выключается.
|
||||
- Изменение `docker-compose.yml` без явной необходимости.
|
||||
- Изменение стадий `STAGE_TRANSITIONS`, реестра QG, terminal-sync `deploy → done`.
|
||||
- Прод-деплой в реальный бой во время разработки задачи (отладка — только на staging-цели хука).
|
||||
|
||||
## 6. Бизнес-требования
|
||||
|
||||
- **BR-1.** После зелёного `deploy-staging`-гейта стадия `deploy` РЕАЛЬНО собирает/перетегирует
|
||||
образ, рестартит целевой сервис и проверяет health — не пишет бумажный SUCCESS.
|
||||
- **BR-2.** Для self-репо `orchestrator` рестарт 8500 выполняется ВНЕШНИМ (detached/host)
|
||||
процессом; deployer-агент НЕ убивает контейнер, в котором работает.
|
||||
- **BR-3.** `deploy_status: SUCCESS` пишется ТОЛЬКО при health-ok хука; провал/health-fail →
|
||||
`deploy_status: FAILED` → откат на `development` (как ORCH-35 staging-rollback, БАГ-8).
|
||||
- **BR-4.** Ручной approve обязателен (флаг `true`): без явного «go» прод НЕ трогается.
|
||||
- **BR-5.** Каждый промоут и откат уведомляет Владельца: Plane-коммент в задачу + Telegram.
|
||||
«Молчаливых» деплоев нет.
|
||||
- **BR-6.** Build-once: в прод идёт тот образ, что прошёл staging-гейт (перетег, не пересборка).
|
||||
- **BR-7.** Staging-гейт (`check_staging_status`) остаётся обязательным предусловием прод-деплоя.
|
||||
- **BR-8.** Прод никогда не остаётся в нерабочем состоянии — авто-rollback при провале health.
|
||||
- **BR-9.** Существующие гейты и инварианты не ломаются: `check_deploy_status`,
|
||||
`_parse_deploy_status`, rollback `deploy → development` (БАГ-8), terminal-sync `deploy → done`,
|
||||
merge-gate (ORCH-43).
|
||||
- **BR-10.** Документация (`deployer.md`, `INFRA.md`, `CHANGELOG.md`) обновлена в том же PR.
|
||||
|
||||
## 7. Критерии готовности к включению ПОЛНОГО авто (вне этой задачи)
|
||||
|
||||
Переключать `DEPLOY_REQUIRE_MANUAL_APPROVE: true → false` можно ТОЛЬКО когда закрыты ВСЕ 5:
|
||||
1. ≥10 успешных промоутов подряд (staging зелёный → approve → прод поднялся, откат не нужен).
|
||||
2. Zero false-negative: staging-гейт ни разу не пропустил битый деплой как «зелёный».
|
||||
3. Авто-rollback проверен в бою (≥2–3 реальных срабатывания), recovery 100%, MTTR < 60с.
|
||||
4. Ни одного «молчаливого» деплоя (каждый промоут/откат уведомил Владельца).
|
||||
5. Период наблюдения ≥10 деплоев ИЛИ ≥2 недели без инцидентов в режиме manual-approve.
|
||||
|
||||
## 8. Риски
|
||||
|
||||
| Риск | Влияние | Митигация |
|
||||
|------|---------|-----------|
|
||||
| Падение прод-орка 8500 при self-деплое | Встаёт конвейер ВСЕХ проектов | Detached host-хук + health + авто-rollback; отладка на staging-цели |
|
||||
| Deployer рестартит сам себя синхронно | Процесс агента убит на середине | BR-2: рестарт только внешним detached-процессом |
|
||||
| Преждевременный `deploy_status: SUCCESS` (хук ещё не закончил) | Задача уходит в done при незавершённом деплое | Гейт читает РЕАЛЬНЫЙ исход хука (механизм — на дизайне) |
|
||||
| Деплой без approve | Неконтролируемый прод-деплой | BR-4: approve-гейт блокирует до «go» |
|
||||
| Пересборка вместо перетега | В прод уезжает не то, что тестировали | BR-6: build-once, `--no-build` + retag |
|
||||
|
||||
## 9. Связанные задачи
|
||||
ORCH-7 (self-hosting), ORCH-21 (auto-rollback), ORCH-34 (хук готов), ORCH-35 (staging-гейт),
|
||||
ORCH-43 (merge-gate в проде), ORCH-54 (эпик автономного внедрения).
|
||||
Дизайн-референс: `tasks/orchestrator/DESIGN_STAGING_ENV.md §4/§7`.
|
||||
136
docs/work-items/ORCH-036/02-trz.md
Normal file
136
docs/work-items/ORCH-036/02-trz.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# ТЗ — ORCH-36: Исполняемый самодеплой (стадия deploy дёргает хост-хук, Вариант B)
|
||||
|
||||
Work Item: ORCH-036
|
||||
Stage: analysis
|
||||
Автор: analyst
|
||||
Дата: 2026-06-06
|
||||
|
||||
> Документ фиксирует ТРЕБОВАНИЯ к изменениям (что и где). Конкретный механизм
|
||||
> (ssh vs docker.sock vs detached nohup/systemd-run; механизм approve) выбирает
|
||||
> архитектор в ADR (`06-adr/`). ТЗ задаёт границы и контракты, не реализацию.
|
||||
|
||||
## 1. Текущее устройство (as-is, разведано в коде)
|
||||
|
||||
- **Стадии** (`src/stages.py`): `… testing → deploy-staging → deploy → done`.
|
||||
- `deploy-staging`: `agent=deployer`, `qg=check_staging_status` (запускается deployer при
|
||||
выходе из `deploy-staging`, входе в `deploy`).
|
||||
- `deploy`: `agent=None`, `qg=check_deploy_status` (агент НЕ запускается при выходе из `deploy`).
|
||||
- **Вывод:** реальную работу стадии `deploy` делает deployer-агент, запущенный на переходе
|
||||
`deploy-staging → deploy`. Он пишет `14-deploy-log.md`. Когда он завершается, `advance_stage`
|
||||
с `current_stage=deploy` прогоняет `check_deploy_status` и двигает `deploy → done`.
|
||||
- **QG** (`src/qg/checks.py`):
|
||||
- `check_deploy_status:464` → `_parse_deploy_status:406` читает ТОЛЬКО `deploy_status:` из
|
||||
YAML-frontmatter `14-deploy-log.md` (worktree → origin/main fallback → not found).
|
||||
- `check_staging_status:580` — условный (реален только для self-hosting `orchestrator`).
|
||||
- `is_self_hosting_repo()` (`:511`) — детектор self-репо.
|
||||
- **Откаты/диспетчеризация** (`src/stage_engine.py`):
|
||||
- `_handle_qg_failure_rollbacks:585` — ветка `deployer` + `check_deploy_status` FAILED →
|
||||
откат `deploy → development`, `set_issue_blocked`, release merge-lease, Plane+Telegram.
|
||||
- Terminal-sync `deploy → done` (`:281`) → `set_issue_done`, release merge-lease.
|
||||
- merge-gate (ORCH-43) на ребре `deploy-staging → deploy` — НЕ трогать.
|
||||
- **Launcher** (`src/agents/launcher.py`):
|
||||
- deployer-агент конфиг: `.task-deploy.md` / `.openclaw/agents/deployer.md` (`:180`).
|
||||
- Пост-обработка: commit+push артефактов в worktree (`:506-558`).
|
||||
- `exit_code != 0 && agent == deployer` → откат `deploy → development` (`:560-581`).
|
||||
- **Хост-хук** (`scripts/orchestrator-deploy-hook.sh`, ORCH-34) — ГОТОВ: `--deploy`/`--rollback`,
|
||||
параметризован env, дефолты STAGING; health 10×6с; авто-rollback; exit 0/1/2.
|
||||
- **Agent (deployer.md)**: на стадии `deploy` сейчас пишет «бумажный» вердикт; в промпте маркер
|
||||
«Real docker/SSH deploys are handled by scripts/orchestrator-deploy-hook.sh (ORCH-36)».
|
||||
- **Топология** (`docs/operations/INFRA.md`): prod=8500 (`.env`), staging=8501 (`.env.staging`,
|
||||
profile staging). Контейнер под uid 1000, доступ к docker.sock через gid 999.
|
||||
|
||||
## 2. Изменения по модулям (to-be)
|
||||
|
||||
### 2.1 `scripts/orchestrator-deploy-hook.sh` (донастройка прод-режима)
|
||||
- Хук уже параметризован; требуется обеспечить **корректный прод-профиль вызова**:
|
||||
`TARGET_SERVICE=orchestrator`, `TARGET_PORT=8500`, `TARGET_IMAGE=orchestrator-orchestrator`,
|
||||
`COMPOSE_PROFILE` (для прод-сервиса — пустой/дефолтный, т.к. prod стартует без profile).
|
||||
- **Build-once (BR-6):** деплой должен использовать образ, прошедший staging (перетег
|
||||
staging-образа → прод-тег + `docker compose up -d --no-build`), а НЕ пересобирать. Если
|
||||
текущий хук всегда `--no-build` и тянет `git pull` — уточнить в ADR, как гарантируется
|
||||
идентичность артефакта staging↔prod (retag staging image, либо общий build-once шаг).
|
||||
- `PREV_IMAGE_FILE` для прод — отдельный путь (например `.deploy-prev-image` без `-staging`),
|
||||
чтобы не путать снапшоты prod/staging.
|
||||
- Поведение `--rollback`, health-loop, exit-code (0=ok, 1=rolled back, 2=rollback тоже упал) —
|
||||
НЕ менять контракт.
|
||||
|
||||
### 2.2 Approve-гейт (новое; место — на дизайне)
|
||||
- Ввести флаг конфигурации `DEPLOY_REQUIRE_MANUAL_APPROVE` (bool, дефолт `true`).
|
||||
- При `true`: перед вызовом прод-хука (после зелёного `deploy-staging`) конвейер ОСТАНАВЛИВАЕТСЯ
|
||||
и ждёт явного «go» Владельца. Без «go» прод-хук НЕ вызывается.
|
||||
- Механизм approve (выбрать ОДИН в ADR): Plane-коммент-триггер (по образцу `:approved:`
|
||||
в `check_analysis_approved`) / Telegram-кнопка / signal-файл. Требование к механизму:
|
||||
рестарт-safe (переживает перезапуск инстанса), идемпотентный, аудируемый.
|
||||
- При `false` (вне этой задачи): approve-шаг пропускается — НЕ реализовывать выключение здесь,
|
||||
только заложить ветку по флагу.
|
||||
|
||||
### 2.3 Триггер реального деплоя из стадии `deploy`
|
||||
- На стадии `deploy` (для self-репо `orchestrator`) вместо/в дополнение к записи вердикта
|
||||
агентом — ИНИЦИИРОВАТЬ внешний detached-процесс (host-хук), который выполнит
|
||||
build-once+restart+health ПОСЛЕ выхода агента (BR-2: агент не рестартит сам себя).
|
||||
- Маршрут вызова (на дизайне): ssh на хост (`DEPLOY_SSH_USER`/`DEPLOY_HOOK_SCRIPT`) ИЛИ
|
||||
detached через docker.sock/nohup/systemd-run. Требование: процесс хука переживает выход
|
||||
агента и завершение его сессии.
|
||||
- Для **не-self** репо (enduro-trails): деплой по ssh на их хост (как раньше) — поведение не ломать.
|
||||
|
||||
### 2.4 Маппинг результата хука → `deploy_status`
|
||||
- `deploy_status: SUCCESS` пишется в `14-deploy-log.md` ТОЛЬКО при exit-code хука = 0 (health-ok).
|
||||
- exit-code ≠ 0 (1 = rolled back; 2 = rollback тоже упал) → `deploy_status: FAILED`.
|
||||
- **Контракт `_parse_deploy_status` НЕ меняется** (читает `deploy_status: SUCCESS|FAILED` из
|
||||
frontmatter). Меняется только КТО и КОГДА пишет этот вердикт — на основе реального исхода.
|
||||
- **Гонка чтения гейта:** т.к. self-рестарт асинхронный (detached), гейт `check_deploy_status`
|
||||
не должен прочитать вердикт ДО завершения хука. Механизм синхронизации (post-factum запись
|
||||
лога/мердж в main / отложенный гейт) — спроектировать в ADR так, чтобы гейт читал РЕАЛЬНЫЙ
|
||||
итог. Контракт чтения из worktree→origin/main (`_deploy_log_from_main`) можно переиспользовать.
|
||||
|
||||
### 2.5 Уведомления (BR-5)
|
||||
- На промоут (старт прод-деплоя + успех) и на откат → `plane_add_comment(work_item_id, …)` +
|
||||
`send_telegram(…)`. Переиспользовать существующие хелперы (`src/notifications.py`,
|
||||
`src/plane_sync.py`). Никаких «молчаливых» деплоев.
|
||||
|
||||
### 2.6 Конфигурация (`src/config.py` / `.env.example` / `.env.staging.example`)
|
||||
- Новый: `deploy_require_manual_approve: bool = True` (env `ORCH_DEPLOY_REQUIRE_MANUAL_APPROVE`).
|
||||
- Прод-параметры хука: `DEPLOY_SSH_USER`, `DEPLOY_SSH_HOST`, `DEPLOY_HOOK_SCRIPT` (уже есть в
|
||||
INFRA-карте) + прод-override `TARGET_SERVICE/PORT/IMAGE`. Прописать дескрипторы в `.env.example`
|
||||
(значения — только на хосте, не коммитить).
|
||||
- Условность по репо: реальный прод-деплой — только для self-hosting (`is_self_hosting_repo`),
|
||||
как ORCH-35; прочие репо идут прежним ssh-путём.
|
||||
|
||||
### 2.7 Документация (BR-10, golden source)
|
||||
- `.openclaw/agents/deployer.md` — раздел «Stage: deploy»: переписать с «бумажного SUCCESS» на
|
||||
«стадия ВЫЗЫВАЕТ хук»; зафиксировать запрет синхронного рестарта 8500 и detached-путь self.
|
||||
- `docs/operations/INFRA.md` — процедура прод-деплоя орка через хук + approve.
|
||||
- `docs/operations/DEPLOY_HOOK.md` — обновить, если затронут контракт хука.
|
||||
- `CHANGELOG.md` — запись о включении исполняемого деплоя (manual-approve).
|
||||
- ADR в `docs/work-items/ORCH-036/06-adr/ADR-NNN-*.md` (создаёт архитектор).
|
||||
|
||||
## 3. API
|
||||
- Изменений публичного HTTP API (`/health`, `/status`, `/queue`, `/webhook/*`) **не требуется**.
|
||||
- Если approve реализуется через Plane-коммент — переиспользуется существующий webhook-путь
|
||||
(`POST /webhook/plane`), новый endpoint не вводится. Если через signal-файл/Telegram —
|
||||
внешний по отношению к HTTP API механизм. Решение — ADR.
|
||||
|
||||
## 4. Схема БД
|
||||
- Изменения схемы **не требуются** для базового сценария (вердикт — в `14-deploy-log.md`;
|
||||
approve-состояние желательно хранить рестарт-safe — допустимо через jobs/task_content или
|
||||
signal-файл, без новой таблицы). Если архитектор сочтёт нужным поле статуса approve —
|
||||
обосновать в ADR; по умолчанию — без миграции.
|
||||
|
||||
## 5. Требования к Quality Gates
|
||||
- `check_deploy_status` и `_parse_deploy_status` — контракт чтения НЕ менять (frontmatter only).
|
||||
- Откат `deploy → development` при `deploy_status: FAILED` (`stage_engine` БАГ-8) — сохранить.
|
||||
- Terminal-sync `deploy → done` и release merge-lease — сохранить.
|
||||
- merge-gate (`check_branch_mergeable`) на ребре `deploy-staging → deploy` — не затрагивать.
|
||||
- `check_staging_status` остаётся обязательным предусловием (BR-7).
|
||||
|
||||
## 6. Артефакты pipeline
|
||||
- Создаётся/обновляется: `docs/work-items/ORCH-036/14-deploy-log.md` (с РЕАЛЬНЫМ `deploy_status`).
|
||||
- Обновляются по pipeline: `06-adr/ADR-NNN-*.md`, `12-review.md`, `13-test-report.md`,
|
||||
`15-staging-log.md` (последующими агентами).
|
||||
|
||||
## 7. Нефункциональные требования
|
||||
- **Безопасность self-deploy:** рестарт 8500 — только внешним рубильником; орк не может
|
||||
необратимо убить себя.
|
||||
- **Идемпотентность** хука и approve-механизма; **рестарт-safe** approve-состояние.
|
||||
- **MTTR < 60с** при авто-rollback (health-loop хука 10×6с уже укладывается).
|
||||
- **Отладка только на staging-цели** хука; реальный прод — лишь после approve.
|
||||
97
docs/work-items/ORCH-036/03-acceptance-criteria.md
Normal file
97
docs/work-items/ORCH-036/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Критерии приёмки — ORCH-36: Исполняемый самодеплой (Вариант B)
|
||||
|
||||
Work Item: ORCH-036
|
||||
Stage: analysis
|
||||
Автор: analyst
|
||||
Дата: 2026-06-06
|
||||
|
||||
Формат: каждый критерий — проверяемое условие PASS/FAIL. Отладка и проверки
|
||||
выполняются на **staging-цели хука** (8501); реальный прод (8500) — только после approve.
|
||||
|
||||
---
|
||||
|
||||
## AC-1. Стадия deploy исполняет реальный деплой (не бумажный)
|
||||
- **PASS:** на стадии `deploy` (после зелёного `deploy-staging`) вызывается хост-хук,
|
||||
который реально перетегирует образ, рестартит целевой сервис и выполняет health-check;
|
||||
`deploy_status` отражает РЕАЛЬНЫЙ исход хука.
|
||||
- **FAIL:** `deploy_status: SUCCESS` пишется без фактического рестарта/health (бумажный лог).
|
||||
- **Проверка:** прогон на staging-цели хука; в логе хука видны retag + `up -d` + health-loop;
|
||||
exit-code хука соответствует записанному `deploy_status`.
|
||||
|
||||
## AC-2. Self-репо: рестарт 8500 — внешним detached-процессом, агент себя не убивает
|
||||
- **PASS:** для `orchestrator` рестарт 8500 выполняет процесс ВНЕ контейнера агента; deployer-агент
|
||||
завершается штатно (exit 0), его процесс не убит рестартом контейнера.
|
||||
- **FAIL:** deployer синхронно делает `docker compose up -d orchestrator` из контейнера и/или
|
||||
агент падает/обрывается на середине из-за рестарта собственного контейнера.
|
||||
- **Проверка:** симуляция на staging-цели; убедиться, что detached-процесс переживает выход агента.
|
||||
|
||||
## AC-3. deploy_status маппится из exit-code хука
|
||||
- **PASS:** exit-code хука 0 → `deploy_status: SUCCESS`; exit-code ≠ 0 (1/2) → `deploy_status: FAILED`.
|
||||
- **FAIL:** любой иной маппинг (например SUCCESS при exit 1).
|
||||
- **Проверка:** unit-тест маппинга exit-code → вердикт; интеграционный прогон с искусственным
|
||||
кодом возврата хука.
|
||||
|
||||
## AC-4. Провал деплоя → откат на development
|
||||
- **PASS:** при `deploy_status: FAILED` задача откатывается `deploy → development`
|
||||
(`set_issue_blocked`, Plane+Telegram), как в существующей ветке БАГ-8.
|
||||
- **FAIL:** при FAILED задача уходит в `done` или зависает.
|
||||
- **Проверка:** существующий контракт `stage_engine._handle_qg_failure_rollbacks` для
|
||||
`deployer`+`check_deploy_status` сохранён и срабатывает.
|
||||
|
||||
## AC-5. Ручной approve обязателен и реально тормозит прод
|
||||
- **PASS:** при `DEPLOY_REQUIRE_MANUAL_APPROVE=true` прод-хук НЕ вызывается до явного «go»;
|
||||
после «go» — вызывается.
|
||||
- **FAIL:** прод-хук дёргается без approve.
|
||||
- **Проверка:** прогон без «go» — целевой сервис НЕ перезапущен (нет записи рестарта в логе хука,
|
||||
не сменился uptime/контейнер); прогон с «go» — рестарт состоялся.
|
||||
|
||||
## AC-6. Уведомления о каждом промоуте и откате
|
||||
- **PASS:** на старт/успех прод-деплоя и на откат приходят и Plane-коммент в задачу, и Telegram.
|
||||
- **FAIL:** хотя бы один промоут/откат прошёл «молчаливо».
|
||||
- **Проверка:** в Plane-задаче и в Telegram-чате присутствуют сообщения для каждого исхода.
|
||||
|
||||
## AC-7. Build-once: в прод идёт образ, прошедший staging
|
||||
- **PASS:** прод-деплой использует тот же образ, что прошёл staging-гейт (retag + `--no-build`),
|
||||
без пересборки.
|
||||
- **FAIL:** прод-деплой пересобирает образ заново (артефакт может отличаться от протестированного).
|
||||
- **Проверка:** sha/тег образа прод == образ, валидированный на staging; в логе нет `build`.
|
||||
|
||||
## AC-8. Staging-гейт остаётся обязательным предусловием
|
||||
- **PASS:** прод-деплой недостижим без зелёного `check_staging_status` (`staging_status: SUCCESS`).
|
||||
- **FAIL:** прод-хук можно вызвать при FAILED/отсутствующем staging-вердикте.
|
||||
- **Проверка:** при `staging_status: FAILED` задача откатывается на development, до `deploy` не доходит.
|
||||
|
||||
## AC-9. Авто-rollback восстанавливает прод (симуляция битого деплоя)
|
||||
- **PASS:** при симуляции битого деплоя на staging-цели health не проходит → хук авто-откатывает
|
||||
на предыдущий образ → сервис снова healthy; exit-code = 1 (rolled back); MTTR < 60с.
|
||||
- **FAIL:** сервис остаётся нерабочим после провала деплоя.
|
||||
- **Проверка:** искусственно сломать health, прогнать хук, убедиться в восстановлении и exit 1.
|
||||
|
||||
## AC-10. Существующие инварианты не сломаны
|
||||
- **PASS:** не изменены контракты `check_deploy_status` / `_parse_deploy_status`,
|
||||
`STAGE_TRANSITIONS`, terminal-sync `deploy → done`, merge-gate (ORCH-43), rollback БАГ-8.
|
||||
- **FAIL:** любой из перечисленных контрактов изменён/сломан.
|
||||
- **Проверка:** существующие тесты deploy/staging/merge-gate зелёные; регресс-прогон `pytest tests/`.
|
||||
|
||||
## AC-11. Условность по репо (не-self не ломается)
|
||||
- **PASS:** для не-self репо (enduro-trails) деплой идёт прежним ssh-путём; self-логика (detached,
|
||||
approve, 8500) применяется только для `orchestrator`.
|
||||
- **FAIL:** не-self репо затронуты self-специфичной логикой и ломаются.
|
||||
- **Проверка:** `is_self_hosting_repo` корректно разводит пути; тест на не-self репо.
|
||||
|
||||
## AC-12. Флаг полного авто НЕ выключен в этой задаче
|
||||
- **PASS:** `DEPLOY_REQUIRE_MANUAL_APPROVE` остаётся `true`; переключение в `false` не делается.
|
||||
- **FAIL:** флаг выставлен в `false` в рамках задачи.
|
||||
- **Проверка:** дефолт конфигурации = `true`; в коде/`.env.example` нет принудительного `false`.
|
||||
|
||||
## AC-13. Документация обновлена (golden source)
|
||||
- **PASS:** обновлены `deployer.md` (стадия deploy = вызов хука), `INFRA.md` (процедура),
|
||||
`CHANGELOG.md`; заведён ADR в `06-adr/`.
|
||||
- **FAIL:** функционал изменён, документация — нет (Reviewer обязан вернуть REQUEST_CHANGES).
|
||||
- **Проверка:** диффы документации присутствуют в том же PR.
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
Все AC-1…AC-13 в статусе PASS; `pytest tests/` зелёный; артефакты pipeline на месте;
|
||||
прод (8500) во время разработки НЕ тронут (вся проверка — на staging-цели хука).
|
||||
122
docs/work-items/ORCH-036/04-test-plan.yaml
Normal file
122
docs/work-items/ORCH-036/04-test-plan.yaml
Normal file
@@ -0,0 +1,122 @@
|
||||
work_item: ORCH-036
|
||||
title: "Исполняемый самодеплой — стадия deploy дёргает хост-хук (Вариант B)"
|
||||
stage: analysis
|
||||
notes: >
|
||||
Все тесты — на изолированном уровне (unit/integration с моками subprocess/ssh
|
||||
и хука). Реальный прод (8500) НЕ трогается. Интеграционные прогоны хука — на
|
||||
staging-цели. Хост-хук (bash) проверяется отдельным интеграционным сценарием с
|
||||
поддельным health/exit-code; в pytest вызов хука мокается.
|
||||
|
||||
tests:
|
||||
# --- exit-code -> deploy_status mapping (AC-1, AC-3) ---
|
||||
- id: TC-01
|
||||
type: unit
|
||||
description: "Маппинг exit-code хука 0 -> deploy_status: SUCCESS"
|
||||
module: tests/test_deploy_hook_mapping.py
|
||||
expected: PASS
|
||||
- id: TC-02
|
||||
type: unit
|
||||
description: "Маппинг exit-code хука 1 (rolled back) -> deploy_status: FAILED"
|
||||
module: tests/test_deploy_hook_mapping.py
|
||||
expected: PASS
|
||||
- id: TC-03
|
||||
type: unit
|
||||
description: "Маппинг exit-code хука 2 (rollback тоже упал) -> deploy_status: FAILED"
|
||||
module: tests/test_deploy_hook_mapping.py
|
||||
expected: PASS
|
||||
|
||||
# --- approve gate (AC-5, AC-12) ---
|
||||
- id: TC-04
|
||||
type: unit
|
||||
description: "DEPLOY_REQUIRE_MANUAL_APPROVE дефолт == true в settings"
|
||||
module: tests/test_deploy_approve.py
|
||||
expected: PASS
|
||||
- id: TC-05
|
||||
type: integration
|
||||
description: "Флаг true и нет 'go' -> прод-хук НЕ вызывается (subprocess/ssh не дёрнут)"
|
||||
module: tests/test_deploy_approve.py
|
||||
expected: PASS
|
||||
- id: TC-06
|
||||
type: integration
|
||||
description: "Флаг true и есть 'go' -> прод-хук вызывается ровно один раз"
|
||||
module: tests/test_deploy_approve.py
|
||||
expected: PASS
|
||||
|
||||
# --- self vs non-self routing (AC-2, AC-11) ---
|
||||
- id: TC-07
|
||||
type: unit
|
||||
description: "is_self_hosting_repo('orchestrator') == True; иной репо -> False (не регрессировал)"
|
||||
module: tests/test_deploy_routing.py
|
||||
expected: PASS
|
||||
- id: TC-08
|
||||
type: integration
|
||||
description: "self-репо orchestrator: рестарт инициируется detached/host-процессом, не синхронно из агента"
|
||||
module: tests/test_deploy_routing.py
|
||||
expected: PASS
|
||||
- id: TC-09
|
||||
type: integration
|
||||
description: "не-self репо (enduro-trails): деплой идёт прежним ssh-путём, self-логика не применяется"
|
||||
module: tests/test_deploy_routing.py
|
||||
expected: PASS
|
||||
|
||||
# --- rollback on FAILED (AC-4) ---
|
||||
- id: TC-10
|
||||
type: integration
|
||||
description: "deploy_status: FAILED -> откат deploy->development, set_issue_blocked, release merge-lease"
|
||||
module: tests/test_deploy_rollback.py
|
||||
expected: PASS
|
||||
|
||||
# --- staging precondition preserved (AC-8) ---
|
||||
- id: TC-11
|
||||
type: integration
|
||||
description: "staging_status: FAILED -> до стадии deploy не доходит (откат на development)"
|
||||
module: tests/test_staging_precondition.py
|
||||
expected: PASS
|
||||
|
||||
# --- notifications (AC-6) ---
|
||||
- id: TC-12
|
||||
type: integration
|
||||
description: "Успешный промоут -> и Plane-коммент, и Telegram отправлены"
|
||||
module: tests/test_deploy_notifications.py
|
||||
expected: PASS
|
||||
- id: TC-13
|
||||
type: integration
|
||||
description: "Откат -> и Plane-коммент, и Telegram отправлены (нет молчаливого деплоя)"
|
||||
module: tests/test_deploy_notifications.py
|
||||
expected: PASS
|
||||
|
||||
# --- build-once (AC-7) ---
|
||||
- id: TC-14
|
||||
type: integration
|
||||
description: "Прод-деплой использует образ staging (retag, без build) — нет шага docker build"
|
||||
module: tests/test_deploy_build_once.py
|
||||
expected: PASS
|
||||
|
||||
# --- regression: unchanged gate contracts (AC-10) ---
|
||||
- id: TC-15
|
||||
type: unit
|
||||
description: "_parse_deploy_status: SUCCESS->(True), FAILED->(False), нет frontmatter->(False) — контракт цел"
|
||||
module: tests/test_qg_checks.py
|
||||
expected: PASS
|
||||
- id: TC-16
|
||||
type: unit
|
||||
description: "STAGE_TRANSITIONS deploy->done и agent/qg deploy не изменены"
|
||||
module: tests/test_stages.py
|
||||
expected: PASS
|
||||
- id: TC-17
|
||||
type: integration
|
||||
description: "terminal-sync deploy->done (set_issue_done + release merge-lease) сохранён"
|
||||
module: tests/test_deploy_terminal_sync.py
|
||||
expected: PASS
|
||||
- id: TC-18
|
||||
type: integration
|
||||
description: "merge-gate на ребре deploy-staging->deploy не затронут (регресс ORCH-43 зелёный)"
|
||||
module: tests/test_merge_gate.py
|
||||
expected: PASS
|
||||
|
||||
# --- auto-rollback hook behavior (AC-9) ---
|
||||
- id: TC-19
|
||||
type: integration
|
||||
description: "Симуляция битого деплоя на staging-цели: health fail -> авто-rollback -> healthy, exit 1, MTTR<60с"
|
||||
module: tests/test_deploy_hook_rollback_sim.py
|
||||
expected: PASS
|
||||
Reference in New Issue
Block a user