diff --git a/memory/2026-06-05.md b/memory/2026-06-05.md index 7b08333..f725f64 100644 --- a/memory/2026-06-05.md +++ b/memory/2026-06-05.md @@ -132,3 +132,64 @@ ### Следующий шаг Этап 3 (ORCH-33): тест-сьют staging — smoke + проверка доступов (Plane sandbox + Gitea sandbox реальными вызовами) + e2e (задача в SANDBOX → ветка в orchestrator-sandbox → статусы+комменты в Plane, верификация по API), режим full-real. Перед e2e: настроить Gitea-webhook sandbox-репо на localhost:8501. Это код для Dev (тест-скрипт) + моя инфра (webhook). + + +--- + +## Staging-среда orchestrator — Этапы 2-3 ВЫКАЧЕНЫ ✅ (05.06, утро) + +### Этап 1 (ORCH-31) — закрыт +- **PR #28 смержен** в main, main HEAD `3b68a29` "Merge PR #28", коммит ORCH-31 `6c1e5ff` в main. +- ⚠️ Грабля мержа: заголовок авторизации Gitea при первом заходе пришёл как `***` (санитайзер) → HTTP 401 `token is required`. Фикс: явно `token ` → HTTP 200 merged. Запомнить: при мерже через Gitea API проверять, что заголовок реально `token <значение>`, а не затёртый. + +### Этап 2 (ORCH-32) — песочница создана + staging-контейнер ПОДНЯТ +- **Gitea-репо песочницы:** `admin/orchestrator-sandbox` (main, auto-init). +- **Plane-проект песочницы:** name "ORCH Sandbox" (Plane НЕ пускает дефис/спецсимволы в name → без дефиса), identifier `SANDBOX`, **project_id `8c5a3025-4f9d-4190-b79f-fa06276bb27e`**. +- **Токены — вариант 1 (решение Славы):** общие с продом, изоляция по проекту/репо + раздельная БД (НЕ отдельные токены). +- **Telegram staging — вариант 1 (решение Славы):** пустой/выключенный, staging молчит в телегу (смотрим по логам/API). Никакого спама в боевой канал. +- **`.env.staging` собран** на проде (`/home/slin/repos/orchestrator/.env.staging`, в .gitignore, НЕ коммитится): реестр `ORCH_PROJECTS_JSON` = ТОЛЬКО sandbox (боевые ET/ORCH → ignored фильтром ORCH-6), Telegram пустой, БД через volume, `ORCH_STAGING=true`. Прод `.env` (23 строки) цел, бэкап сделан. +- **Контейнер `orchestrator-staging` поднят на 8501** (`docker compose --profile staging up -d`), образ `orchestrator-orchestrator-staging:latest`. Проверено лично: `/health`=ok, `/queue`=ok (Claude Code 2.1.142 виден), прод `orchestrator` Up 16h БЕЗ рестарта. +- **Изоляция подтверждена:** staging знает ТОЛЬКО sandbox (`known_plane_project_ids()`={8c5a3025...}); боевые ORCH(8da6aa25)/ET(7a79f0a9) → False; БД физически раздельная `data/staging/orchestrator.db`. + +### Webhook-изоляция (важная находка) +- **Gitea webhook прод-репо `orchestrator`** шлёт жёстко на `localhost:8500/webhook/gitea` (прод). Sandbox-репо пока БЕЗ хуков (правильно). +- **Plane webhooks через workspace API недоступны** (404) — настраиваются на уровне Plane-инстанса/UI (`plane-app-*` контейнеры). Прод-Plane шлёт на 8500. Staging боевые Plane-события НЕ получит, пока webhook в Plane не настроен на 8501. +- **Главный ключ изоляции:** `ORCH_PROJECTS_JSON` staging = только sandbox → даже если событие прилетит, всё не-sandbox → `ignored` (фильтр ORCH-6). + +### Этап 3 (ORCH-33) — тест-сьют ГОТОВ, PR #29 (ждёт мержа) +- Dev написал `scripts/staging_check.py` (smoke A + доступы B + e2e C, exit-code, cleanup в finally) + `docs/STAGING_CHECK.md`. Ветка `feature/ORCH-33-staging-testsuite`. **PR #29 open.** +- **Проверено лично на проде: 10/10 PASS, exit 0.** Файлы только новые (src/tests/compose/.env не тронуты). Боевое НЕ задето (нет staging-check веток в orchestrator/enduro-trails, нет тест-задач в боевом ORCH). Песочница чиста после cleanup (sandbox-репо = только main, Plane SANDBOX = 0 задач). Прод 8500 жив. +- **Ключевое архитектурное знание (порядок старта конвейера):** при старте сначала resolve проекта → подтяг name/desc из Plane → QG-0 валидация → **создаётся work_item_id + ветка + начальные доки + строка задачи в БД** → ТОЛЬКО ПОТОМ enqueue аналитика (Claude CLI через launcher). Значит e2e проверяет РАННИЕ артефакты (ветка/доки) ДО запуска LLM — быстро, без расхода кредитов. Аналитика не ждём. +- **Режима заглушек агентов (гибрид C) в коде НЕТ** — но для e2e он и не нужен (проверяем раннюю стадию до LLM). + +### Открытый нюанс (не блокер) +- Bot-токены агентов (`ORCH_PLANE_BOT_ANALYST` и пр.) НЕ добавлены членами в SANDBOX-проект → `add_comment` от их имени = 403. Dev заменил проверку «коммент в Plane» на надёжный ранний артефакт «analyst job в очереди». Чтобы закрыть полностью — добавить бот-аккаунты в SANDBOX через Plane API (моя инфра-работа, мелкая). + +### Следующие шаги +1. Мерж PR #29 (Этап 3) — предложено + добавить ботов в SANDBOX. +2. **Этап 4 (ORCH-34):** хост-деплой-хук `orchestrator-deploy-hook.sh` (промоут staging→prod, health 10×6с=60с, auto-rollback PREV_IMG). Образец `/home/slin/bin/enduro-deploy-hook.sh`. +3. **Этап 5 (ORCH-35):** стадия `deploy-staging` перед `deploy-prod` в конвейере. + +### Идентификаторы (Этап 2-3) +- Plane SANDBOX project_id: `8c5a3025-4f9d-4190-b79f-fa06276bb27e`, identifier `SANDBOX` +- Gitea sandbox-репо: `admin/orchestrator-sandbox` +- staging порт 8501, контейнер `orchestrator-staging`, профиль compose `staging`, образ `orchestrator-orchestrator-staging:latest`, БД `data/staging/orchestrator.db`, `.env.staging` (в .gitignore) +- main HEAD после Этапа 1: `3b68a29`; PR #28 merged, PR #29 open (Этап 3) +- ТЗ: `tasks/orchestrator/DEV_TASK_ORCH33_STAGING_TESTSUITE.md`; отчёт `tasks/orchestrator/reports/dev-2026-06-05-orch33-staging-testsuite.md` + +--- + +## Этап 3 закрыт + боты в SANDBOX (05.06, продолжение) + +### PR #29 смержен → Этап 3 в main +- **PR #29 merged** (HTTP 200, AUTH="token "+TOK — урок учтён). main HEAD `93169f1`, коммит сьюта `94334bd`. + +### Нюанс с бот-комментами закрыт (Plane membership) +- **Корень 403 при `add_comment` бот-токеном:** бот-токен ВИДИТ проект (GET 200), но НЕ может постить комменты, пока его owner НЕ член проекта. Воспроизвела: бот POST comment=403, админ POST comment=201. +- **7 бот-аккаунтов Plane (workspace members):** Analyst `c925cbcd-a8dc-4506-978e-15354ce3ad31`, Developer `bfe59a48-a7cd-4ce1-a78b-83f8891a4aba`, Reviewer `9836a30d-1294-430d-8109-ceb3e784d1d8`, Tester `7cdfc9e7-c552-4fd1-b4a7-3b1f03e72751`, Architect `6d82b825-c8b2-447c-bca0-c4d34c6200ac`, Deployer `ebf17448-d544-465e-8b0e-57581f76507c`, Стрим `468040f8-f609-406a-84d2-a119880a5e8e`. (+ admin-токен owner = `mva154` daf4d3f4..., + системный `Plane` 43c79cc2...). +- **Identity бот-токена узнаётся через** `GET {PBASE}/users/me/` с `X-API-Key: ` → возвращает id+display_name. +- **Добавление члена проекта Plane (РАБОЧИЙ формат):** `POST /workspaces/{slug}/projects/{pid}/members/` body `{"member": , "role": 15}` ПООДИНОЧКЕ. ⚠️ Формат `{"members":[{...}]}` и `member_id` НЕ работают (400 "member: This field is required"). role 15 = member. +- **Все 7 ботов добавлены членами SANDBOX** (теперь 8 members). Верифицировано: Analyst и Developer боты постят комменты → HTTP 201. Нюанс Этапа 3 устранён. + +### Дальше +Этап 4 (ORCH-34): хост-деплой-хук `orchestrator-deploy-hook.sh` (промоут staging→prod, health 10×6с=60с, auto-rollback по PREV_IMG). Образец `/home/slin/bin/enduro-deploy-hook.sh`. diff --git a/tasks/orchestrator/DEV_TASK_ORCH34_DEPLOY_HOOK.md b/tasks/orchestrator/DEV_TASK_ORCH34_DEPLOY_HOOK.md new file mode 100644 index 0000000..eae914b --- /dev/null +++ b/tasks/orchestrator/DEV_TASK_ORCH34_DEPLOY_HOOK.md @@ -0,0 +1,54 @@ +# DEV TASK — ORCH-34: хост-деплой-хук orchestrator с health-чеком и авто-rollback + +**Проект:** orchestrator | **Сервер:** slin@82.22.50.71 (pw motoZ@yaz2010) | **Репо:** /home/slin/repos/orchestrator +**Ветка:** `feature/ORCH-34-deploy-hook` из свежего origin/main. `git fetch origin && git checkout main && git pull --ff-only && git checkout -b feature/ORCH-34-deploy-hook`. +**Этап:** 4 из 5 (после Этапов 1-3: staging живой на 8501, песочница рабочая, тест-сьют в main). + +## ЦЕЛЬ +Написать деплой-хук `scripts/orchestrator-deploy-hook.sh` — bash-скрипт, который продвигает (промоутит) orchestrator на новый образ С HEALTH-ЧЕКОМ и АВТОМАТИЧЕСКИМ ОТКАТОМ, если новый контейнер не поднялся. Это аналог `/home/slin/bin/enduro-deploy-hook.sh`, НО с обязательным health-циклом + auto-rollback (которого у enduro-хука НЕТ). + +⚠️ **ВАЖНО ПРО БЕЗОПАСНОСТЬ:** на Этапе 4 хук тестируется ТОЛЬКО на STAGING-контейнере (`orchestrator-staging`, порт 8501). Боевой прод (`orchestrator`, 8500) хук на этом этапе НЕ ТРОГАЕТ. Поэтому скрипт ДОЛЖЕН быть параметризован по цели (service name + порт health) через аргументы/env, дефолт — БЕЗОПАСНЫЙ (staging), а не прод. Переключение на прод — осознанный шаг Этапа 5 / ручной запуск Славой, НЕ в этом ТЗ. + +## ОБРАЗЕЦ (изучить, повторить паттерн PREV_IMG) +`/home/slin/bin/enduro-deploy-hook.sh` (прочитай его на хосте). Из него берём: +- режим `--rollback`: восстановить образ из `$PREV_IMAGE_FILE` (retag PREV_IMG → APP_IMAGE, `docker compose up -d --no-build`), если файла нет — exit !=0. +- normal deploy: захватить ТЕКУЩИЙ образ контейнера ДО рестарта в `$PREV_IMAGE_FILE` (best-effort, не падать), `git pull`, `docker compose up -d`. +- логирование с UTC-таймстампами в лог-файл. + +## ЧЕГО У ОБРАЗЦА НЕТ И ЧТО ДОБАВИТЬ (суть ORCH-34) +После рестарта целевого контейнера — **HEALTH-ЦИКЛ**: опрашивать `http://localhost:/health` **10 попыток × 6 секунд = до 60с**. Критерий успеха: HTTP 200 И тело содержит `"status":"ok"`. +- Если health стал ok в пределах 60с → деплой успешен, exit 0. +- Если за 60с health НЕ поднялся → **АВТОМАТИЧЕСКИЙ ROLLBACK**: вызвать собственную rollback-ветку (восстановить PREV_IMG, рестарт, и ещё раз health-чек восстановленного — короткий, напр. 5×3с). Залогировать «deploy FAILED, rolled back to PREV_IMG». exit !=0 (чтобы вызывающий конвейер знал о фейле). +- Если и после rollback health не поднялся → залогировать критично «ROLLBACK ALSO FAILED», exit !=0. + +## ПАРАМЕТРИЗАЦИЯ (обязательно — для безопасности) +Скрипт принимает (через env-переменные с дефолтами ИЛИ флаги — на твоё усмотрение, задокументируй): +- `TARGET_SERVICE` (имя docker-compose сервиса) — **дефолт `orchestrator-staging`** (НЕ прод!). +- `TARGET_PORT` (порт health) — **дефолт `8501`** (staging). +- `TARGET_IMAGE` (образ для retag при rollback) — дефолт образа staging (узнай реальный: `docker inspect orchestrator-staging --format '{{.Config.Image}}'`). +- `COMPOSE_PROFILE` — для staging нужен профиль `staging` (иначе compose не видит сервис). Учти: `docker compose --profile staging up -d --no-build `. +- `PREV_IMAGE_FILE` — отдельный файл для staging (напр. `$REPO/.deploy-prev-image-staging`), чтобы НЕ пересекаться с прод-файлом enduro/орка. +- `LOG` — отдельный лог (напр. `/var/log/orchestrator/deploy-hook.log`, создать каталог; если нет прав — fallback в `$REPO/deploy-hook.log`). +- режимы: `--deploy` (дефолт, можно без флага) и `--rollback`. + +⚠️ Прод-значения (service `orchestrator`, порт 8500, образ `orchestrator-orchestrator`) скрипт ПОДДЕРЖИВАЕТ через переопределение env, но ДЕФОЛТ — staging. В коде НЕ хардкодить прод как дефолт. + +## ⛔ OFF-LIMITS / ПРАВИЛА +- НЕ трогать src/, tests/, docker-compose.yml, .env, .env.staging, существующий `/home/slin/bin/enduro-deploy-hook.sh`. Только НОВЫЙ файл `scripts/orchestrator-deploy-hook.sh` + `docs/DEPLOY_HOOK.md` (как работает, переменные, примеры запуска для staging И прода). +- Тестировать ТОЛЬКО на `orchestrator-staging` (8501). Боевой прод `orchestrator` (8500) НЕ рестартить, НЕ трогать. Если тест может задеть прод — СТОП, отчёт. +- НЕ менять `DEPLOY_HOOK_SCRIPT` в .env прода (переключение хука — Этап 5, не сейчас). +- НЕ регистрировать раннеров, НЕ nohup долгих процессов. Раннер mva154-runner-orch уже есть. +- PR push в main ЗАПРЕЩЁН. НЕ мержить — коммит в ветку + PR. +- Если факт разошёлся с ТЗ — СТОП, отчёт, не угадывать. + +## ПРОВЕРКА (обязательный пруф в отчёт) — всё на STAGING +Скрипт лежит в репо (`scripts/`), но для теста его надо запускать НА ХОСТЕ (он дёргает docker compose). Тестовый прогон: +1. **Happy-path:** запустить хук в `--deploy` против staging (TARGET_SERVICE=orchestrator-staging, PORT=8501, profile staging). Показать лог: захват PREV_IMG → рестарт → health стал ok за N секунд → exit 0. После — `curl localhost:8501/health` = ok. +2. **Rollback-path (САМОЕ ВАЖНОЕ):** сэмулировать НЕработающий деплой и доказать авто-откат. Безопасный способ: запустить хук с заведомо «битым» образом ИЛИ временно подменить health-цель на несуществующий порт, чтобы health-цикл провалился → хук должен сам откатиться на PREV_IMG и поднять staging обратно. Показать лог: «health failed after 60s → ROLLBACK → restored PREV_IMG → staging ok again», exit !=0. ПОСЛЕ теста staging ОБЯЗАН быть жив (`curl localhost:8501/health` = ok). Опиши ТОЧНО, как симулировал фейл (чтобы воспроизводимо и без риска проду). +3. **Прод не задет:** `curl localhost:8500/health` = ok, `docker ps` показывает прод `orchestrator` Up без рестарта (сравни uptime до/после). +4. `git log --oneline origin/main..origin/feature/ORCH-34-deploy-hook` — коммит виден ПОСЛЕ push. + +⚠️ Если для rollback-теста придётся пересобирать/портить staging-образ — делай это ОБРАТИМО и в самом конце верни staging в рабочее состояние (health ok). НЕ оставляй staging сломанным. + +## РЕЗУЛЬТАТ +Новые файлы: `scripts/orchestrator-deploy-hook.sh` (deploy + rollback + health-цикл 10×6с + auto-rollback, параметризован, дефолт staging) + `docs/DEPLOY_HOOK.md`. Оба тест-прогона (happy + rollback) зелёные на staging, прод цел. PR в Gitea. Отчёт → `tasks/orchestrator/reports/dev-2026-06-05-orch34-deploy-hook.md`. Коммит: `feat(staging): add orchestrator deploy hook with health-check and auto-rollback (ORCH-34)`.