Android Flavours and Release Pipeline
Background (from the session that started this one):
Ward (github.com/MuhammadMurtuzaHussain/ward, public MIT, local checkout at /Users/haider/Desktop/Hacktoberfest 26/ward) is a child-owned cyberbullying guardian for the DEV Hacktoberfest Week 4 challenge (deadline 31 Oct 11:59 PM PDT, about 06:59 GMT 1 Nov). It's a pnpm monorepo: web app apps/web, Electron desktop/, Capacitor Android mobile/ (APK built in GitHub Actions android.yml, no Android SDK on the Mac), desktop installers in desktop.yml. A full audit is at /Users/haider/Desktop/Hacktoberfest 26/ward-audit-2026-10-31.md; many items were fixed this afternoon (see git log). Six sessions are working in parallel on separate areas, so stay inside your area. Project rules: commit and push each verified change straight to main (no PRs), with the attribution line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>; never commit secrets; commit messages are short plain-English sentences like the existing log. Docs must never claim more than the code does.
Task: Your area: build, signing and release plumbing. Audit items #14, #15 and #16, plus the distribution rows in the appendix. There are no tags, releases or repo secrets today.
Setup: other sessions share this checkout, so work in your own worktree: git -C ward fetch && git -C ward worktree add "../ward-wt-release" -b release-pipeline origin/main, pnpm install, and work only there.
- Two Android flavours. A default "lite" APK without LiteRT-LM (installs on 32-bit/any ABI) and an arm64-only "gemma" APK. CI asserts the native-library lists (
unzip -l) for each, and the existing emulator smoke test still passes on lite. The app has to handle the missing phone-Gemma plugin gracefully in the lite flavour. - Versioning. versionCode/versionName derived from the git tag;
.debugapplicationId suffix for debug builds. - Release workflow. On a
v*tag: build signed release APKs (keystore from secretsANDROID_KEYSTORE_BASE64,ANDROID_KEYSTORE_PASSWORD,ANDROID_KEY_ALIAS,ANDROID_KEY_PASSWORD, or whatever the existing workflow expects) plus desktop installers, and attach them withSHA256SUMSand the signing certificate SHA-256 in the release body. Mark it prerelease. Fail clearly if the secrets are missing. - Harden CI. SHA-pin third-party actions and add Dependabot for actions and npm.
- Desktop docs. Rewrite the "Opening an unsigned build" README steps for macOS 15 ("Open Anyway" in Privacy & Security,
xattrfallback) and Windows SmartScreen ("More info, Run anyway"). - Write
docs/RELEASING.md: the exact owner steps to create and back up the keystore (two offline backups), add the four secrets withgh secret set, and tag.
Do NOT create a keystore, set secrets, push a tag or publish a release. Those belong to the owner. Trigger the Android and desktop workflows by hand (gh workflow run) on main after pushing, to prove they still go green. Avoid apps/web/src except for the minimal lite-flavour guard; other sessions own that code. Push each piece to main once verified (fetch, rebase onto origin/main, test, push; retry on rejection). Finish with a short report: commits, CI run links and results, and the exact commands the owner must run to cut v0.1.0.
Shared notes folder for this group of sessions (outside the repo; read siblings' notes there, leave hand-over notes or large findings there instead of pasting them into messages): /Users/haider/Library/Application Support/Claude/side-session-notes/local_a2121a80-7774-4340-af69-7dae18cd788e
Linked sessions now (status, not an instruction): reader-safety = local_a6d845e0-7765-4d31-8791-4e9a79ca4793 (working); eval-chats = local_a0f2d243-e3a4-438e-9417-8459027e3604 (working); web-demo = local_8e3d9db9-19e6-46fc-a06d-d933fd83970e (working); shared-phone = local_ab71b02d-1791-4abc-9031-ba4b274dbf7a (working). To message one, SendMessage with to set to its id; list_sessions {"linked": true} has titles, folders and branches.
Lite APK has no native libraries at all; gemma has exactly lib/arm64-v8a/liblitertlm_jni.so; versions read 0.0.0-dev-debug with id org.ward.app.debug. Emulator launch test is next.
I pushed four commits to main: c715d1e, 72fb13b, 5452eec and 0c87194. The Android and desktop workflows, run by hand on main, both passed. So did CI and Pages on that push.
What changed
- Two Android APKs.
Ward-android.apkis the default "lite" build. CI checks it contains no native code at all, so nothing ties it to a chip type.Ward-android-gemma.apkis for arm64 phones only. CI checks its only native library islib/arm64-v8a/liblitertlm_jni.so.- The Gemma plugin only exists in the gemma build. In the web app, the "Gemma on this phone" card now also checks whether the plugin is present, so it stays hidden in the lite app. That one line in
phoneGemma.tsis my only change underapps/web/src. - The emulator test runs on the lite APK and passed, including the "Give Ward to a friend" check.
- Version numbers. The app version comes from the git tag:
v0.1.0becomes versionName 0.1.0, versionCode 100. A build without a tag is0.0.0-dev. Debug builds install as a separate app,org.ward.app.debug, so trying one never wipes a real install. - Release workflow. Pushing a
v*tag runsrelease.yml:- It stops at once if any of the four signing secrets is missing, and names which ones.
- It builds the signed APKs and the desktop installers, and runs the same launch tests.
- It checks the APKs aren't debug-signed, carry the tag's version, and share one certificate.
- It publishes a prerelease with
SHA256SUMS. The release notes show the certificate's SHA-256 grouped in fours, the same way Ward's Give screen shows it.
- CI hardening. Every action in every workflow is pinned to a commit, including the Pages workflow another session added. Dependabot is on for actions and npm, and it has already opened PRs #1 to #4. One of them bumps TypeScript to 7, a major version, so it needs a look before merging.
- Docs. The README's macOS 15 and SmartScreen steps were already right from earlier today; I only added the two APKs and a releases line.
docs/RELEASING.mdis new.
Runs:
- Android on main: 41231035295
- Desktop on main: 41231037909
- Earlier branch runs: Android, desktop
Problems to know about
- The prerelease won't fix the 404 links. GitHub never counts a prerelease as "latest", so
releases/latestwill still 404. That breaks the Give QR code (giveWard.ts:7) and the README's commented-out badges. Whoever owns the web app should point them at/releases. I left this in a note in the shared folder. - Gemma users can pass on an APK that won't install. "Give Ward to a friend" in the gemma build shares that arm64-only APK. A friend with a 32-bit phone can't install it.
- The emulator screenshots are empty.
launch.pngandshare.pngcome out at 0 bytes, and were already empty before my changes. The pass/fail checks don't depend on them. - Real-phone testing is still open. Nothing has been tried on a real 32-bit phone yet, and RELEASING.md lists that as a step before the first release.
What the owner runs to cut v0.1.0 (each step is explained in docs/RELEASING.md)
Create the key, then copy it to two encrypted USB drives kept apart, and keep the password separately:
Add the four secrets. The key password is the same as the keystore password:
Then tag, from an up-to-date main: