Раздел: System
Идентификатор:updates· Экран:ui/updates/(8 файлов)
Снимок: 2026-10-11
1. Зачем и что это
Это единственный экран, где сходятся сборка, публикация и установка, поэтому он же служит точкой входа для агента: через backend API того же назначения работают MCP-инструменты dev_build, dev_swap, dev_deploy, dev_gate.
2. Как попасть
Хаб инструментов → секция System → карточка «Обновления» (hub_updates_title, подпись «Проверка и установка обновлений приложения и окружения», тайл — «Обновл.»).
| Откуда ещё | Путь |
|---|---|
| Чат Codex | пункт «Updates» в меню треда |
| Мост | app_navigate с screen: "updates" |
Маршрут: Screen.kt → MainRouter (UpdatesScreen).
3. Экран: элементы и действия
| Карточка | Что делает |
|---|---|
| Обновление приложения | Проверка манифеста, скачивание APK, кнопка Install |
EnvironmentCard | Обновление окружения целиком |
BackendControlCard | Сборка, замена и перезапуск backend, очистка |
| Developer-панель | Сборка APK, публикация на сервер, backend, codex |
InstalledVersionsCard | Установленные версии компонентов |
UpdateLogPanel | Хвост л��га операций и состояние операции |
Developer-панель (UpdatesDevCards.kt):
| Карточка | Кнопки | Что делает |
|---|---|---|
| APK build | Build APK | Сборка через backend API; режим debug/release |
| Release to server | Publish | Публикация APK и backend на agent.y83.ru |
| Backend | Build backend, Replace & restart, Cleanup | Сборка бинаря, smoke → switch → health → rollback, очистка |
| Codex | Update codex | Скачать бинарь с GitHub и подменить, со smoke и schema diff |
4. Возможности подробно
Проверка обновления
Сверка идёт по манифесту на сервере. Экран сравнивает:
versionCodeманифеста с установленнымAppVersion.code;- sha256 установленного APK (
AppVersion.installedApkSha256()) с sha256 из манифеста.
Второе сравнение ловит особый случай sameCodeRebuild: та же версия, но пересобранный APK. Если sha256 отличается, экран покажет обновление как доступное — иначе пересборка той же версии была бы невидима.
Когда установленная сборка совпадает с доступным релизом, карточка прямо сообщает: «Installed build matches the available release».
Установка APK
installApk():
- проверяет
Updater.isInstallAllowed(ctx)— разрешение на установку из неизвестных источников; если его нет, открывает настройки и просит повторить; - ищет локальный APK на sdcard: 26 МБ не гоняются по кругу, но файл ставится только при совпадении sha256 с манифестом;
- если локального файла нет — скачивает и запускает установщик;
- состояние
downloadingблокирует повторное нажатие.
Кнопка Install всегда ведёт в системный установщик или файловый менеджер — прямая установка через pm install на MIUI не работает (нет права MANAGE_USERS).
Операции окружения
Каждая операция — с состоянием (OpState) и логом. UpdateLogPanel показывает хвост лога операции, подсвечивая активные строки (logLineState).
| Операция | Что делает |
|---|---|
| Обновление окружения | POST /api/v1/env/update + опрос статуса |
| Сборка APK | POST /api/v1/env/build + опрос build/status |
| Публикация | POST /api/v1/env/deploy + опрос deploy/status |
| Сборка backend | dev_build {target:"backend"} |
| Замена backend | smoke → switch → health → rollback, с автооткатом |
| Обновление codex | Скачать с GitHub, smoke, schema diff, замена бинаря |
Логи и ошибки
Ошибки и сообщения операций показываются на экране и дублируются в лог (FileLog.log), откуда их читает dev_log {source: "deploy" | "swap" | "gate"}.
5. Данные: БД, файлы, настройки
| Что | Где лежит | Как меняется | Кто читает |
|---|---|---|---|
| Установленная версия | AppVersion.name / .code | Установка APK | Экран |
| Манифест релиза | agent.y83.ru | Публикация | Проверка обновления |
| sha256 установленного APK | Вычисляется на устройстве | — | Сравнение с манифестом |
| Логи операций | Файлы (через backend) | dev_log | Экран и агент |
| Версия backend | VERSION в репозитории | build-backend.sh | Карточка версий |
Версия приложения не попадает в генерируемый BuildConfig.kt — она живёт в app/version-stamp.properties и в рантайме в util/AppVersion.
6. Backend: REST/роуты
| Метод и путь | Назначение | Обработчик |
|---|---|---|
GET /api/v1/env/versions | версии компонентов | envHandler.Versions |
GET /api/v1/env/status | статус окружения | envHandler.Status |
GET /api/v1/env/log | хвост лога установщика | envHandler.LogTail |
POST /api/v1/env/update | обновить окружение | envHandler.Update |
POST /api/v1/env/build | собрать APK | envHandler.Build |
GET /api/v1/env/build/status | статус сборки APK | envHandler.BuildStatus |
POST /api/v1/env/deploy | публикация на прод | envHandler.Deploy |
GET /api/v1/env/deploy/status | статус публикации | envHandler.DeployStatus |
GET /api/v1/env/codex | текущая и апстрим-версия codex | envHandler.Codex |
POST /api/v1/env/codex/upgrade | обновление codex | envHandler.CodexUpgrade |
GET /api/v1/env/codex/upgrade/status | статус обновления codex | envHandler.CodexUpgradeStatus |
Роуты: backend/internal/api/v1/routes.go:67–77.
7. Мост и MCP
| Инструмент | Что делает | |||
|---|---|---|---|---|
| `dev_build {target: "apk"\ | "backend", mode}` | Сборка APK или backend | ||
dev_swap {confirm: true} | Замена работающего backend с откатом при неудаче | |||
dev_deploy {confirm: true, skip} | Публикация на agent.y83.ru | |||
| `dev_gate {mode: "fast"\ | "full"}` | Ворота качества перед «готово» | ||
dev_status {what} | Сводка состояния сборки, swap, публикации | |||
| `dev_log {source: "deploy"\ | "swap"\ | "gate"\ | "setup"}` | Логи операций |
Правила проекта: APK собирается только через backend API или dev_build, backend — только через build-backend.sh + swap. Прямой gradle assemble*, go build и запуск supervisord запрещены механически.
8. Настройки, конфиг, квоты и лимиты
| Параметр | Значение | Где задаётся |
|---|---|---|
| Режим сборки | debug / release | setBuildMode |
| Время сборки | debug ~30 с, release ~5 мин | Подпись карточки |
| Публикация | agent.y83.ru | dev_deploy / Updates |
| Проверка обновления | versionCode + sha256 | ViewModel |
9. Ловушки и ограничения
- Установка требует разрешения на неизвестные источники. Без него кнопка Install откроет настройки и попросит повторить — это ожидаемо, не ошибка.
- Локальный APK ставится только при совпадении sha256. Файл с тем же именем, но другой сборкой, будет отвергнут.
- Прямая установка через
pm installне работает на MIUI (нет MANAGE_USERS) — Install всегда открывает системный установщик. - Debug-сборка подписана тем же ключом, что и release, поэтому её можно ставить поверх release; обратное — не всегда.
- Замена backend с откатом: smoke-тест проходит до переключения, а при неудаче бинарь возвращается назад. Поэтому «замена» может выглядеть как ничего не сделавший.
- Версия не должна попадать в
BuildConfig.kt: файл перегенерируется при каждой сборке и тянет за собой полную компиляцию KSP. Версия живёт вapp/version-stamp.properties. - Обновление codex на dev-машине идёт отдельно — установщик этот шаг пропускает, чтобы не откатить версию из GitHub.
- Публикация на прод требует подтверждения — действие необратимо.
10. Источники правды
app/src/main/java/com/y83/ws/ui/updates/UpdatesScreen.kt— экран.app/src/main/java/com/y83/ws/ui/updates/UpdatesViewModel.kt— проверка, установка, операции.app/src/main/java/com/y83/ws/ui/updates/UpdatesCards.kt,UpdatesDevCards.kt— карточки.app/src/main/java/com/y83/ws/ui/updates/UpdatesOperations.kt— карточки операций, лог, состояния.app/src/main/java/com/y83/ws/ui/updates/UpdateHost.kt,UpdatesFormat.kt— хост обновлений, форматирование.app/src/main/java/com/y83/ws/util/AppVersion.kt— установленная версия и sha256.app/build.gradle.kts,app/version-stamp.properties— версия и её источник.backend/internal/api/v1/routes.go:67–77— роуты окружения.skills/y83-app/SKILL.md,y83-publish/SKILL.md— workflow сборки и публикации.