auto-sync: 2026-06-04 10:10:01
This commit is contained in:
85
tasks/orchestrator/DEV_TASK_GITEA_MERGE_GATE.md
Normal file
85
tasks/orchestrator/DEV_TASK_GITEA_MERGE_GATE.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# DEV TASK: закрыть вторую дверь баг-8 — gitea PR-merged обходит deploy-QG
|
||||
|
||||
## Контекст / проблема
|
||||
БАГ 8 (deploy без QG) был починен в `stage_engine.advance_stage` через `check_deploy_status`
|
||||
(читает `deploy_status:` из frontmatter `14-deploy-log.md`). Но есть **вторая дверь**:
|
||||
обработчик Gitea-вебхука `pull_request` при `action=closed & merged=true` **слепо** переводит
|
||||
задачу в `done` для ЛЮБОЙ стадии, минуя QG.
|
||||
|
||||
Боевой инцидент (ET-012, task 30):
|
||||
- deployer мержит PR в начале работы → прилетает webhook `closed+merged` → `gitea.py` мгновенно
|
||||
ставит `done` (за 33 сек), ПОКА deployer ещё работает 6 минут.
|
||||
- deployer затем пишет `deploy_status: FAILED` — но поздно, задача уже `done`.
|
||||
- `check_deploy_status` **не вызывается вообще** → фейк-done вернулся через merge-вебхук.
|
||||
|
||||
## Файл
|
||||
`src/webhooks/gitea.py` — единственный файл с изменениями кода.
|
||||
|
||||
## Текущий код (конец обработчика `pull_request`, примерно стр. 336-339)
|
||||
```python
|
||||
elif action == "closed" and pr.get("merged", False):
|
||||
update_task_stage(task_id, "done")
|
||||
notify_stage_change(task_id, current_stage, "done")
|
||||
logger.info(f"Task {task_id}: PR merged, stage → done")
|
||||
```
|
||||
|
||||
## Что нужно
|
||||
Merge PR **не должен** напрямую ставить `done`, когда `current_stage == "deploy"`.
|
||||
Для deploy финальный переход deploy→done обязан проходить через `check_deploy_status`
|
||||
(вердикт deployer'а), как и задумано баг-8 фиксом. Для всех ОСТАЛЬНЫХ стадий — поведение
|
||||
merge сохранить как есть (прямой `done` — это легитимный путь, когда фичу мержат не из конвейера).
|
||||
|
||||
### Требуемая логика
|
||||
```python
|
||||
elif action == "closed" and pr.get("merged", False):
|
||||
# БАГ 8 (вторая дверь): для стадии deploy финальный done гейтится
|
||||
# вердиктом deployer'а (check_deploy_status), а НЕ фактом merge PR.
|
||||
# deployer мержит PR в начале работы — merge != успешный деплой.
|
||||
if current_stage == "deploy":
|
||||
logger.info(
|
||||
f"Task {task_id}: PR merged at deploy stage — done gated by "
|
||||
f"deployer verdict (check_deploy_status), not merge event. Ignoring merge-driven done."
|
||||
)
|
||||
return
|
||||
update_task_stage(task_id, "done")
|
||||
notify_stage_change(task_id, current_stage, "done")
|
||||
logger.info(f"Task {task_id}: PR merged, stage → done")
|
||||
```
|
||||
|
||||
**Обоснование игнора (а не вызова advance_stage):** на deploy стадии deployer-job
|
||||
уже запущен через очередь (`enqueue_job` на входе стадии). Когда он завершится,
|
||||
launcher вызовет `advance_stage`, который выполнит `check_deploy_status` и сам решит
|
||||
done/rollback. Дублировать advance_stage из merge-вебхука НЕ нужно — это создаст гонку.
|
||||
Merge-вебхук на deploy просто **молча игнорируется** (done решает только вердикт).
|
||||
|
||||
## ОГРАНИЧЕНИЯ (НЕ трогать)
|
||||
- НЕ менять ветки `action == "reviewed"` (APPROVED / REQUEST_CHANGES) — они работают.
|
||||
- НЕ менять HMAC, project-filter (`get_project_by_repo`), импорты кроме необходимого.
|
||||
- НЕ трогать `stage_engine.py`, `launcher.py`, `checks.py`, `stages.py`, `conftest.py`.
|
||||
- НЕ трогать nginx, openclaw.json, .env, queue, PLANE_STATES, gitea_public_url.
|
||||
- Сохранить блок launcher.py:475.
|
||||
|
||||
## Тесты
|
||||
- Добавить тест(ы) в существующий тест-файл вебхуков gitea (найти где тестируется
|
||||
`pull_request` merged — вероятно `tests/.../test_gitea_webhook*.py` или аналог).
|
||||
- Кейсы:
|
||||
1. `closed+merged` при `current_stage="deploy"` → задача НЕ переходит в `done`
|
||||
(остаётся на deploy), `update_task_stage(...,"done")` НЕ вызван.
|
||||
2. `closed+merged` при `current_stage` НЕ deploy (например `review` или иной валидный) →
|
||||
задача переходит в `done` (регрессия не сломана).
|
||||
- Запустить полный `pytest`. Baseline: **227 passed + 10 failed** (10 failed = off-limits:
|
||||
9 HMAC/401 + 1 webhook-POST — их НЕ чинить, они и должны падать).
|
||||
Новые тесты должны дать **229+ passed, те же 10 failed**.
|
||||
|
||||
## Процесс сдачи
|
||||
- Ветка от актуального main orchestrator: `fix/gitea-merge-deploy-gate`.
|
||||
- Прямой push в main запрещён (pre-receive hook) → только через PR в Gitea.
|
||||
- Gitea токен: `docker exec orchestrator printenv ORCH_GITEA_TOKEN`.
|
||||
- Репо на проде: `/home/slin/repos/orchestrator` (slin@82.22.50.71, пароль в .env).
|
||||
- В отчёте: commit-хеш, номер PR, вывод pytest (passed/failed), diff gitea.py.
|
||||
- Отчёт положить в `tasks/orchestrator/reports/dev-2026-06-04-gitea-merge-gate.md`.
|
||||
|
||||
## Verify (после мержа PR)
|
||||
1. Перезапустить контейнер orchestrator (подхватить новый код).
|
||||
2. Прогнать любую задачу до deploy ИЛИ юнит-проверкой убедиться: merge-вебхук на deploy
|
||||
не ставит done; done ставится только после deployer verdict через check_deploy_status.
|
||||
Reference in New Issue
Block a user