Skip to content

Fix: release otp.zip poisons subsequent debug native deploys#42

Merged
GenericJam merged 1 commit into
masterfrom
fix/native-deploy-stale-beam-push
Jul 25, 2026
Merged

Fix: release otp.zip poisons subsequent debug native deploys#42
GenericJam merged 1 commit into
masterfrom
fix/native-deploy-stale-beam-push

Conversation

@GenericJam

Copy link
Copy Markdown
Owner

Summary

  • mix mob.deploy --native reports success but can silently leave stale BEAMs on-device. Root cause: mix mob.release --android writes otp.zip into the shared src/main/assets/ Gradle source set, which every build variant merges — including debug. A prior release build leaves this file behind, and MobBridge.kt's extractOtpIfNeeded() re-extracts it on the next app launch after any reinstall (keyed off PackageInfo.lastUpdateTime), silently overwriting freshly-pushed dev BEAMs with the stale release snapshot.
  • otp.zip now goes to the release-variant asset source set (src/release/assets/), which Gradle never merges into debug builds — structurally impossible to recur, not a "remember to clean up" convention.
  • MobDev.NativeBuild.remove_stale_release_otp_zip/1 runs before every debug assembleDebug, deleting a leftover src/main/assets/otp.zip if present, so existing checkouts (built with older mob_dev versions) get healed automatically.

How this was found

Traced on a real Sloppy Joe app deploy: every intermediate step (fresh BEAM staged, tar built correctly, adb push succeeded, run-as tar xf returned clean exit 0 with no stderr) checked out, yet the on-device file stayed stale. Confirmed the bundled debug APK's assets/otp.zip itself contained the stale content (a snapshot from an earlier mix mob.release --android run), and that removing it fixed the very next deploy. Restoring the file reproduced the bug exactly.

Test plan

  • mix test — 2119/2119 passing (4 new tests covering ReleaseAndroid.otp_zip_path/0 and NativeBuild.remove_stale_release_otp_zip/1)
  • mix format --check-formatted clean
  • mix credo --strict clean (0 issues)
  • Verified end-to-end on a physical Moto G Power (non-rooted, run-as push path): ran a real mix mob.release --android with this fix, confirmed otp.zip lands in src/release/assets/ (not src/main/assets/) and is still correctly bundled into the release AAB via Gradle's variant merging, then ran mix mob.deploy --native immediately after (the exact poisoning scenario) and confirmed fresh BEAM content on-device afterward
  • Pre-push hook (format, credo --strict, compile --warnings-as-errors) passed

🤖 Generated with Claude Code

mix mob.deploy --native reported success while silently leaving stale
BEAMs on-device. Root cause: mix mob.release --android wrote otp.zip to
the shared src/main/assets/, which Gradle merges into every build
variant. A prior release build left it there for the next debug build
to inherit too, and MobBridge.kt's extractOtpIfNeeded() re-extracts it
on every reinstall (keyed off PackageInfo.lastUpdateTime), silently
overwriting freshly pushed dev BEAMs with the stale release snapshot.

The zip now goes to the release-variant asset source set
(src/release/assets/), which Gradle never merges into debug builds, so
a release build can no longer poison a later debug deploy structurally.
NativeBuild.remove_stale_release_otp_zip/1 also heals any existing
checkout that still carries the old leftover file.

Verified end-to-end on a physical Moto G Power (non-rooted, run-as
push path): reproduced the staleness by restoring the old file, then
confirmed a real mix mob.release --android + mix mob.deploy --native
round-trip with this fix leaves fresh BEAM content on-device.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@GenericJam
GenericJam merged commit 3f03a63 into master Jul 25, 2026
3 checks passed
@GenericJam
GenericJam deleted the fix/native-deploy-stale-beam-push branch July 25, 2026 05:13
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