Полный цикл M0–M5 по ТЗ: - Catalog Service: импорт runtipi/runtipi-appstore → catalog_apps, идемпотентный синк, кэш логотипов, авто раз в 24ч (APScheduler), флаг update_available. - App Engine: установка (клон золотого шаблона → pct push compose/.env → docker compose up → health-check) с журналом шагов, шифрованием env (Fernet), генерацией random-секретов и прогрессом по WebSocket. - Lifecycle: start/stop/restart/logs/delete + реконсиляция состояния (orphaned). - Update/Rollback через снапшоты Proxmox (pre-update, хранение последнего 1). - UI: экраны App Store (сетка/поиск/категории), страница приложения, мастер установки (динамическая form_fields + advanced + прогресс + креденшелы), My Apps; i18n ru/en; атрибуция Runtipi. - RBAC app:view/install/manage; только unprivileged LXC; pct exec/push без shell-инъекций (base64 + экранирование). - Модели catalog_apps/installed_apps/app_operations (миграции 31–32). - Docs: golden-template, appstore-poc/catalog/engine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.2 KiB
3.2 KiB
App Store — M1 Catalog Service
Конвертер каталога runtipi/runtipi-appstore → таблица catalog_apps. Backend-этап
(UI — позже). Наполнение и отдача каталога через API.
Компоненты
- Модель:
backend/app/models/appstore.py→CatalogApp(таблицаcatalog_apps). - Миграция:
migrate_appstore_catalog()вbackend/migrations/migrations.py(авто на старте). - Сервис:
backend/app/services/appstore_catalog.pyCatalogProvider(ABC) →RuntipiCatalogProvider(скачивание tarball, парсинг).sync_catalog(db, ref?)— идемпотентный upsert + кэш логотипов.start_catalog_scheduler()— авто-синк раз вCATALOG_SYNC_INTERVAL_HOURS(APScheduler).
- API:
backend/app/api/appstore/catalog.py(роутер подключён вmain.py). - Права:
app:view,app:install,app:manage(backend/app/rbac/permissions.py).
Настройки (env, все с дефолтами)
| Переменная | Дефолт | Назначение |
|---|---|---|
RUNTIPI_APPSTORE_REPO |
runtipi/runtipi-appstore |
источник |
RUNTIPI_APPSTORE_REF |
master |
ветка/tag/commit (рекомендуется фиксировать) |
APPSTORE_DATA_DIR |
/app/data/appstore |
кэш логотипов (volume appstore_data) |
CATALOG_SYNC_INTERVAL_HOURS |
24 |
периодичность авто-синка |
APPSTORE_HOST_ARCH |
amd64 |
арх. нод (пометка неподдерживаемых) |
API
GET /api/appstore/catalog?q=&category=&available_only=&limit=&offset= (app:view)
GET /api/appstore/catalog/meta (app:view)
GET /api/appstore/catalog/{app_id} (app:view)
GET /api/appstore/catalog/{app_id}/logo (app:view)
POST /api/appstore/catalog/sync (app:manage)
Verification (DoD M1)
- Запустить синхронизацию:
POST /api/appstore/catalog/sync(или дождаться авто-джоба).- Ожидаемо:
stats.total ≥ 150(на текущем репозитории проходит фильтр ~265 приложений).
- Ожидаемо:
GET /api/appstore/catalog/meta→total,last_synced_at, список категорий.GET /api/appstore/catalog?q=uptime→ карточки сlogo_url.GET /api/appstore/catalog/{app_id}→form_fields,compose_yaml,description_md.- Идемпотентность: повторный
syncне увеличиваетtotalнеконтролируемо (created≈0,updated>0). - Устойчивость (F-CAT-5): битый
config.jsonодного приложения не роняет синк —errors++, остальные проходят.
Оффлайн-валидация парсера на реальном репозитории (stdlib): 271 папка, 270 с config/compose/logo/описанием, 0 ошибок парсинга, 143 с формами, 5 deprecated исключены → 265 проходят фильтр.