feat(pipeline): уведомления CI/CD — PipelineWatcher, CI загрузок на Gitea Actions #50

Merged
Eleboba merged 2 commits from feat/11-pipeline-watcher into dev 2026-10-19 12:40:52 +03:00
Owner

Closes #11 · C-24, C-30…C-34 · ADR-016

Как это работает

push ─► pushes(ci=pending) ─► wake()
PipelineWatcher ─ Gitea API runs?head_sha=… (10 с, бэкофф до 60 с)
   ├ running   ─► «CI: ⏳ идёт проверка» в сообщении о push
   ├ success   ─► «✅ CI пройден» ─► tgit-runner ─► «🚀 CD: сервисы … развёрнуты» / ⛔ + алерт всем
   ├ failed    ─► «❌ CI упал на шаге check / lint» + хвост лога (длинный — ещё и файлом), CD не запускается
   └ 30 мин без вердикта ─► ⌛, CD не запускается

Что сделано

  • CI загрузок — Gitea Actions (ADR-016): infra/uploads-template/.gitea/workflows/check.yml — compile · ruff · bandit · pytest по шагам. У прогона Gitea есть head_sha, куб meta не нужен. .gitea/ защищён от правок из бота.
  • app/pipeline/: протокол CIProvider и gitea.py (ретраи на сеть и 5xx, упавший шаг, лог джоба). SourceCraft подключится второй реализацией, наблюдатель не изменится.
  • PipelineWatcher: состояние — в pushes.ci_status/cd_status и pipeline_runs, сообщение о push каждый раз рендерится из БД. Опрос — только пока есть незавершённые push, иначе спит до нового push. После рестарта продолжает: ждёт CI дальше, прерванный деплой повторяет.
  • Деплой только после зелёного CI. Прогоны могут закончиться не по порядку — старый push не разворачивает сервис, который развернёт более новый (иначе откатил бы его).
  • CI_PROVIDER=none (по умолчанию) — прежнее поведение: деплой сразу после push, без строки CI.
  • Миграция 0002 (данные): старые push → skipped, чтобы первый тик не разослал авторам «таймаут CI».
  • ADR-016, ARCHITECTURE §2.5/§5.2, README, DEPLOY, .env.example.

Как проверено

  • Живой Gitea: workflow установлен в HSE/tgit-uploads (540eaa4) → прогон 5225 ✅ за 28 с, все 7 шагов, тест hello прошёл; GiteaCI.find(sha) на живом API — running → success.
  • 357 тестов (23 новых): клиент Gitea на respx (статусы, упавший шаг, отмена, ретраи, 404); наблюдатель — зелёный путь, красный с логом, длинный лог файлом, таймаут, падение деплоя, порядок версий, рестарт посреди деплоя, без CI, цикл переживает ошибки API и просыпается на push. Покрытие 92 %, ruff, mypy strict.

Чтобы включить на dev

В /srv/tgit/dev/.env: CI_PROVIDER=gitea, CI_TOKEN=<токен Gitea с чтением HSE/tgit-uploads>. Без них бот работает как раньше.

Чек-лист

  • rebase на origin/dev
  • lint + тесты зелёные
  • секретов в диффе нет
  • лог в issue дописан

🤖 Generated with Claude Code

Closes #11 · C-24, C-30…C-34 · ADR-016 ## Как это работает ``` push ─► pushes(ci=pending) ─► wake() PipelineWatcher ─ Gitea API runs?head_sha=… (10 с, бэкофф до 60 с) ├ running ─► «CI: ⏳ идёт проверка» в сообщении о push ├ success ─► «✅ CI пройден» ─► tgit-runner ─► «🚀 CD: сервисы … развёрнуты» / ⛔ + алерт всем ├ failed ─► «❌ CI упал на шаге check / lint» + хвост лога (длинный — ещё и файлом), CD не запускается └ 30 мин без вердикта ─► ⌛, CD не запускается ``` ## Что сделано - **CI загрузок — Gitea Actions** (ADR-016): `infra/uploads-template/.gitea/workflows/check.yml` — compile · ruff · bandit · pytest по шагам. У прогона Gitea есть `head_sha`, куб `meta` не нужен. `.gitea/` защищён от правок из бота. - **`app/pipeline/`**: протокол `CIProvider` и `gitea.py` (ретраи на сеть и 5xx, упавший шаг, лог джоба). SourceCraft подключится второй реализацией, наблюдатель не изменится. - **`PipelineWatcher`**: состояние — в `pushes.ci_status/cd_status` и `pipeline_runs`, сообщение о push каждый раз рендерится из БД. Опрос — только пока есть незавершённые push, иначе спит до нового push. После рестарта продолжает: ждёт CI дальше, прерванный деплой повторяет. - **Деплой только после зелёного CI.** Прогоны могут закончиться не по порядку — старый push не разворачивает сервис, который развернёт более новый (иначе откатил бы его). - `CI_PROVIDER=none` (по умолчанию) — прежнее поведение: деплой сразу после push, без строки CI. - Миграция 0002 (данные): старые push → `skipped`, чтобы первый тик не разослал авторам «таймаут CI». - ADR-016, ARCHITECTURE §2.5/§5.2, README, DEPLOY, `.env.example`. ## Как проверено - **Живой Gitea:** workflow установлен в `HSE/tgit-uploads` (`540eaa4`) → прогон [5225](https://gitea.24studbank.ru/HSE/tgit-uploads/actions/runs/5225) ✅ за 28 с, все 7 шагов, тест `hello` прошёл; `GiteaCI.find(sha)` на живом API — `running` → `success`. - 357 тестов (23 новых): клиент Gitea на respx (статусы, упавший шаг, отмена, ретраи, 404); наблюдатель — зелёный путь, красный с логом, длинный лог файлом, таймаут, падение деплоя, порядок версий, рестарт посреди деплоя, без CI, цикл переживает ошибки API и просыпается на push. Покрытие 92 %, ruff, mypy strict. ## Чтобы включить на dev В `/srv/tgit/dev/.env`: `CI_PROVIDER=gitea`, `CI_TOKEN=<токен Gitea с чтением HSE/tgit-uploads>`. Без них бот работает как раньше. ## Чек-лист - [x] rebase на origin/dev - [x] lint + тесты зелёные - [x] секретов в диффе нет - [x] лог в issue дописан 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Eleboba added 1 commit 2026-10-19 00:25:23 +03:00
- app/pipeline: протокол CIProvider, клиент Gitea Actions (прогон по head_sha, упавший
  шаг, лог джоба, ретраи), PipelineWatcher — опрос только при незавершённых push,
  сообщение о push обновляется CI ⏳ → ✅/❌ → CD 🚀/⛔, автору — отдельные уведомления
- деплой сервисов — только после зелёного CI; старый push не откатывает сервис,
  который развернёт более новый; после рестарта бот продолжает с того же места
- CI_PROVIDER=none — прежнее поведение (деплой сразу после push)
- шаблон tgit-uploads: .gitea/workflows/check.yml; .gitea/ защищён от правок из бота
- миграция 0002: старые push помечены skipped, чтобы не слать им «таймаут CI»
- ADR-016, ARCHITECTURE §2.5/§5.2, README, DEPLOY, .env.example

Refs #11

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eleboba added 1 commit 2026-10-19 00:37:20 +03:00
У Settings нет префикса env, поэтому переменная CI=true с раннера Gitea
попадала в поле ci и роняла создание настроек во всех тестах.

Refs #11

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eleboba merged commit 446208c8ad into dev 2026-10-19 12:40:52 +03:00
Sign in to join this conversation.