Files
AstraDeploy/bot-integration-fsm-plan.md

292 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План интеграции AstraDeploy и бота (FSM + callback API)
## Цели
Сделать наблюдаемую, устойчивую и воспроизводимую установку через бота с поэтапными статусами.
Скрипт уже умеет отдавать:
- `started`
- `step`
- `success`
- `failed`
Нужно оборачивать это в `FSM`-движок на бэкенде бота.
## 1. Точка входа callback
### Endpoint
- `POST /astra-deploy/report`
- Заголовок: `Authorization: Bearer <report-token>`
- Content-Type: `application/json`
### Тело (из скрипта)
```json
{
"status": "step",
"core": "paper",
"dir": "/opt/minecraft/paper",
"port": 25565,
"protocol": "tcp",
"service": "tmux-systemd",
"message": "Installing base packages",
"step": "preflight_packages",
"step_index": 14,
"step_total": 80,
"step_percent": 17
}
```
### Рекомендуемый расширенный payload (бот-раннер может добавить)
```json
{
"request_id": "uuid",
"job_id": "job_123",
"user_id": "123",
"locale": "ru"
}
```
### Ответ
- `200/204` с `{ "ok": true }` или пустым телом.
- Идемпотентность по `(request_id, status, step, step_index, step_total, ts_sec)` или аналогичной паре.
## 2. Запуск задачи из бота
Ключевые параметры запускаемого процесса:
- `--core ...`
- `--dir ...`
- `--port ...`
- `--service systemd|tmux-systemd|screen|none`
- `--user ...`
- `--firewall yes|no`
- `--yes`
- `--accept-license yes` (обязательно в автоматическом)
- `--accept-eula yes` для Java-ядер
- `--report-url ...`
- `--report-token ...`
- `--locale ru|en` (или `LANGUAGE`/`LANG`)
- `--dry-run`, `--update`, `--force-clean`, `--backup-existing`, `--allow-existing`
- `--build`, `--mc-version` для `nethergamesmc`
## 3. FSM состояния
### Состояния
- `QUEUED`
- `RUNNING`
- `VALIDATION`
- `PREPARE_ENV`
- `CORE_INSTALL`
- `POST_INSTALL`
- `WAITING_INPUT`
- `ROLLBACK`
- `DONE`
- `FAILED`
- `DRY_RUN`
- `STALLED` (таймаут между шагами)
### Переходы
- `started` -> `RUNNING`
- `step(parse_complete|prepare_defaults|preflight_*)` -> `VALIDATION`
- `step(preflight_packages|preflight_java|preflight_user|preflight_directory)` -> `PREPARE_ENV`
- `step(install_core|deploy_core|update_core|core_*)` -> `CORE_INSTALL`
- `step(core_post|core_service|service_*|finalize)` -> `POST_INSTALL`
- `status=success` -> `DONE`
- `status=failed` -> `FAILED`
- `--dry-run` (локально определено) -> `DRY_RUN`
- долгий таймаут без новых step -> `STALLED`
- interactive без автоматических флагов и требующие ответа -> `WAITING_INPUT`
### Идёмпотентная обработка
- Игнорировать дубликаты последнего шага в том же `request_id`.
- Обновлять состояние только если новый `step_index` выше предыдущего или статус изменился на более поздний.
## 4. Полная карта `step`
### Общая фаза и предзапуск
- `parse_complete`
- `prepare_defaults`
- `preflight_start`
- `install_start`
- `finalize`
- `core_runtime`
- `core_install`
- `core_update`
### Предпроверки
- `preflight_begin`
- `preflight_validate_root`
- `preflight_detect`
- `preflight_detect_os`
- `preflight_validate_support`
- `preflight_update_mode_check`
- `preflight_validate_plan`
- `preflight_validate_licenses`
- `preflight_validate_port`
- `preflight_directory`
- `preflight_packages`
- `preflight_java`
- `preflight_user`
### Установка/обновление ядер
- `core_resolve_channel`
- `core_resolve_download`
- `core_fetch`
- `core_render`
- `core_configure`
- `core_post`
- `core_service`
- `core_chown`
- `core_backup`
- `core_update_done`
- `core_phpbuild_resolve`
- `core_phpbuild_fetch`
- `core_composer`
- `core_repo_clone`
- `core_install`
- `install_core`
- `deploy_core`
- `update_core`
### Системные шаги
- `packages_start`
- `packages_dry_run`
- `packages_index`
- `download_start`
- `download_completed`
- `download_swap`
- `firewall_start`
- `firewall_done`
- `firewall_manual`
- `java_install`
- `render_start_script`
- `chmod_start_script`
- `service_stop`
- `service_create`
- `service_reload_enable`
- `service_start`
- `user_create`
- `user_exists`
- `prepare_dir`
- `permission_fix`
## 5. Маппинг на UX-сообщения (ru/en)
### RU
- `preflight_*` → «Подготовка окружения и проверок»
- `preflight_packages` / `packages_*` → «Установка базовых пакетов»
- `core_*` → «Установка и настройка ядра»
- `service_*`, `core_service` → «Настройка автозапуска»
- `core_chown` / `prepare_dir` / `permission_fix` → «Настройка доступа»
- `success` → «Установка завершена»
- `failed` → «Ошибка установки»
### EN
- `preflight_*``Environment preflight`
- `core_*``Core installation`
- `service_*``Service setup`
- `failed``Deployment failed`
## 6. Edge-cases по сценариям запуска
- **Interactive (без `--yes`)**
- может остановиться на подтверждении лицензии/ЕULA/директории
- статус `WAITING_INPUT`
- **`--easy`**
- обычный процесс, добавляется план-сводка до preflight
- **`--update`**
- `step_total` уменьшается на 6, проверяется существующая непустая директория
- **`--dry-run`**
- физически без изменений, callback может отсутствовать (как реализовано сейчас)
- **`--force-clean`**
- удаление содержимого директории перед установкой
- **`--backup-existing`**
- резервная копия `*.backup-<timestamp>`
- **`--allow-existing`**
- пропуск проверки непустой директории
- **Неправильный `core` / OS**
- жёсткий fail с объяснением
- **Порт занят**
- fail с деталями `tcp/udp` и предложением сменить порт
- **Сбой callback API**
- для скрипта не фатальный; бот не должен переводить задачу в `FAILED` из-за 5xx webhook-а
## 7. Rollback и пост-факту
На фатальной ошибке скрипт делает:
- лог ошибки
- попытку удаления созданного сервиса (если был создан)
- сообщение с путём лога (`/var/log/astra-deploy/...`)
- завершение с кодом ошибки
Для бота:
- статусы -> `ROLLBACK` (внутренний подстейт)
- показать пользователю:
- возможная причина
- путь лога
- безопасный список ручных действий
## 8. Минимальная модель хранения
### `jobs`
- `id`
- `user_id`
- `core`, `dir`, `port`, `service`, `locale`
- `fsm_state`
- `status`
- `percent`
- `step`, `step_index`, `step_total`, `message`
- `request_id`, `report_token_id`, `process_pid`
- `created_at`, `updated_at`
### `job_events`
- `job_id`
- `status`, `step`, `step_index`, `step_total`, `step_percent`
- `message`
- `raw_payload` (json)
- `created_at`
## 9. Шаблоны уведомлений
### Telegram (RU)
1) Запуск: `🚀 Установка AstraDeploy запущена`
2) Шаг: `⚙️ {percent}% | {state} | {step}`
3) Успех: `✅ Установка завершена`
4) Ошибка: `❌ Установка завершена с ошибкой`
### Telegram (EN)
1) `🚀 AstraDeploy started`
2) `⚙️ {percent}% | {state} | {step}`
3) `✅ Installation completed`
4) `❌ Installation failed`
Кнопки:
- `Получить статус`
- `Логи`
- `Запустить проверку`
- `Повторить (dry-run)`
## 10. Безопасность
- Токены webhook не логировать.
- Проверять `Authorization` строго.
- Проверка whitelist по разрешённым `step`.
- Rate limit на report endpoint.
- Защищённое хранение токенов (vault/secret/env).
## 11. Проверочный набор для интеграции
- `paper` non-interactive, валидные флаги
- `paper` без `--accept-eula` и с `--yes` -> `failed`
- `nethergamesmc --dry-run` -> без изменений, шаги в локальном логе
- занятый порт -> `failed`
- `--update` на пустой директории -> `failed`
- `--force-clean` на непустой директории -> success после очистки
- callback 5xx -> установка продолжается, без ложного FAILED в UI
## 12. Что отдаёт разработчику бота на старте
- список поддерживаемых `core`: `pmmp,paper,purpur,velocity,powernukkitx,nethergamesmc`
- поддерживаемые режимы сервиса: `systemd`, `tmux-systemd`, `screen`, `none`
- список ключевых шагов из этого плана выше
- статусные правила и fallback-поведение для отсутствующего callback