Automated signed release builds + Obtainium support #3

Open
opened 2026-10-02 10:58:15 +02:00 by lukas · 1 comment
Owner

Goal

Stop building the APK by hand. Every version tag should automatically produce a signed release APK, and the releases should be consumable by Obtainium so the app updates itself on-device.

Proposal

  • Gitea Actions workflow triggered on version tags (e.g. v1.0.0):
    1. npm install → npm test → npm run build
    2. npx cap sync android → ./gradlew assembleRelease (JDK 21, API 36 — see AGENTS.md)
    3. Sign with the release keystore (key + passwords via Actions secrets, never in repo)
    4. Attach app-release.apk to the Gitea release, named stably (e.g. mindlist-v1.0.0.apk)
  • Keep the artifact URL pattern stable so an Obtainium "HTML / direct APK" source keeps working across versions.

Constraints

  • Debug builds must never be published as releases (anticipated confusion with the launcher-icon issue: release vs debug signing).
  • The release keystore stays out of git (see AGENTS.md hard rule #3); CI gets it via secrets only.

Acceptance

  • Pushing a v* tag yields a Gitea release with a signed, installable APK attached — no manual steps
  • The APK installs over the previous release (same signature) on the test Pixel
  • Obtainium can track the repo and offers the new version as an update
## Goal Stop building the APK by hand. Every version tag should automatically produce a signed release APK, and the releases should be consumable by [Obtainium](https://obtainium.imranr.dev/) so the app updates itself on-device. ## Proposal - Gitea Actions workflow triggered on version tags (e.g. `v1.0.0`): 1. `npm install` → `npm test` → `npm run build` 2. `npx cap sync android` → `./gradlew assembleRelease` (JDK 21, API 36 — see AGENTS.md) 3. Sign with the release keystore (key + passwords via Actions secrets, never in repo) 4. Attach `app-release.apk` to the Gitea release, named stably (e.g. `mindlist-v1.0.0.apk`) - Keep the artifact URL pattern stable so an Obtainium "HTML / direct APK" source keeps working across versions. ## Constraints - Debug builds must never be published as releases (anticipated confusion with the launcher-icon issue: release vs debug signing). - The release keystore stays out of git (see AGENTS.md hard rule #3); CI gets it via secrets only. ## Acceptance - [ ] Pushing a `v*` tag yields a Gitea release with a signed, installable APK attached — no manual steps - [ ] The APK installs over the previous release (same signature) on the test Pixel - [ ] Obtainium can track the repo and offers the new version as an update
lukas changed title from create release with automatic Build and support for obtainium to Automated signed release builds + Obtainium support 2026-10-02 11:35:23 +02:00
lukas added the enhancementrelease labels 2026-10-02 11:35:58 +02:00
Author
Owner

Verified end-to-end ✅

  • v* tag → Gitea Actions builds (npm test → PWA → cap sync → assembleRelease, JDK 21, API 36), signs with the release key, verifies via apksigner + fingerprint pin, and attaches mindlist-<tag>.apk (+ .sha256) to the release. Proven live: test tag produced a signed 3.5 MB APK on a release (cleaned up afterwards), plus green dry-runs.
  • Secrets in place: KEYSTORE_PASSPHRASE, RELEASE_STORE_PASSWORD, RELEASE_KEY_ALIAS, RELEASE_KEY_PASSWORD (keystore itself travels AES-encrypted in git).
  • Remaining manual step: in Obtainium, Add App → Gitea → repo URL (+ access token while the repo is private).

Follow-ups if ever needed: versionCode must be bumped in android/app/build.gradle before each release tag (CI enforces this and fails loudly otherwise).

Verified end-to-end ✅ - `v*` tag → Gitea Actions builds (`npm test` → PWA → `cap sync` → `assembleRelease`, JDK 21, API 36), signs with the release key, verifies via `apksigner` + fingerprint pin, and attaches `mindlist-<tag>.apk` (+ `.sha256`) to the release. Proven live: test tag produced a signed 3.5 MB APK on a release (cleaned up afterwards), plus green dry-runs. - Secrets in place: `KEYSTORE_PASSPHRASE`, `RELEASE_STORE_PASSWORD`, `RELEASE_KEY_ALIAS`, `RELEASE_KEY_PASSWORD` (keystore itself travels AES-encrypted in git). - Remaining manual step: in Obtainium, Add App → Gitea → repo URL (+ access token while the repo is private). Follow-ups if ever needed: `versionCode` must be bumped in `android/app/build.gradle` before each release tag (CI enforces this and fails loudly otherwise).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: lukas/mindlist#3