Runbook — релиз и публикация APK
Audience: operator. Описывает текущий ручной поток. Механизация пайплайна ведётся отдельно (GitLab issue #11) — здесь именно то, что делается руками сегодня.
⚠ Подписной keystore — секрет; см. runbook секретов. Никогда не печатать пароль keystore.
Поток (сборка → подпись → публикация)
1. Сборка (на worker)
APK собирается на воркере по проверенному рецепту: JDK21 + bindgen-sysroot env-переменные (нужны для aws-lc-sys). Раскладка Tauri: backend/ + фронт frontend/ (nx). Debug-артефакт ~684 MB → strip → ~32 MB. (Детальный build-рецепт — во внутренней памяти команды android-apk-build-recipe; здесь — операционный обзор.)
2. Подпись
С версии 0.5.1 действует РОТИРОВАННЫЙ ключ (
release-key-v2, issue #90). Источник подписи для 0.5.1 и новее —release-key-v2.jks.age+release-key-v2.creds.age(alias + пароль) изkontinuum/secrets. Старыйrelease-key.jks.age— только архив для воспроизводимости 0.5.0; в репозиторииkontinuum-appключа больше нет.
cd ~/secrets-repo
age -d -i ~/.git-key release-key-v2.jks.age > /tmp/release-key.jks
# alias + пароль (НЕ печатать в лог):
ALIAS=$(age -d -i ~/.git-key release-key-v2.creds.age | sed -n 's/^alias=//p')
PASS=$(age -d -i ~/.git-key release-key-v2.creds.age | sed -n 's/^storepass=//p')
# подписать собранный APK этим keystore (apksigner --ks /tmp/release-key.jks
# --ks-key-alias "$ALIAS" --ks-pass "pass:$PASS"), затем:
unset PASS
shred -u /tmp/release-key.jksРОТАЦИЯ ЛОМАЕТ IN-PLACE ОБНОВЛЕНИЕ (0.5.0 → 0.5.1)
Подписной серт у 0.5.1 другой (новый ключ). Android требует совпадения подписи для in-place апдейта, поэтому пользователи 0.5.0 один раз переустановят приложение при переходе на 0.5.1 (self-update не сработает — клиент отклонит APK с чужой подписью). Отметь это явно в release notes 0.5.1. Начиная с 0.5.1 и далее in-place обновление снова работает (ключ стабилен).
signing key = crown jewel
Ключ подписи = возможность выпускать обновления для установленной базы. Потеря или утечка боевого ключа = невозможность апдейтить эту базу. Боевой ключ хранится только зашифрованным в kontinuum/secrets (release-key-v2.jks.age); копия приватного age-ключа (~/.git-key) off-machine = его страховка. В git-репозитории приложения ключа нет (был утечкой со слабым паролем — issue #90, закрыт #29).
3. sha256
sha256sum kontinuum-<ver>-arm64.apk4. Публикация (на aruba1)
Скопировать APK на update-endpoint и записать latest.json:
scp kontinuum-<ver>-arm64.apk root@94.177.204.91:<updates-static-root>/
# затем на aruba1 записать latest.json (схема ниже)latest.json (текущая схема, живой пример):
{
"versionCode": 4000,
"versionName": "0.4.0",
"url": "https://updates.kontinuum.cloud/kontinuum-0.4.0-arm64.apk",
"sha256": "<sha256 опубликованного APK>",
"notes": "<человекочитаемые release notes>",
"minSdk": 24
}5. Проверка
curl -s https://updates.kontinuum.cloud/latest.json # видна новая версия?
# приложение само сверяет sha256 при self-update — sha256 в json ОБЯЗАН
# совпадать с опубликованным APK, иначе клиент отклонит обновление.Инфраструктура канала
Раздачей занимается kontinuum-updates-static.service (python static 127.0.0.1:8088) за cloudflared.service на aruba1 — см. runbook туннелей §2. Если latest.json не виден снаружи — сначала проверить эти два юнита.
Чек-лист релиза
- [ ] APK собран на worker (JDK21 + bindgen env), stripped.
- [ ] Подписан release-key-v2 (0.5.1+); расшифрованная копия
shred-нута. - [ ] (если первый релиз на новом ключе) release notes явно предупреждают о переустановке.
- [ ] sha256 посчитан.
- [ ] APK + latest.json (с верным sha256) опубликованы на aruba1.
- [ ]
curl latest.jsonснаружи показывает новую версию. - [ ] Установка self-update на устройстве проходит (sha256 совпал).