Support iOS-only development on a Mac (don't crash when adb is absent)#29
Merged
Conversation
`mix mob.connect` (and any tunnel path) crashed with `:enoent` for a
Mac set up only for iOS: the dist-port collision check shelled out to
`adb forward --list`, and `System.cmd("adb", ...)` *raises* for a missing
binary rather than returning a non-zero exit. The raise happened inside a
linked `Task.async`, so the exit propagated and killed the whole connect.
Two parts:
1. Bug fix — `MobDev.Tunnel.run_adb/1` resolves `adb` via
`System.find_executable/1` first (mirroring `Discovery.Android.list_devices/0`)
and returns `{:error, "adb not found on PATH"}` when absent. Every caller
already handles `{:error, _}`, so the port scan / cleanup degrade to "no
adb forwards" instead of crashing. iOS-only Macs now work with no adb at all.
2. Explicit iOS-only mode — `mix mob.connect --ios-only` / `--android-only`
restrict discovery to one platform, and a `mob.exs` default
(`config :mob_dev, platforms: [:ios]`) makes it project-wide so a Mac-only
iOS dev sets it once. Skipping the Android scan also avoids sweeping in a
phone plugged in for some other project.
New pure kernels with tests: `MobDev.Config.parse_platforms/1`,
`Mix.Tasks.Mob.Connect.resolve_platforms/2`, plus a regression test that
`Tunnel.ports_in_use/1` degrades to a MapSet when adb is off PATH.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GenericJam
added a commit
that referenced
this pull request
Jun 29, 2026
…s absent) mix mob.connect no longer crashes with :enoent when adb isn't installed (Tunnel.run_adb guards on System.find_executable). Adds --ios-only / --android-only and a `config :mob_dev, platforms: [:ios]` default. (#29) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a Mac set up only for iOS (no Android platform-tools),
mix mob.connectcrashes:The dist-port collision check (
Tunnel.ports_in_use/1→forward_host_ports/0) shells out toadb forward --list.System.cmd("adb", ...)raises:enoentfor a missing binary rather than returning a non-zero exit, and because it runs inside a linkedTask.async, the crash propagates an exit that kills the whole connect. The existing{:error, _} -> MapSet.new()fallback never gets a chance to run.iOS-only on a Mac is fully supported (the simulator shares the Mac's network stack — no tunnels needed); adb should simply never be required.
Fix
1. Robustness (the actual bug).
Tunnel.run_adb/1now resolvesadbviaSystem.find_executable/1first — the same guardDiscovery.Android.list_devices/0already uses — and returns{:error, "adb not found on PATH"}when it's absent. Every caller already handles{:error, _}, so the port scan and forward cleanup degrade to "no adb forwards" instead of crashing. iOS-only Macs now work with no adb installed at all.2. Explicit iOS-only mode (requested ergonomic). Even when adb is present, you can scope a session:
mix mob.connect --ios-only/--android-onlymob.exsso a Mac-only iOS dev sets it once:Tests (pure kernels + regression)
MobDev.Config.parse_platforms/1— nil/valid/filtered/invalid/non-list matrixMix.Tasks.Mob.Connect.resolve_platforms/2— flag precedence + both-flags errorMobDev.TunnelAdbMissingTest— withadboff PATH,ports_in_use/1returns aMapSetinstead of crashing (locks the regression)31 targeted tests pass. Pre-existing unrelated failures (HotPush/enable/adopt/tflite/ndk — environmental) were confirmed failing on the base before this change too.
🤖 Generated with Claude Code