feat(bot): клиент SourceCraft API — прогоны, логи кубов, sha коммита, ретраи
- SourceCraftClient (httpx): list_runs, get_run, get_cube_logs (постранично), run_commit_sha; ретраи на сетевые ошибки и 5xx с экспоненциальной задержкой, 4xx — SourceCraftError без повторов - модели: RunStatus/EventType из swagger, «1970-01-01» = не задано, failed_cubes без служебных #-кубов - у прогона в API нет sha → куб check/meta в tgit-uploads печатает TGIT_COMMIT_SHA (ADR-014) - CLI: python -m app.sourcecraft.cli runs - тесты на реальных ответах API (фикстуры), порог покрытия 45 → 80 Refs #10 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,3 +121,11 @@
|
||||
**Решение:** конвейер из пяти шагов (SPEC §4.3.1): детерминированный фильтр → отдельный LLM-вызов «страж» с JSON-вердиктом `safe|attack` (невалидный ответ = `attack`) → отдельный LLM-вызов «планировщик», который получает только промт и список контейнеров и возвращает `LogQuery` → валидация → выполнение в Python. Пользователю показывается итоговый grep и найденные строки. Атака → отказ + алерт админам.
|
||||
**Альтернативы:** один вызов LLM с инструкцией «откажись, если атака» — страж и исполнитель в одном контексте, injection обходит оба; передавать логи в LLM для поиска — injection из логов и утечка секретов.
|
||||
**Последствия:** два LLM-вызова на запрос (латентность, токены → квота 30/сутки); даже при обходе стража вред ограничен схемой `LogQuery`.
|
||||
|
||||
## ADR-014: Связь «прогон ↔ коммит» — через куб `meta`, печатающий sha
|
||||
**Дата:** 2026-10-14 · **Статус:** принято (уточняет ADR-003)
|
||||
|
||||
**Контекст:** бот должен понять, какой прогон CI относится к его пушу. В API SourceCraft у прогона нет sha коммита (ни в списке, ни в деталях), фильтра по коммиту нет; логи служебных кубов (`#git-clone`) API не отдаёт.
|
||||
**Решение:** первый куб задачи `check` в `tgit-uploads` — `meta`: `echo "TGIT_COMMIT_SHA=$SOURCECRAFT_COMMIT_SHA"`. Бот читает его лог (`SourceCraftClient.run_commit_sha`) и сопоставляет прогон с пушем.
|
||||
**Альтернативы:** запускать CI из бота вручную (`POST /cicd/runs` с `head.commit`) — номер прогона известен сразу, но push-триггер пришлось бы убрать, и ручные пуши в репозиторий остались бы без CI; сопоставление по времени — ломается при параллельных пушах.
|
||||
**Последствия:** +1 короткий куб на прогон; куб `meta` нельзя удалять или переименовывать (он в `.sourcecraft/`, который бот защищает от правок); прогоны старше этого решения sha не имеют.
|
||||
|
||||
Reference in New Issue
Block a user