Publish Android releases to a self-hosted F-Droid repo

scripts/fdroid-publish.sh builds a signed arm64 APK and adds it to an
F-Droid repo in a given directory, creating the app signing key and the
repo on first use. The versionCode is the commit count, so any commit can
ship without a manual version bump.

Release builds are signed when src-tauri/gen/android/keystore.properties
exists and stay unsigned otherwise. The manifest picks up the deep-link
plugin's intent filter, which every build regenerates and was never
committed.
This commit is contained in:
2026-10-13 21:20:28 -05:00
parent ece21c1acf
commit 3a72780027
5 changed files with 305 additions and 1 deletions

View File

@@ -346,6 +346,55 @@ With the dev session running, Studio's device dropdown, Device Manager
To build without Studio and without a dev server, use `cargo tauri android
build` — that path needs no addr file.
### Distributing to phones (F-Droid)
Releases go out through a small F-Droid repo you host yourself: add it to the
F-Droid app once, and every new build then shows up there as an update.
`scripts/fdroid-publish.sh` builds a signed arm64 APK and adds it to the repo
in a directory you choose. It needs fdroidserver:
```bash
pipx install fdroidserver
```
The first run also makes the app's signing key and the repo. Give it the
address the repo will be served at:
```bash
FDROID_REPO_URL=https://fdroid.example.com/repo ./scripts/fdroid-publish.sh --init-keystore ~/fdroid-mtgc
```
After that, publishing is just:
```bash
./scripts/fdroid-publish.sh ~/fdroid-mtgc # or: npm run android:publish -- ~/fdroid-mtgc
```
It ends by printing the repo address with its fingerprint
(`https://…/repo?fingerprint=…`); add that in F-Droid under **Settings →
Repositories**.
- **Serve only `~/fdroid-mtgc/repo`** (and `archive/`, which holds older
versions, if you like) — any static file server will do. Never serve the
directory itself: it holds the repo signing key (`keystore.p12`) and its
password (`config.yml`).
- **Back up both keys**: `~/.local/share/mtgc/android-release.jks` with
`src-tauri/gen/android/keystore.properties` (the app key and its password),
and the repo directory's `keystore.p12` with `config.yml`. Android only
installs an update signed with the same key as the installed app, so
without the app key every phone would have to uninstall and reinstall.
- **Versions are automatic.** The Android versionCode is the number of commits
on `HEAD`, and the version shown is e.g. `0.1.0-44-gece21c1`, so any commit
can ship without a bump. That's also why pushed history shouldn't be
rewritten. The script won't publish uncommitted changes without
`--allow-dirty`, or a versionCode the repo already has.
- A phone with a debug build, or anything signed with another key, has to
uninstall it before F-Droid can install the release, and uninstalling
deletes the app's data. Sync or **Export library…** first.
Without `keystore.properties`, `cargo tauri android build` still produces an
unsigned APK as before.
### Card data on a phone
Downloading card data streams ~740MB of JSON to build a ~73MB database, which