Repository navigation
Make local signed release builds possible without leaking passwords - #9
Conversation
Building a personal-profile release locally is the only way to obtain that artifact, and two things made it needlessly hazardous. Without the four signing variables no signingConfig is created and AGP emits `*-release-unsigned.apk`. scripts/build-apk copied that into dist/ under a name giving no hint it could not be installed, and exited 0; the failure surfaced much later as INSTALL_PARSE_FAILED_NO_CERTIFICATES. Verify release output with apksigner and fail with an actionable message. Getting the variables into the container also required --remote-env, placing passwords in the host process list, which docs/releases.md already warns against for keytool. Forward all four from localEnv as devcontainer.json already did for AUTOSPEED_PERSONAL_USE_ACK. Unset variables forward as empty, which is the existing no-signing path, so a clean clone is unaffected. Document the local recipe, including that AUTOSPEED_SIGNING_STORE_FILE is a path inside the container. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 379a93aa-5a91-48d4-af89-3c240ef6d47f
There was a problem hiding this comment.
🟡 Changes recommended
The current apksigner selection logic is lexicographic and can pick the wrong build-tools version when multiple versions are installed.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Enables safer and more reliable local signed release APK builds (including personal-profile variants) by preventing unsigned “successful” release artifacts from being treated as installable and by avoiding passing signing secrets via host argv.
Changes:
scripts/build-apknow verifies release APKs withapksignerand fails with guidance if the output is unsigned.docs/releases.mddocuments a local signed release build workflow that relies on host-exported env vars forwarded into the devcontainer..devcontainer/devcontainer.jsonforwards signing env vars fromlocalEnvinto the container to avoid--remote-envpassword exposure.
File summaries
| File | Description |
|---|---|
| scripts/build-apk | Adds release APK signature verification via apksigner to prevent copying unsigned artifacts into dist/. |
| docs/releases.md | Adds local-release build instructions aligned with the new scripts/build-apk failure mode and devcontainer env forwarding. |
| .devcontainer/devcontainer.json | Forwards signing-related environment variables from the host into the devcontainer. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
scripts/build-apk may non-deterministically verify/copy the wrong APK when both signed and unsigned release artifacts coexist in the output directory.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
scripts/build-apk:59
apkis selected earlier viafind ... -print -quit, which is non-deterministic if multiple APKs exist in the outputs directory (e.g. after switching from an unsigned build to a signed build, both*-release-unsigned.apkand*-release.apkcan coexist). In that case this verification (and the subsequent copy) may target the wrong/stale artifact and incorrectly fail (or copy an unsigned APK despite a signed one being present). Consider re-selecting the release APK here to prefer the signed*-release.apkwhen present before runningapksigner.
- Files reviewed: 3/3 changed files
- Comments generated: 0 new
- Review effort level: Lite
Building a personal-profile release locally is the only way to get that artifact, since the workflow only ever publishes public builds. Two things made it worse than it needed to be.
A successful build could hand you an uninstallable APK
Without the four signing variables,
releaseSigningAvailableis false, nosigningConfigis created, and AGP emitsapp-personal-play-release-unsigned.apk.scripts/build-apkthen copied that todist/autospeed-personalPlay-release.apk-- a name with no hint that it cannot be installed -- and exited 0.Confirmed before fixing:
Installing it fails with
INSTALL_PARSE_FAILED_NO_CERTIFICATES, far from the cause.scripts/build-apknow verifies release output withapksignerand fails with an actionable message instead of copying it.Signing passwords had to go through argv
The only documented way to get the variables into the container was
--remote-env, which puts passwords in the host process list -- the same exposuredocs/releases.mdalready warns about forkeytool.devcontainer.jsonnow forwards all four fromlocalEnv, exactly as it already did forAUTOSPEED_PERSONAL_USE_ACK, so they can be exported in the shell instead. Unset variables forward as empty, which is the existing "no signing config" path, so a clean clone is unaffected.Verification
dist/.debuggableabsent rather thantrue, application IDio.pryce.android.autospeed.personalrather than.personal.debug../scripts/container-run ./scripts/checkpasses.docs/releases.mdgains the local-build recipe the new error message points at, including thatAUTOSPEED_SIGNING_STORE_FILEis a container-side path.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com