Reverse-engineered ParkSmarter API client (TypeScript, live-verified) plus a de-Googled Expo/React Native app for GrapheneOS: MapLibre meter map with GPS, VisionCamera QR kiosk scanning with save/share, local session-expiry reminders, UnifiedPush wiring, and Gitea CI to publish signed APKs for Obtainium. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3.6 KiB
Distribution: self-hosted CI → Obtainium
Goal: push a git tag, have your server build a signed APK, publish it as a release
on git.mowden.top, and have Obtainium on your GrapheneOS phone auto-offer updates.
Repo: ssh://git@git.mowden.top:222/hank/BigBrainParking.git
(web: https://git.mowden.top/hank/BigBrainParking)
1. One-time: create the signing key (do this locally)
The signer is permanent — Obtainium (and F-Droid) pin it, so if you ever rebuild with a different key, users must uninstall + reinstall. Keep this keystore backed up and secret.
keytool -genkeypair -v -keystore bigbrainparking.keystore \
-alias bigbrainparking -keyalg RSA -keysize 2048 -validity 10000
base64 -w0 bigbrainparking.keystore # copy this string for the CI secret
2. One-time: add CI secrets
On git.mowden.top → the repo → Settings → Actions → Secrets, add:
| Secret | Value |
|---|---|
ANDROID_KEYSTORE_B64 |
the base64 string from step 1 |
ANDROID_KEYSTORE_PASSWORD |
keystore password |
ANDROID_KEY_ALIAS |
bigbrainparking |
ANDROID_KEY_PASSWORD |
key password |
3. One-time: an Actions runner that can build Android
You need a Gitea/Forgejo Actions runner registered to this repo/instance. The provided
workflow (.gitea/workflows/build-apk.yml) runs inside a container image that already has
the Android SDK + Node, so the host runner just needs Docker:
# on your server: install act_runner (Gitea) or forgejo-runner (Forgejo), then:
./act_runner register --instance https://git.mowden.top --token <RUNNER_TOKEN>
./act_runner daemon # (or a systemd unit)
Make sure the runner labels include ubuntu-latest (or edit runs-on: in the workflow).
If
git.mowden.topis Forgejo, move the workflow to.forgejo/workflows/build-apk.yml(Forgejo also reads.gitea/workflows, so it usually works as-is).
4. Release flow (every update)
# bump version in app/app.json ("version") first, then:
git tag v0.1.0
git push origin v0.1.0
CI builds app/android/app/build/outputs/apk/release/*.apk, signs it, and attaches it to a
new release v0.1.0. Done.
5. Add the app in Obtainium (on the phone)
Obtainium supports Gitea/Forgejo release sources. Add app → paste:
https://git.mowden.top/hank/BigBrainParking
Pick the Gitea (or Forgejo) source type if prompted, and Obtainium will track releases and offer each new signed APK. Install ntfy + set it as your UnifiedPush distributor for push later.
Fallback if your Obtainium build lacks Gitea support
Serve the APK statically and use Obtainium's "HTML" source:
- CI (or a hook) copies the APK to a web dir, e.g.
/var/www/bbp/BigBrainParking-<version>.apk. - nginx with autoindex on that dir:
location /bbp/ { root /var/www; autoindex on; } - In Obtainium, add an HTML app pointing at
https://<yourserver>/bbp/with an APK link filter likeBigBrainParking-.*\.apkand version extraction from the filename.
This path skips Gitea releases entirely — it's just a directory of signed APKs — but you lose changelogs and per-release metadata.
Notes
- Reproducibility / F-Droid later: if you ever want a real F-Droid repo (signed index,
usable by the F-Droid client too), run
fdroidserveron the server pointed at the same APK output dir. Obtainium consumes F-Droid repos as well. Overkill for one app, but an option. - Version code: Expo derives Android
versionCodefromapp.json. Bumpexpo.version(and optionally setexpo.android.versionCode) each release so Obtainium sees an increase.