auto-sync: 2026-06-05 14:30:02
This commit is contained in:
108
tasks/orchestrator/reports/dev-2026-06-05-orch10-states.md
Normal file
108
tasks/orchestrator/reports/dev-2026-06-05-orch10-states.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Dev Report: ORCH-10 — per-project Plane state resolution
|
||||
Дата: 2026-06-05
|
||||
Статус: DONE
|
||||
|
||||
## Задача
|
||||
Устранить блокер запуска ORCH-задач: `src/plane_sync.py` хардкодил глобальный `PLANE_STATES` с UUID статусов только enduro-проекта. Webhook-сравнение `new_state == PLANE_STATES["in_progress"]` совпадало только с ET UUID `b873d9eb`, ORCH UUID `e331bfb3` игнорировался — pipeline никогда не стартовал для ORCH-задач.
|
||||
|
||||
## Сделано
|
||||
|
||||
- [x] Создана ветка `feature/ORCH-10-per-project-states` из `origin/main`
|
||||
- [x] Прочитан и изучен существующий код `src/plane_sync.py`, `src/webhooks/plane.py`, `src/projects.py`
|
||||
- [x] Реализован `get_project_states(project_id)` — динамический резолвинг UUID по проекту через Plane API
|
||||
- [x] Добавлен `_DEFAULT_STATES` (= прежний `PLANE_STATES`), `PLANE_STATES` оставлен как alias
|
||||
- [x] Добавлен кэш `_STATES_CACHE` per project_id и функция `reload_project_states()`
|
||||
- [x] Добавлен `stage_to_state(stage, project_id)` через `get_project_states`
|
||||
- [x] `update_issue_state()` переключён на `stage_to_state()` вместо `STAGE_TO_STATE` dict
|
||||
- [x] Все `set_issue_*()` функции резолвят UUID через `get_project_states(project_id)`
|
||||
- [x] `webhooks/plane.py::handle_issue_updated()` — сравнение через `get_project_states(project_id)` вместо глобального `PLANE_STATES`
|
||||
- [x] `webhooks/plane.py::start_pipeline()` QG-0 blocked path — `get_project_states(plane_project_id)["blocked"]`
|
||||
- [x] Написаны 23 новых теста в `tests/test_orch10_states.py`
|
||||
- [x] `pytest tests/ -q` — 342 passed (было 319, +23)
|
||||
- [x] Коммит: `fix(plane): resolve issue states per-project instead of hardcoded enduro UUIDs (ORCH-10)`
|
||||
- [x] Push ветки и создание PR #33
|
||||
|
||||
## Изменённые файлы
|
||||
|
||||
| Файл | Что изменено |
|
||||
|------|-------------|
|
||||
| `src/plane_sync.py` | `_DEFAULT_STATES` + `PLANE_STATES` alias; `_STATES_CACHE`; `get_project_states()`; `reload_project_states()`; `_PLANE_NAME_TO_KEY`; `_STAGE_TO_STATE_KEY`; `stage_to_state()`; `update_issue_state()` → `stage_to_state()`; все `set_issue_*()` через `get_project_states()` |
|
||||
| `src/webhooks/plane.py` | `handle_issue_updated()`: `proj_states = get_project_states(project_id)`, сравнение per-project; `start_pipeline()` QG-0: `get_project_states(plane_project_id)["blocked"]` |
|
||||
| `tests/test_orch10_states.py` | 23 новых теста (NEW FILE) |
|
||||
|
||||
## Результат
|
||||
|
||||
### pytest
|
||||
```
|
||||
342 passed, 4 warnings in 9.66s
|
||||
```
|
||||
Было 319, стало 342 (+23 ORCH-10 теста). Ни один существующий тест не сломан.
|
||||
|
||||
### git diff --name-status origin/main..feature/ORCH-10-per-project-states
|
||||
```
|
||||
M src/plane_sync.py
|
||||
M src/webhooks/plane.py
|
||||
A tests/test_orch10_states.py
|
||||
```
|
||||
Только разрешённые файлы. `qg/checks.py`, launcher, queue — не тронуты.
|
||||
|
||||
### PR
|
||||
**#33** — https://git.mva154.duckdns.org/admin/orchestrator/pulls/33
|
||||
Ветка: `feature/ORCH-10-per-project-states` → `main`. Мержить НЕ нужно (Стрим смержит вручную после ревью).
|
||||
|
||||
## Проверка всех критериев ТЗ
|
||||
|
||||
1. **pytest tests/ -q** — ✅ 342 passed (было 319)
|
||||
|
||||
2. **get_project_states(ET) → ET-UUID; get_project_states(ORCH) → ORCH-UUID** — ✅
|
||||
- `test_get_project_states_enduro`: все 14 ET UUID совпадают
|
||||
- `test_get_project_states_orchestrator`: все 14 ORCH UUID совпадают
|
||||
- `test_get_project_states_et_in_progress_uuid`: ET `in_progress` = `b873d9eb-993c-48cd-97ac-99a9b1623967`
|
||||
- `test_get_project_states_orch_in_progress_uuid`: ORCH `in_progress` = `e331bfb3-e17e-4699-ba48-4abb89c21b7b`
|
||||
|
||||
3. **webhook in_progress распознаётся для обоих проектов** — ✅
|
||||
- `test_webhook_in_progress_et_starts_pipeline`: ET `b873d9eb` → `handle_status_start` called
|
||||
- `test_webhook_in_progress_orch_starts_pipeline`: ORCH `e331bfb3` → `handle_status_start` called
|
||||
- `test_webhook_et_in_progress_not_confused_with_orch`: ET UUID в ORCH-проекте НЕ триггерит
|
||||
|
||||
4. **Fallback при недоступном API → _DEFAULT_STATES** — ✅
|
||||
- `test_get_project_states_api_error_fallback`: Exception → `_DEFAULT_STATES`
|
||||
- `test_get_project_states_non_200_fallback`: HTTP 500 → `_DEFAULT_STATES`
|
||||
- `test_get_project_states_empty_response_fallback`: пустой results → `_DEFAULT_STATES`
|
||||
- `test_get_project_states_none_project_id_fallback`: None → `_DEFAULT_STATES` без API-вызова
|
||||
|
||||
5. **git diff --name-status** — ✅ только `plane_sync.py`, `webhooks/plane.py`, `tests/`
|
||||
|
||||
## Архитектура резолвинга/кэша
|
||||
|
||||
```
|
||||
get_project_states(project_id: str) -> dict[str, str]
|
||||
│
|
||||
├── if project_id in _STATES_CACHE -> return cached
|
||||
│
|
||||
├── GET /api/v1/workspaces/{WORKSPACE}/projects/{project_id}/states/
|
||||
│ ├── success → map by _PLANE_NAME_TO_KEY, fill missing from _DEFAULT_STATES
|
||||
│ │ → _STATES_CACHE[project_id] = resolved; return resolved
|
||||
│ └── failure → log warning; return _DEFAULT_STATES (ET values, safe fallback)
|
||||
│
|
||||
└── None project_id → _DEFAULT_STATES immediately
|
||||
|
||||
stage_to_state(stage, project_id) -> str | None
|
||||
└── _STAGE_TO_STATE_KEY[stage] -> logical key
|
||||
└── get_project_states(project_id)[key] -> UUID
|
||||
```
|
||||
|
||||
**Кэш**: `_STATES_CACHE: dict[str, dict[str,str]]` — per project_id, не протухает (процесс перезапускает). `reload_project_states(project_id=None)` — для тестов и ручного сброса.
|
||||
|
||||
**Backward compat**: `PLANE_STATES` = `_DEFAULT_STATES` (alias). `STAGE_TO_STATE` оставлен как статический dict на ET-значениях (для тестов). `update_issue_state()` теперь вызывает `stage_to_state()` вместо него.
|
||||
|
||||
## Проблемы и решения
|
||||
|
||||
**Проблема**: `$()` в bash-heredoc-е SSH интерпретировался шеллом → bash command substitution error.
|
||||
**Решение**: файлы передавались через `base64 | ssh 'base64 -d > file'` — без heredoc.
|
||||
|
||||
**Проблема**: `git commit -m` с Python-кодом в строке вызывал bash syntax error.
|
||||
**Решение**: многострочный `-m` отдельной строкой через SSH; bash-парсер затронул только переменные типа `$()` — commit прошёл корректно.
|
||||
|
||||
## Следующий шаг
|
||||
Отправить на ревью → Стрим мержит PR #33 → ребилд docker-образа → ручная проверка на проде.
|
||||
Reference in New Issue
Block a user