Skip to content

MOB-169: mob.deploy freezes explicit targets before doing work - #77

Merged
GenericJam merged 2 commits into
masterfrom
review/MOB-169-deploy-targets
Sep 12, 2026
Merged

GenericJam merged 2 commits into
masterfrom
review/MOB-169-deploy-targets

Conversation

@GenericJam

Copy link
Copy Markdown
Owner

MOB-169 — mix mob.deploy freezes an explicit target set before compile, build, install, or push, so a device appearing during a long native build cannot join the operation and physical phones plugged in for unrelated work are never implicitly targeted.

Adopted this branch from a prior agent's session — they left the work uncommitted, no PR, ticket sitting In Progress with no comment. Rebased onto current master (which now carries the 0.7.1 release), verified the design against the decision record, applied review findings, squashed into one coherent commit.

Design

See decisions/2026-09-11-deploy-freezes-explicit-targets.md. New shared MobDev.TaskTargets module implements the policy:

  • --device <id> — one named device, physical allowed
  • --all-devices — every emulator and simulator
  • --all-physical — every physical device
  • Combined broad flags — every connected device
  • No flag — exactly one emulator or simulator, auto-selected; physical never implicit; multiple dev devices are an error
  • On Android-only runs, non-empty ANDROID_SERIAL is a named target when no CLI scope was supplied; explicit CLI wins

MobDev.Uninstaller delegates through the same selector so device-changing tasks cannot drift.

Behaviour change users will hit

A bare mix mob.deploy with two or more emulators or simulators running for parallel testing used to fan out to both, and now refuses with an ambiguity error demanding an explicit selection (--device <id> or --all-devices). Physical devices also no longer receive an implicit deploy. The CHANGELOG under [Unreleased] names this explicitly.

Adversarial pre-commit review (SOUND WITH FIXES)

Two real issues, both fixed with revert-verified tests:

  • F1 blocker: ANDROID_SERIAL hijacked mixed-platform default runs. On macOS mix mob.deploy runs on [:android, :ios], and a stale ANDROID_SERIAL from another tool would turn a bare deploy into --device xyz, raising :no_matching_devices against any connected iOS simulator. Fixed by narrowing the ANDROID_SERIAL rule to Android-only runs (matches the decision record's exact wording) and adding a String.trim/1 so a whitespace-only value is treated as unset. Two new tests, both flip on revert.
  • F2 should-fix: CHANGELOG didn't name the multi-emulator break as a behaviour change. Added the paragraph.
  • Also caught while adopting: the prior agent had added the MOB-169 CHANGELOG entry inside the [0.7.0] block, which shipped to Hex last week without any of this work. Moved to a fresh [Unreleased] block at the top.

Gates

  • mix test: 2447 pass, 0 fail (2 new tests)
  • mix credo --strict: 0 issues (3750 mods/funs)
  • mix format --check-formatted: clean
  • mix compile --warnings-as-errors --force: clean
  • mix mob.security_scan: 0 findings across 57 hex deps + 4 bundled OTP tarballs

Not device-verified

mob_dev is host-side tooling — no device to verify against. Ready for release when a next mob_dev version warrants one.

Closes MOB-169.

GenericJam and others added 2 commits September 11, 2026 17:53
Discovery used to fan out to every reachable device during
compatibility checks, native installs, and the final BEAM push
independently. A bare `mix mob.deploy --native` installed on every
Android device from `adb devices` and tried every connected iPhone,
ignoring ANDROID_SERIAL. The set could change during a long native
build, so even reading the initial output did not define which
devices the command would later modify — a phone plugged in for
unrelated work would receive the deploy.

The task now discovers once and resolves an immutable target list
before compile / build / install / push begins. Every downstream
stage consumes that list. See
`decisions/2026-09-11-deploy-freezes-explicit-targets.md`.

New shared `MobDev.TaskTargets` policy:

- `--device <id>` selects one named device, including a physical
  device.
- `--all-devices` selects every emulator and simulator.
- `--all-physical` selects every physical device.
- Combined broad flags select every connected device.
- No flag = exactly one emulator or simulator, auto-selected.
  Physical devices are never implicit; multiple development devices
  are an error demanding an explicit selection.
- On Android-only runs, a non-empty `ANDROID_SERIAL` is a named
  target when no CLI scope was supplied. Explicit CLI wins.

`MobDev.Uninstaller` delegates through the same selector so device-
changing tasks cannot drift.

## Reviews before commit

Adopted this branch from a prior agent's session (they left the
work uncommitted, no PR, ticket sitting In Progress with no
comment). Rebased onto current master (which now carries the
0.7.1 release), verified the design against the decision record,
ran gates:

- 2447 mix tests pass (2 new, added while addressing review
  findings). Every changed test flips when the corresponding fix
  is reverted.
- `mix format --check-formatted`, `mix credo --strict`,
  `mix compile --warnings-as-errors --force`,
  `mix mob.security_scan` all clean.

Adversarial subagent review of the ~1000-line diff (verdict SOUND
WITH FIXES) caught:

- **F1 blocker**: `ANDROID_SERIAL` hijacked mixed-platform default
  runs. On macOS `mix mob.deploy` runs on [:android, :ios], and a
  stale ANDROID_SERIAL from another tool would turn a bare deploy
  into `--device xyz` and raise :no_matching_devices against any
  connected iOS simulator. Fixed by narrowing the ANDROID_SERIAL
  rule to Android-only runs (matches the decision record's exact
  wording), plus a `String.trim/1` so a whitespace-only value is
  treated as unset. Two revert-verified tests added.
- **F2 should-fix**: CHANGELOG did not name the multi-emulator
  break as a behaviour change. Added a paragraph.
- **Also caught by me**: the prior agent had added the MOB-169
  CHANGELOG entry inside the [0.7.0] block, which shipped to Hex
  a week ago without any of this work. Moved to a fresh
  [Unreleased] block at the top.

Not device-verified (mob_dev is host-side tooling, no device to
verify against). Ready for release when a next mob_dev version
warrants one.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- CHANGELOG: name the actual iOS refactor (extracted
  finalize_ios_override_result/2 so :skipped can no longer inherit the
  incomplete-override wording) instead of implying a mid-copy fix that
  the diff does not make.
- TaskTargets moduledoc: spell out that combining --all-devices and
  --all-physical selects every connected device, and that multiple
  development devices with no scope flag is an ambiguity error.

Behaviour unchanged; docs only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@GenericJam
GenericJam merged commit 52b0a72 into master Sep 12, 2026
3 checks passed
@GenericJam
GenericJam deleted the review/MOB-169-deploy-targets branch September 12, 2026 00:03
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