Skip to content

feat(flutter): make the Android receiver releasable - #2

Merged
TerrorSquad merged 3 commits into
mainfrom
feat/android-release-signing
Aug 10, 2026
Merged

TerrorSquad merged 3 commits into
mainfrom
feat/android-release-signing

Conversation

@TerrorSquad

Copy link
Copy Markdown
Owner

Porter had no path to a build a stranger could install. This adds one for Android, plus the missing LICENSE and a release pipeline for the sender.

What's here

docs: add the MIT LICENSE file — the repo had none, which technically left the code unusable by anyone else. MIT, matching gstack and forge.

feat(flutter): make the Android receiver releasable — Flutter's template signs release builds with the debug keystore. That keystore is generated per machine and expires after a year, and Android refuses an update signed with a different key, so a published APK would have stranded everyone who installed it.

Release signing is now opt-in through a gitignored android/key.properties. When it is absent — fresh clone, or CI — the build falls back to the debug keystore as before, so flutter build apk --release still works for anyone building for themselves. Adds mise run flutter-apk / flutter-apk-split and docs/RELEASING-ANDROID.md.

ci: build sender binaries on release and publish the Homebrew formula — the README calls the sender "a single static binary" but shipped none. On a published release this cross-compiles for macOS and Linux (arm64 + x86_64), attaches the tarballs, and regenerates the formula in homebrew-tap with real checksums. Mirrors what goreleaser does for forge.

Verified

APKs build: arm64 25.2 MB · armeabi-v7a 21.0 MB · x86_64 27.7 MB · universal 68.6 MB. apksigner confirms the fallback still yields CN=Android Debug, as documented. flutter analyze clean.

Before cutting a release

  • Add the HOMEBREW_TAP_GITHUB_TOKEN secret to this repo — GITHUB_TOKEN cannot write to another repository
  • Reconcile the version: version.txt says 2.8.0, rust-sender/Cargo.toml says 0.1.0, and there has never been a release
  • Generate the release keystore (see docs/RELEASING-ANDROID.md)

Notes

Two pre-existing local issues surfaced while verifying, neither caused by this branch (debug builds failed identically before it) and neither committed, since both are machine-specific:

  • flutter build apk fails with a bare 25.0.2 — that is the JDK, not an NDK version. Android Studio's bundled Java 25 is unparseable by Gradle 8.12. Fix: flutter config --jdk-dir="$(/usr/libexec/java_home -v 17)". Documented in RELEASING-ANDROID.md.
  • android/local.properties pointed at a stale second Flutter SDK.

Also worth knowing: porter-sender has no --version or --help flag, and --version exits 1. That is why the Homebrew smoke test drives join instead — verified working locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LAsieST4zZGygM4WwsEuSH

TerrorSquad and others added 3 commits August 10, 2026 12:11
Every other repo in the org carries one; this one never did. Without it
the code is technically unlicensed, so nobody can legally use it — worth
fixing before the repo gets any attention.

MIT, matching gstack and forge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAsieST4zZGygM4WwsEuSH
The receiver had no publishable build path: Flutter's template signs
release builds with the debug keystore, which is generated per machine
and expires after a year. Android refuses an update signed with a
different key, so an APK published that way would strand everyone who
installed it.

Release signing is now opt-in through a gitignored android/key.properties.
When it is absent — a fresh clone, or CI — the build falls back to the
debug keystore as before, so `flutter build apk --release` still works
for anyone building for themselves. Only a published APK needs the key.

Adds `mise run flutter-apk` (universal) and `flutter-apk-split` (per-ABI,
roughly a third the size each), and docs/RELEASING-ANDROID.md covering
keystore setup, verifying which key actually signed an APK, and the
Gatekeeper-equivalent wording for the release notes.

This makes Android the receiver a stranger can install without any Apple
Developer relationship — macOS notarization stays a separate concern.

Verified: arm64 25.2 MB, armeabi-v7a 21.0 MB, x86_64 27.7 MB, universal
68.6 MB. apksigner confirms the fallback path still yields CN=Android
Debug, as documented.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAsieST4zZGygM4WwsEuSH
The README calls the sender "a single static binary", but the repo shipped
none — the only install path was `cargo build --release`, which needs a Rust
toolchain on the very machine most likely to be locked down.

On a published release this cross-compiles porter-sender for macOS
(arm64/x86_64) and Linux (arm64/x86_64), attaches the tarballs, then
regenerates Formula/porter-sender.rb in TerrorSquad/homebrew-tap with the
real checksums. Mirrors what goreleaser already does for forge, hand-rolled
because goreleaser is Go-only.

The formula's test drives `join` rather than `--version`: the sender is a
ratatui TUI that panics without a real terminal, and there is no --version
flag (it exits 1). `join` is plain file I/O, so it works in Homebrew's
sandbox.

Requires the HOMEBREW_TAP_GITHUB_TOKEN secret on this repo — GITHUB_TOKEN
cannot write to another repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAsieST4zZGygM4WwsEuSH
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying porter with  Cloudflare Pages  Cloudflare Pages

Latest commit: 21a4140
Status: ✅  Deploy successful!
Preview URL: https://1a372c9c.porter-3xy.pages.dev
Branch Preview URL: https://feat-android-release-signing.porter-3xy.pages.dev

View logs

@TerrorSquad
TerrorSquad merged commit a1dece1 into main Aug 10, 2026
3 checks passed
@TerrorSquad
TerrorSquad deleted the feat/android-release-signing branch August 10, 2026 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant