--- name: publish description: "APK publizieren: Version bumpen, APK bauen, auf VPS hochladen, Server-Version aktualisieren, QR-Code/Download-Seite verifizieren. Verwende diesen Skill immer wenn eine neue App-Version veröffentlicht werden soll – auch wenn der User nur 'publish', 'release', 'veröffentlichen', 'neue Version', 'APK hochladen', 'APK deployen', 'Update bereitstellen' oder 'QR-Code aktualisieren' sagt. Trigger-Phrasen: 'publish', 'release', 'veröffentlichen', 'APK hochladen', 'neue Version', 'Update ausrollen', 'QR-Code'." --- # Skill: Publish (APK auf VPS veröffentlichen) Dieser Skill deckt den vollständigen Workflow ab, um eine neue App-Version auf dem VPS bereitzustellen, sodass: 1. Die **Homepage** (QR-Code + Download-Link) die aktuelle APK anbietet 2. Die **Update-Prüfung in der App** die neue Version erkennt und zum Download anbietet --- ## Architektur-Überblick ``` App (lokal) VPS (bollwerk.online) ───────────── ───────────────────── app/build.gradle.kts /opt/bollwerk/ versionCode / versionName ├── docker-compose.yml (BOLLWERK_APP_VERSION_CODE/NAME) ├── data/app-latest.apk (statisch ausgeliefert) ./gradlew assembleDebug └── Server-Container (Ktor) → app-debug.apk ├── GET / → Homepage mit QR-Code ├── GET /api/version → JSON {versionCode, versionName, apkUrl} scp → /opt/bollwerk/data/ └── GET /static/* → Dateien aus data/ ``` ### Wie die Update-Prüfung funktioniert 1. App ruft `GET {serverUrl}/api/version` auf → erhält `VersionInfo(versionCode, versionName, apkUrl)` 2. `CheckForUpdateUseCase` vergleicht `versionInfo.versionCode > BuildConfig.VERSION_CODE` 3. Falls neuer → zeigt Download-Button, lädt APK herunter, installiert via `ApkInstaller` ### Wie die Version gesetzt wird - `POST /api/admin/version` mit `Authorization: Bearer ` Header - Server speichert `versionCode` + `versionName` persistent in `data/version.json` - `GET /api/version` liest aus `VersionStore` (Fallback auf Env-Vars, falls Datei fehlt) - **Kein Container-Neustart nötig!** ### Wie die Homepage funktioniert - `GET /` liefert HTML mit QR-Code (via qrcodejs) + Download-Link auf `/static/app-latest.apk` - Version wird aus `VersionStore` gelesen (persistent in `data/version.json`) --- ## Publish-Workflow (Schritte) ### Schritt 1 – Version bumpen In `app/build.gradle.kts`: - `versionCode` um 1 erhöhen - `versionName` **immer strikt im Format `x.y.z`** führen (z.B. `1.7.13`) - Das dritte Segment (`z`) muss dem `versionCode` entsprechen ### Schritt 2 – Build & Test ```powershell .\gradlew.bat assembleDebug test ``` Die APK liegt danach unter: `app/build/outputs/apk/debug/app-debug.apk` ### Schritt 3 – APK auf VPS hochladen ```powershell scp app/build/outputs/apk/debug/app-debug.apk root@195.246.231.210:/opt/bollwerk/data/app-latest.apk ``` **Voraussetzung:** SSH-Agent muss laufen und Key geladen sein (siehe vps-deploy Skill). ### Schritt 4 – Server über neue Version benachrichtigen Die Version wird per API-Call gesetzt (kein Container-Neustart nötig): ```powershell $body = @{ versionCode = $CODE; versionName = $NAME } | ConvertTo-Json -Compress Invoke-WebRequest -Uri "https://bollwerk.online/api/admin/version" ` -Method POST ` -Headers @{ "Authorization" = "Bearer $env:BOLLWERK_ADMIN_TOKEN"; "Content-Type" = "application/json" } ` -Body $body ` -UseBasicParsing ``` Alternativ mit curl: ```bash curl -s -X POST https://bollwerk.online/api/admin/version \ -H "Authorization: Bearer $BOLLWERK_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"versionCode\": $CODE, \"versionName\": \"$NAME\"}" ``` **Voraussetzung:** Die Umgebungsvariable `BOLLWERK_ADMIN_TOKEN` muss gesetzt sein. Das Token muss mit dem `BOLLWERK_ADMIN_TOKEN` auf dem VPS übereinstimmen. ### Schritt 5 – Verifizieren ```powershell # Version-API prüfen Invoke-WebRequest -Uri "https://bollwerk.online/api/version" -UseBasicParsing | Select-Object -ExpandProperty Content # Homepage prüfen (QR-Code-Seite) Invoke-WebRequest -Uri "https://bollwerk.online/" -UseBasicParsing | Select-Object StatusCode, StatusDescription ``` --- ## Automatisiertes Skript Das Skript `publish-apk.py` in diesem Skill-Ordner automatisiert den **gesamten** Release-Workflow (Version bumpen, bauen, hochladen, API-Call, verifizieren, committen): ```powershell # Alles automatisch (versionCode +1, versionName wird auf x.y. gesetzt): python ".github/skills/publish/publish-apk.py" # Mit neuem versionName: python ".github/skills/publish/publish-apk.py" --version-name "2.0.42" # Nur hochladen (APK bereits gebaut, kein Push): python ".github/skills/publish/publish-apk.py" --skip-build --skip-push ``` **Voraussetzungen:** - SSH-Agent muss laufen (für APK-Upload per SCP) - `$env:BOLLWERK_ADMIN_TOKEN` muss gesetzt sein (für Version-Notify API-Call) **Parameter:** | Parameter | Pflicht | Default | Beschreibung | | ---------------- | ------- | ----------- | ------------------------------------------------- | | `--version-name` | nein | aus current major.minor + code | Neuer versionName im Format `x.y.z` (z.B. "2.0.42") | | `--version-code` | nein | aktuell + 1 | Expliziter versionCode; sonst automatisch +1 | | `--apk-path` | nein | debug-APK | Pfad zur APK-Datei | | `--skip-build` | nein | false | Gradle-Build überspringen | | `--skip-verify` | nein | false | Verifizierung nach dem Deploy überspringen | | `--skip-push` | nein | false | Git-Push überspringen (nur lokaler Commit) | --- ## Wichtige Dateien | Datei | Beschreibung | | -------------------------------------------------------- | ------------------------------------------ | | `app/build.gradle.kts` (L18-19) | `versionCode` / `versionName` | | `server/src/main/resources/application.conf` | Server-Version-Defaults + Env-Var-Override | | `server/src/main/kotlin/.../store/VersionStore.kt` | Persistente Version in `data/version.json` | | `server/src/main/kotlin/.../routes/VersionRoutes.kt` | Homepage + `/api/version` + POST-Endpoint | | `server/src/main/kotlin/.../plugins/Routing.kt` | `staticFiles("/static", File("data"))` | | `app/src/main/java/.../usecase/CheckForUpdateUseCase.kt` | Update-Prüfung in der App | | `app/src/main/java/.../ui/update/UpdateViewModel.kt` | Update-UI + Download-Logik | --- ## Environment-Variablen (VPS) | Variable | Pflicht | Beschreibung | | --------------------------- | ------- | ------------------------------------------------------------ | | `BOLLWERK_ADMIN_TOKEN` | ja | Bearer-Token für `POST /api/admin/version` (min. 32 Zeichen) | | `BOLLWERK_APP_VERSION_CODE` | nein | Fallback-VersionCode (nur wenn `data/version.json` fehlt) | | `BOLLWERK_APP_VERSION_NAME` | nein | Fallback-VersionName (nur wenn `data/version.json` fehlt) | --- ## Bekannte Lücken / TODOs - **Kein Release-Build:** Aktuell wird `assembleDebug` verwendet. Für Produktion → Signing-Config + `assembleRelease` einrichten. - **Env-Vars optional:** `BOLLWERK_APP_VERSION_CODE` / `BOLLWERK_APP_VERSION_NAME` können aus der docker-compose.yml entfernt werden, sobald `data/version.json` initial gesetzt ist.