Skip to content

Latest commit

 

History

History
124 lines (106 loc) · 6.66 KB

File metadata and controls

124 lines (106 loc) · 6.66 KB

Android release checklist

The repository can produce a shrunk release APK, but public distribution still requires publisher-owned signing and store configuration.

Before every release

  1. Select the minimum compatible OwnNode Agent release and run its complete test suite.

  2. Choose the daily versionPatch (0-99). The app derives versionName as yyyy.MM.dd.patch and versionCode as yyyyMMddpp; increment the patch for every additional Play upload on the same day.

  3. Run:

    ./gradlew :app:testDebugUnitTest :app:lintRelease :app:assembleRelease
  4. Test a signed build on the oldest supported Android version and the current Android release. Cover LAN HTTP, Tailscale HTTP, HTTPS, an invalid token, every optional backend capability, process death, reboot, and interrupted media uploads.

  5. Generate an Android App Bundle with a publisher-owned upload key. Store key material in the CI or release environment, never in this repository.

  6. Publish matching backend/API release notes and installation instructions.

GitHub Actions publishing setup

The manually dispatched Publish AAB to Closed Testing workflow builds a signed release bundle and publishes it only to a completed closed-testing release. It defaults to the initial closed-track identifier, alpha. If the active closed track has a different title in Play Console, enter that exact track identifier when dispatching the workflow. Production (production), open testing (beta), and internal testing (qa) identifiers are rejected.

Configure the google-play GitHub Environment, restrict it to the main branch, and add an approval rule. The workflow pins every external action to a complete commit SHA so a mutable action tag cannot change the code used for publishing.

Add these secrets to that environment (or to the repository):

  • ANDROID_SIGNING_KEY_BASE64: the Play upload keystore, Base64-encoded as a single string.
  • ANDROID_SIGNING_STORE_PASSWORD: the upload keystore password.
  • ANDROID_SIGNING_KEY_ALIAS: the upload-key alias.
  • ANDROID_SIGNING_KEY_PASSWORD: the upload-key password.
  • GOOGLE_SERVICES_JSON_BASE64: app/google-services.json, Base64-encoded as a single string.
  • PLAY_SERVICE_ACCOUNT_JSON: the complete Google service-account JSON used by the Google Play Developer API.

Enable the Google Play Android Developer API, invite the service-account email under Play Console > Users and permissions, and grant only the permissions needed to release this app. The application ID com.zen.pistats must already exist in Play Console; the first bundle may need to be uploaded manually.

To publish, open GitHub > Actions > Publish AAB to Closed Testing > Run workflow, confirm the closed-track identifier, and set a unique patch for that date. Only one Play publishing run executes at a time to avoid conflicting Play edits.

Transaction sync

  • Confirm SMS permission is requested only after the user enables transaction capture and that disabling capture remains possible while the Pi or Actual Budget is unavailable.
  • Receive a supported future bank SMS and confirm it enters Needs review.
  • Confirm every newly queued Needs review item posts a privacy-safe notification and tapping it opens that transaction's review dialog directly.
  • Confirm the account selector contains the safe labels configured on the Pi without exposing Actual account IDs.
  • Select the bank account and edit the amount, direction, payee, reference, date, and time; confirm changed field names and an optional note survive process recreation in the encrypted queue.
  • Approve it and confirm it remains Ready until the user taps Sync approved transactions.
  • Tap the sync button, observe the WorkManager job, and confirm Actual Budget receives the corrected values as one uncleared transaction before the app reports Synced. Confirm the correction note is not uploaded.
  • Retry the same event and confirm backend idempotency prevents a duplicate.
  • Force an Actual import failure and confirm the app shows a copyable Diagnostic ID and safe error code. Match that ID in journalctl -u pistats-backend, then verify neither Android logcat nor the Pi journal contains the SMS, sender, amount, payee, account, reference, token, or credentials.
  • Simulate losing the HTTP response after Actual accepts an import. Confirm the immediate idempotent reconciliation request receives the already-imported response, marks the item synced, and does not show client_io_error. If both attempts lose their responses, confirm WorkManager queues a later retry without leaving the button labeled Syncing.
  • Put an immediate media backup into WorkManager backoff, then tap Back up now. Confirm the queued retry is replaced immediately and the button is disabled only while the replacement worker is actively running.
  • Change the backend URL while service discovery is still loading. Confirm the stale request neither restores the service-discovery spinner nor overwrites services from the new backend. Repeat while entering or leaving demo mode.
  • Confirm no newly parsed transaction can bypass user review.

Google Play requirements

  • Host the privacy policy from the backend repository and keep its effective date and behavior accurate.
  • Complete the Data safety form. OwnNode sends telemetry requests and, when the user explicitly enables it, authorized photos/videos and approved normalized transaction fields to the self-hosted server selected by that user. Firebase Analytics and Crashlytics are included for aggregate usage measurement and crash diagnostics; declare their current collection accurately. OwnNode has no advertising SDK.
  • READ_MEDIA_IMAGES and READ_MEDIA_VIDEO require a Photo and Video Permissions declaration. The listing and review video must present automatic private media backup as a core feature. If Google does not approve broad access, ship a Play flavor using only Android Photo Picker-selected media and reserve automatic full-library backup for direct/F-Droid distribution.
  • Provide in-app and store-listing disclosure that media leaves the phone for a user-configured self-hosted server.
  • Use Play App Signing and retain the upload key recovery material securely.

Operational release requirements

  • Never distribute a default bearer token or a preconfigured backend URL.
  • Never expose the backend's plain HTTP listener directly to the public internet. Use a trusted LAN/Tailscale route or an HTTPS reverse proxy.
  • Confirm the Debian package generates a unique token, remains localhost-bound by default, and preserves /etc/pistats/pistats.env during upgrades.
  • Back up signing keys and APT repository signing keys offline.