13 Commits
Author SHA1 Message Date
Linus Rath b3bd19cc8c ci: roll every android release out to the internal and closed testing tracks on google play 2026-10-23 16:48:22 +02:00
Linus Rath 341cdb0e61 feat: build a Google Play bundle alongside the GitHub APK
The app now has two product flavors. `github` is the sideloaded APK as
before, with the same package name and its in-app updater. `play` is a
bundle for Google Play as `org.bulwarkmail.mobile`, without the updater
or the installer permission, since Play forbids apps updating themselves.

- `release-android.yml` builds the Play bundle in a second job, checks
  its signer, package name and permissions, and keeps it as an artifact.
  With `PLAY_SERVICE_ACCOUNT_JSON` set it uploads it to internal testing.
- The Play flavor uses the new Firebase project; the GitHub flavor keeps
  the old one until the app re-registers its token when it changes.
- Widget clicks and the device-sync account type follow the package name.
- Photos come from the system picker without asking for media access,
  and the unused microphone permission from expo-camera is removed.
- A manual workflow run without a tag no longer replaces the APK of the
  latest release.
2026-10-20 12:56:44 +02:00
Linus Rath 5dfe869acb ci: publish a checksum and signed build provenance with the release apk 2026-09-27 15:23:51 +02:00
Linus Rath 4052523ba9 ci: read the apk signer from newer apksigner output in the release check 2026-09-24 22:45:52 +02:00
Linus Rath e30749a50e ci: stop the android release failing on the runner's new sdk tools 2026-09-24 22:31:01 +02:00
Linus Rath e5659ed5e8 ci: attach the r8 mapping to android releases
Release APKs are obfuscated since R8 was turned on, and nothing kept
the mapping that decodes their stack traces. The workflow now copies
`android/app/build/outputs/mapping/release/mapping.txt` to
`bulwark-mobile-<version>-<commit>-mapping.txt`, uploads it as a
workflow artifact and attaches it to the release next to the APK. The
in-app updater only picks `.apk` assets, so it ignores the new file.

If R8 is on (`android.enableMinifyInReleaseBuilds=true`) and no mapping
was written, the step fails instead of publishing an APK whose crashes
cannot be read. docs/android-release.md explains how to decode a trace
with `retrace`.
2026-09-24 22:14:35 +02:00
Linus Rath 6f0abb4384 fix: stop signing release apks with the public debug key
Every published APK up to 0.1.62 was signed with the React Native
template's debug keystore, whose key is public. Anyone could sign an
"update" that Android installs over the app, with access to its
SecureStore credentials and mail cache. The release build type fell
back to the debug signing config whenever no release key was passed,
and the workflow carried on silently when `ANDROID_KEYSTORE_BASE64`
was empty.

- `android/app/build.gradle` reads the release key from the
  `BULWARK_RELEASE_*` gradle properties or environment variables and
  has no fallback. Without them a release build fails in the new
  `checkReleaseSigning` task. It only runs for release variants, so
  debug builds and `expo run:android` are unchanged. A local test
  build can opt in with `-PallowDebugSignedRelease=true`, which is
  ignored whenever `CI` is set.
- The release workflow fails in its first step when a signing secret
  is missing, checks the keystore, alias and password before the
  build, and refuses a debug key uploaded as the release key.
- An optional `ANDROID_SIGNING_LINEAGE_BASE64` secret re-signs the APK
  with APK Signature Scheme v3 key rotation from the debug key to the
  release key, from API 28, so existing installs on Android 9+ can
  update and stop trusting the debug key afterwards.
- Before anything is uploaded, `apksigner verify` has to show the
  release key as the Android 9+ signer, never the debug certificate.
- `*.keystore` and `*.lineage` files are gitignored.

Audit item S2 in `docs/audit-2026-09.md`.
2026-09-24 18:52:15 +02:00
Linus Rath 5ac2a142b5 feat: update Android build configuration to use arm64-v8a architecture and improve caching mechanism 2026-04-26 21:58:08 +02:00
Linus Rath a8a0d475db chore: update readme 2026-04-26 04:57:10 +02:00
Linus Rath 2fa48e8e05 feat: enhance Android release workflow with caching and tag resolution 2026-04-26 04:53:01 +02:00
Linus Rath d5710128fd chore: ensure gradlew is executable before building release APK 2026-04-26 04:19:05 +02:00
Linus Rath ef63d8fa86 feat: update versioning system and remove app.json 2026-04-26 04:15:57 +02:00
Linus Rath 365ffefd33 chore: add Android release CI and sync local work
CI:
- .github/workflows/release-android.yml builds APK on release publish
  and via workflow_dispatch, attaches it to the release.
- android/app/build.gradle: optional release signingConfig driven by
  Gradle properties (ANDROID_KEYSTORE_BASE64 secret etc.); falls back
  to the debug keystore when no secrets are set.
- .gitignore: untrack /android so the runner can build directly;
  ignore build outputs (build/, .cxx/), Metro/Expo dev logs, scratch.

Track android/ sources including BulwarkFcmPackage.kt and
google-services.json (Firebase Android keys are public per Google's
docs and intended to ship in the APK).

JS sync: push notifications + background task, vacation responder
(api + store), contact activity component, search utilities, settings
polish, calendar/contacts/email store and screen tweaks.

Tooling: scripts/poll-reload.mjs — Windows polling-watcher that hits
Metro /reload on file change (workaround for unreliable fs.watch
without Watchman).
2026-04-26 04:12:08 +02:00