feat(runner): tgit-runner — сервисы в песочнице на хосте, деплой после push (#13)
CI / ruff · mypy · pytest (pull_request) Successful in 4m3s
CI / ruff · mypy · pytest (pull_request) Successful in 4m3s
- infra/runner/tgit-runner: deploy/restart/remove/list по SSH forced command; аргументы не исполняются и не глобятся; архив — только файлы и папки, без «..», ≤ 20 МБ, есть main.py; health_url — только localhost - песочница: uid 10001, read-only, tmpfs noexec, cap-drop ALL, no-new-privileges, 128 МБ без swap, 0.25 CPU, 64 PID, --network none (сеть — только по egress-allow админа), лимит 10 сервисов, 2 образа - новая версия стартует рядом (-next) и заменяет старую, только став healthy; иначе удаляется, старая работает, exit 3 - бот: после push git archive изменённых services/<name>/ → runner; автору — «🚀 работает» или «⛔ не развёрнут» с логом, команде — алерт ⛔; удалённая папка → remove; «♻️ Перезапустить» в «Статусе» для админа (S-5) - examples/escape_attempts: все попытки выбраться — BLOCKED на живом Docker - install.sh, authorized_keys.example; CD бота обновляет runner на хосте Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -203,7 +203,9 @@ SQLAlchemy 2 (async) + Alembic. PostgreSQL в Compose; в тестах — SQLit
|
||||
`authorized_keys` пользователя `tgit-deploy`). Подкоманды: `deploy <service> <sha>`, `restart <service>`,
|
||||
`probe <service> <path>` (HTTP-проба изнутри сети сервиса). Аргументы валидируются: имя `^[a-z][a-z0-9-]{1,30}$`, sha — hex.
|
||||
|
||||
`deploy`: забирает архив `services/<service>` по sha из `tgit-uploads` → собирает образ `tgit-svc-<service>:<sha>` из
|
||||
`deploy`: получает архив `services/<service>` в stdin — его делает бот (`git archive <sha>:services/<service>`)
|
||||
сразу после push, так что у хоста нет доступа к репозиторию → проверяет архив (только файлы и папки, без `..`,
|
||||
≤ 20 МБ, есть `main.py`) → собирает образ `tgit-svc-<service>:<sha>` из
|
||||
шаблона (`python:3.12-slim` + `requirements.txt`, `HEALTHCHECK` из `tgit.yaml` сервиса, если задан) → запускает:
|
||||
|
||||
```
|
||||
@@ -216,7 +218,11 @@ docker run -d --name tgit-svc-<service> --label tgit.managed=true --label tgit.s
|
||||
--restart on-failure:3
|
||||
--log-opt max-size=5m --log-opt max-file=2
|
||||
```
|
||||
Если новый контейнер не стал healthy за 60 с — откат на предыдущий образ и ненулевой код выхода (CD падает → алерт ⛔).
|
||||
Новая версия стартует рядом со старой как `tgit-svc-<service>-next` и заменяет её, только став healthy (с
|
||||
`health_url` — по `HEALTHCHECK`, без него — 10 с без рестартов). Иначе новый контейнер удаляется, старый продолжает
|
||||
работать, код выхода 3 → бот пишет автору push «⛔ не развёрнут» с хвостом лога и поднимает алерт ⛔ всей команде.
|
||||
Сервис, папка которого исчезла из коммита, удаляется (`remove`). Перезапуск — `restart` из «Статуса» (админ).
|
||||
Установка и обновление — [`infra/runner/README.md`](../infra/runner/README.md).
|
||||
|
||||
## 5. CI/CD
|
||||
|
||||
|
||||
Reference in New Issue
Block a user