Pad/doc/release.md
Greg Pomerantz f31f849665 Make the release process script-driven and documented
The release flow, install policy, and on-device rules previously lived in
session context. Now:

- scripts/release.sh: the executable release — gate 1 static checks,
  gate 2 full go test (incl. TestNoFramesWhileIdle), gate 3 frame-regression
  profile on the emulator, build (SKIP_CHECK=1 avoids double static checks),
  then install to EVERY connected device (emulators and phones; the
  wireless-debugging serial changes per reconnect, the loop sidesteps it).
  Any gate failure aborts before install; dirty tree is warned, not fatal.
- doc/release.md: the process, the install-to-all-devices default, the rule
  that a phone is INSTALL-ONLY during a release (on-device
  profiling/testing is diagnostic and needs explicit approval per run),
  failure-handling table, versioning gap (still gogio default 1.0.0.1), and
  emulator requirements.
- doc/README.md: release.md added to the doc table.
- architecture.md §11: pointer to the release flow.

Validated end-to-end: release.sh ran all three gates (PASS), built the APK,
and installed it on both the phone and the emulator in one command.
2026-08-20 14:54:48 -04:00

3.6 KiB

Release process

A release is ./scripts/release.sh — that one command is the executable form of this document. If this document and the script ever disagree, fix both in the same change.

What a release does

  1. Gate 1 — static checks: scripts/check.sh (go vet + staticcheck).
  2. Gate 2 — test suite: go test -count=1 ./... — includes TestNoFramesWhileIdle (internal/test/e2e), the headless frame-regression guard.
  3. Gate 3 — frame-regression profile, EMULATOR only: scripts/profile_emulator.sh (auto-selects an emulator; it never auto-selects a phone). See architecture.md §11 for what it measures and why the budgets are shaped the way they are.
  4. Build: scripts/build_phone.sh --no-install (arm64+arm APK → cmd/pad/pad-phone.apk; static checks are skipped here, already gate 1).
  5. Install to every connected device — emulators and phones.

Any gate failure aborts before the install. The working tree may be dirty; the script warns, but the gates then certify the current (possibly uncommitted) state — commit the release work before shipping.

Install policy

  • Pushing a release build to the developer's phone is the default and expected behavior — release.sh installs to all adb devices entries, which is what makes the phone just work without knowing its serial (the wireless-debugging IP:port changes on every reconnect; the install loop sidesteps that entirely).
  • On a phone that has never had the app, grant "All files access" (MANAGE_EXTERNAL_STORAGE) in system settings after the first install.

On-device profiling/testing: NOT part of a release

The release touches a phone only to install the APK. It never profiles, tests, force-stops, or otherwise drives a phone:

  • On-device runs (e.g. scripts/profile_emulator.sh -s <phone serial>) are diagnostics: they force-stop the app, seed and remove a file in its storage, and read its profiler output. The developer may be using the phone while a release runs.
  • Therefore an on-device run requires explicit approval in the moment (ask first, name the serial), and its results are informational, never a gate. The frame-regression gate is tier 2 (headless) + tier 3 (emulator) only.

Failure handling

Gate Fails on First things to check
1 static vet/staticcheck findings The findings; don't waive without a reason in the commit message
2 tests any test go test -count=1 -run <Name> ./... to isolate; e2e tests are deterministic — a flake is a bug in the test
3 profile a phase over its frame budget The printed phases + PERF/PERF-PRESENT logcat lines (a spinner is usually obvious); confirm the emulator wasn't under host load (rerun once before investigating)
build gogio/apktool/sign Toolchain notes in scripts/build_phone.sh header

If the profile gate is in question, a diagnostic run on the phone (requires approval) is the escalation path — not a replacement for the gate.

Versioning (known gap)

The APK is currently built with the gogio-default version (1.0.0.1); releases do not bump a version yet. When release distribution starts mattering, add a version step here (and to release.sh) — until then, "which release" is identified by the git commit the APK was built from.

Emulator requirements

Gate 3 needs a running emulator (adb devices shows emulator-*). scripts/emu.sh manages the AVD (see its header); the AVD must have had "All files access" granted once (it has). No phone needs to be connected for a release to succeed — the install step simply reports no devices.