auto-sync: 2026-06-05 10:00:01

This commit is contained in:
Stream
2026-06-05 10:00:01 +03:00
parent 504bac2e25
commit 1eff3311d4
2 changed files with 84 additions and 0 deletions

View File

@@ -232,3 +232,25 @@
- Done state id (ORCH project): `3738cd3c-7610-4907-ba5e-26b9a248d9c0`
- ТЗ Этап 4: `tasks/orchestrator/DEV_TASK_ORCH34_DEPLOY_HOOK.md`; отчёт `tasks/orchestrator/reports/dev-2026-06-05-orch34-deploy-hook.md`
- Деплой-хук: `scripts/orchestrator-deploy-hook.sh`, образец enduro: `/home/slin/bin/enduro-deploy-hook.sh`
---
## ORCH-36 (Вариант B самодеплоя) заведён в Backlog + критерии «доверия к автоматике» (05.06)
### ORCH-36 создан в Plane Backlog
- **id `84a6c09d-7a03-4cb7-a58b-3d8963c565a5`**, seq 36, name "ORCH-36: Исполняемый самодеплой — стадия deploy дёргает хост-хук (Вариант B)".
- Суть: стадия `deploy` реально дёргает хост-хук `orchestrator-deploy-hook.sh` (ORCH-34) через ssh → промоут в прод (8500) с health+авто-rollback. На старте — ОБЯЗАТЕЛЬНЫЙ ручной approve (`DEPLOY_REQUIRE_MANUAL_APPROVE=true`). Делается ПОСЛЕ ORCH-35 (Вариант A — staging-гейт ворота).
- Слава: "позже вернёмся" → лежит в бэклоге детально описанной.
### «Доверие к автоматике» — ФОРМАЛЬНЫЕ критерии (для флага true→false)
Переход `DEPLOY_REQUIRE_MANUAL_APPROVE` true→false (manual approve → полный авто) — ТОЛЬКО когда ВСЕ 5 закрыты (метрики набираются в режиме ручного approve):
1. **≥10 успешных промоутов подряд** (staging зелёный → approve → прод поднялся, откат не нужен).
2. **Zero false-negative (критично):** staging-гейт НИ РАЗУ не пропустил битый деплой как «зелёный».
3. **Авто-rollback проверен в бою ≥2-3 раза:** recovery rate 100%, MTTR <60с.
4. **Ни одного «молчаливого» деплоя:** каждый промоут/откат → Plane + Telegram.
5. **Период наблюдения:** ≥10 деплоев ИЛИ ≥2 недели без инцидентов в manual-approve.
Когда 5/5 → осознанное переключение флага отдельным шагом.
### Этап 5 (ORCH-35) = Вариант A (решение по объёму ждёт Славу: только A или A+B)
- Вариант A: стадия `deploy-staging` МЕЖДУ testing и deploy, QG `check_staging_status` (образец `check_deploy_status`), deployer гоняет `staging_check.py` против 8501. Прод-деплой недостижим пока staging не зелёный. Off-limits: не ломать существующие QG/rollback.
- Полный план разведки — в `tasks/orchestrator/DESIGN_STAGING_ENV.md` (раздел "РАЗВЕДКА КОДА ДЛЯ ЭТАПА 5").

View File

@@ -0,0 +1,62 @@
# DEV TASK — ORCH-35: стадия `deploy-staging` как обязательные ворота перед прод-деплоем (Вариант A)
**Проект:** orchestrator | **Сервер:** slin@82.22.50.71 (pw motoZ@yaz2010) | **Репо:** /home/slin/repos/orchestrator
**Ветка:** `feature/ORCH-35-staging-gate` из свежего origin/main. `git fetch origin && git checkout main && git pull --ff-only && git checkout -b feature/ORCH-35-staging-gate`.
**Этап:** 5 (финальный) из 5. После Этапов 1-4: staging живой на 8501, песочница рабочая, тест-сьют `scripts/staging_check.py` в main, деплой-хук в main.
## ЦЕЛЬ (Вариант A — «ворота», БЕЗ исполняемого деплоя)
Вставить в конвейер новую стадию **`deploy-staging` МЕЖДУ `testing` и `deploy`**. На ней прогоняется staging-тест-сьют против живого staging (8501) и пишется машинный вердикт. **Прод-деплой (`deploy`) недостижим, пока `deploy-staging`-гейт не зелёный.** Это «бумажные ворота»: реальный docker-деплой в прод НЕ делается (это Вариант B = ORCH-36, отдельная задача — НЕ трогать).
Новая цепочка: `...testing → deploy-staging → deploy → done`.
## ⛔ OFF-LIMITS / КРИТИЧНО (это БОЕВОЙ конвейер)
- **НЕ ломать существующие QG:** `check_deploy_status`, `check_tests_passed`, `_parse_deploy_status`, БАГ-8 rollback (`deploy`-вердикт FAILED → откат на `development` в `stage_engine.py` ~525), terminal-sync `deploy→done` (~260). ТОЛЬКО ДОБАВЛЯТЬ, не переписывать существующее.
- **НЕ дёргать реальный docker / хост-хук / ssh-деплой в прод.** Это Вариант B (ORCH-36). Здесь только прогон staging-сьюта + вердикт.
- **НЕ трогать** `.env`, `.env.staging`, `docker-compose.yml`, `scripts/staging_check.py`, `scripts/orchestrator-deploy-hook.sh`.
- PR push в main ЗАПРЕЩЁН, НЕ мержить. Коммит в ветку + PR.
- НЕ регистрировать раннеров, НЕ nohup. Раннер mva154-runner-orch уже есть.
- Если факт разошёлся с ТЗ — СТОП, отчёт, не угадывать.
## ТОЧНЫЕ ТОЧКИ ВСТРОЙКИ (разведано 05.06)
### 1. `src/stages.py` — `STAGE_TRANSITIONS`
Сейчас:
```
"testing": {"next": "deploy", "agent": "deployer", "qg": "check_tests_passed"},
"deploy": {"next": "done", "agent": None, "qg": "check_deploy_status"},
```
Стать (вставить `deploy-staging` между ними, СОХРАНИВ порядок ключей — `get_previous_stage` использует порядок dict для rollback):
```
"testing": {"next": "deploy-staging", "agent": "deployer", "qg": "check_tests_passed"},
"deploy-staging": {"next": "deploy", "agent": "deployer", "qg": "check_staging_status"},
"deploy": {"next": "done", "agent": None, "qg": "check_deploy_status"},
```
⚠️ Семантика поля `agent` = «кто запускается при выходе ИЗ стадии» (см. docstring stages.py). На стадии `deploy-staging` отрабатывает deployer-агент (гоняет сьют + пишет вердикт), при выходе из неё агента нет → `deploy` имеет `agent:None` как сейчас. ВНИМАТЕЛЬНО: проверь, что переход `testing→deploy-staging` запускает нужного агента и не сломал текущую логику `get_agent_for_stage`. Обнови docstring-цепочку вверху файла.
### 2. `src/qg/checks.py` — новый QG `check_staging_status`
- Создай функцию по ОБРАЗЦУ `check_deploy_status` (строка 407) + `_parse_deploy_status` (350) + `_deploy_log_from_main` (374). Сигнатура: `check_staging_status(repo: str, work_item_id: str, branch: str | None = None) -> tuple[bool, str]`.
- Парсит ТОЛЬКО машинное поле `staging_status:` (SUCCESS→pass, FAILED→fail, нет поля/нет frontmatter→fail) из нового лог-файла `15-staging-log.md` (читать из origin/main так же, как deploy-log — сделай аналог `_staging_log_from_main` или параметризуй существующий хелпер по имени файла, НЕ ломая deploy-версию).
- Зарегистрируй в `QG_CHECKS` (строка 444): добавь `"check_staging_status": check_staging_status,`.
- `_run_qg` (`stage_engine.py:77`): новый QG идёт по общей ветке `check_fn(repo, work_item_id, branch)` — спец-обработка НЕ нужна (как у `check_deploy_status`). Проверь, что попадает в общий путь.
### 3. `src/usage.py` — `AGENT_ARTIFACT` (если нужно для логов/ссылок)
- Сейчас `"deployer": ("Deploy log", "14-deploy-log.md")`. Для стадии `deploy-staging` deployer пишет `15-staging-log.md`. Артефакт-маппинг сейчас по агенту, а deployer теперь на ДВУХ стадиях (deploy-staging и deploy) — реши аккуратно: либо маппинг по стадии, либо deployer на staging-стадии явно пишет `15-staging-log.md`. НЕ сломай существующую логику `14-deploy-log.md`. Если простого решения нет — опиши в отчёте и оставь deploy-log как есть, главное чтобы `check_staging_status` нашёл свой файл.
### 4. Промпт deployer-агента (`.openclaw/agents/deployer.md` в репо)
- Найди файл (`system_prompt` указан в `launcher.py:108` как `.openclaw/agents/deployer.md`). Если он есть — добавь инструкцию: на стадии `deploy-staging` агент гоняет `python3 scripts/staging_check.py --base-url http://localhost:8501 --mode stub`, и по результату (exit 0 = все PASS) пишет в `docs/work-items/<wi>/15-staging-log.md` frontmatter `staging_status: SUCCESS` (или `FAILED`), затем мержит артефакт в main (как 14-deploy-log). Если файла промпта нет в репо — опиши в отчёте, где он реально живёт, и согласуй (СТОП).
### 5. `tests/` — обновить под новую цепочку
- `tests/test_stage_engine.py`, `tests/test_qg.py` (и любые, что упоминают `STAGE_TRANSITIONS`/`testing→deploy`/`check_deploy_status`) — обнови ожидания на новую цепочку `testing→deploy-staging→deploy→done`. Добавь тест на `check_staging_status` (SUCCESS/FAILED/missing — как для deploy). Добавь тест, что `deploy-staging` FAILED откатывает корректно (если в движке есть rollback-ветка для staging — или подтверди, что generic-rollback через `get_previous_stage` сработает: previous(`deploy-staging`)=`testing`... ⚠️ проверь, КУДА должен откатываться провал staging — на `development` как deploy, или на `testing`? Реши по логике: провал staging = код плох → откат на `development`, как у deploy-БАГ-8. Если для этого нужна ветка в stage_engine — добавь по образцу БАГ-8, НЕ ломая deploy-ветку).
## ПРОВЕРКА (обязательный пруф в отчёт)
1. **Юнит-тесты зелёные:** `pytest tests/ -q` — ВСЁ passed (включая новые тесты staging-гейта). Покажи итог (N passed). Существующие тесты deploy НЕ red.
2. **Цепочка стадий:** показать, что `get_next_stage("testing")=="deploy-staging"`, `get_next_stage("deploy-staging")=="deploy"`, `get_next_stage("deploy")=="done"`. И `get_qg_for_stage("deploy-staging")=="check_staging_status"`.
3. **QG-логика:** `check_staging_status` на файле с `staging_status: SUCCESS`→(True,...), `FAILED`→(False,...), без поля→(False,...). Покажи прогон.
4. **Rollback staging-провала:** тест/прогон, что FAILED на `deploy-staging` откатывает задачу куда решено (development), не застревает и не идёт в `deploy`.
5. **Прод НЕ задет:** изменения только в коде (`src/stages.py`, `src/qg/checks.py`, возможно `src/usage.py`, `.openclaw/agents/deployer.md`, `tests/`). НЕ трогать .env/compose/staging_check.py/deploy-hook.sh. `git diff --name-only origin/main..ветка` — показать список.
6. `git log --oneline origin/main..origin/feature/ORCH-35-staging-gate` — коммит виден ПОСЛЕ push.
⚠️ Это ворота-гейт, реального деплоя НЕТНЕ запускай ничего против боевого прода (8500), НЕ дёргай docker-рестарты. Юнит-тесты + статический прогон QG достаточно. Живой e2e staging-сьют уже покрыт ORCH-33.
## РЕЗУЛЬТАТ
Изменения: `src/stages.py` (+стадия), `src/qg/checks.py` (+check_staging_status, +registry), при необходимости `src/usage.py` и `.openclaw/agents/deployer.md`, `tests/` (обновлены + новые). Все тесты зелёные. PR в Gitea. Отчёт → `tasks/orchestrator/reports/dev-2026-06-05-orch35-staging-gate.md`. Коммит: `feat(pipeline): add deploy-staging gate before prod deploy (ORCH-35)`.