Linear: https://linear.app/engineereddev/issue/ENG-272
What's in this PR (6 files, plus a lead commit):
scripts/release.tsasmise run release <version> [--dry-run]: preflight (onmain, clean,main=origin/mainafter fetch, semver newer than the lastv*tag,mise run check, a printed reminder to confirm Tangled CI); multi-archdocker buildx(linux/amd64,linux/arm64,--build-arg VERSION,:latestexcept for-rc); signedassembleReleasewith-PreleaseVersionName/-PreleaseVersionCode(§16.8: major·10000 + minor·100 + patch);apksigner verify --print-certsmust match the fingerprint indocs/RELEASING.mdbeforedist/release/pneumo-<v>.apk+SHA256SUMSare written; tag, push tag to Tangled, pushmain+ tag to the mirror,gh release create(--prereleasefor-rc). Every login/push sits behind one dry-run boundary.- Secrets: the GHCR token only flows
gh auth token→docker login --password-stdin; keystore passwords come from~/.config/pneumo/release.env(mode 600, validated) into the Gradle child's environment only; Gradle output is captured; errors print only messages. apps/android/app/build.gradle.kts: areleasesigningConfig created only when all fourANDROID_*env vars are present (otherwise unsigned); version name/code from Gradle properties (dev defaults unchanged).mise.toml:releasetask;e2e:dockeracceptsIMAGE=(scripts/e2e/docker.ts).scripts/ci/check.shtype-checksrelease.ts.docs/RELEASING.md: prerequisites, the one-time signing setup, cutting a release, test-only overrides, the backup warning.- Lead commit
233b1a3: the real keystore was created on the owner's Mac with the documented script (passwords never printed); its public certificate SHA-2560E:FF:…:03:E5is recorded indocs/RELEASING.md.
Verify:
- Implementer:
check:infra,check:android,e2e:dockerandIMAGE=pneumo:eng-267 e2e:dockerexit 0;release 0.1.0-rc.1 --dry-runwith a throwaway key in an isolated cleanmaincheckout: exit 0, both arches built, APK signed and matched,SHA256SUMSwritten, 0 publication calls, 0 password leaks; wrong fingerprint → exit 1 with nothing written; unsignedassembleReleasestays unsigned with dev versions; all preflight refusals tested. - Lead (on
1e4f66d):check:infraexit 0,check:androidexit 0. - After merge the lead runs the real
mise run release 0.1.0-rc.1(needs the owner'sgh auth refresh -s write:packages).
🤖 Generated with Claude Code