Skip to content

Releases: GenericJam/mob_dev

0.6.17

Choose a tag to compare

@github-actions github-actions released this 29 Jun 20:12

Fixed

  • mix mob.connect crashed on a Mac set up only for iOS. The dist-port
    collision check shelled out to adb forward --list, and System.cmd("adb", …)
    raises :enoent for a missing binary rather than returning a non-zero exit —
    inside a linked Task, so the crash propagated and killed the whole connect.
    MobDev.Tunnel.run_adb/1 now resolves adb via System.find_executable/1
    first (mirroring Discovery.Android.list_devices/0) and returns {:error, …}
    when it's absent, so the port scan degrades to "no forwards" and iOS-only
    Macs work with no Android platform-tools installed. (#29)

Added

  • mix mob.connect --ios-only / --android-only restrict discovery to one
    platform — handy when a phone for another project is plugged in. Set it
    project-wide in mob.exs with config :mob_dev, platforms: [:ios]. New pure
    helpers MobDev.Config.parse_platforms/1 and
    Mix.Tasks.Mob.Connect.resolve_platforms/2. (#29)

0.6.16

Choose a tag to compare

@github-actions github-actions released this 24 Jun 22:18

Added

  • Plugins can contribute array-valued iOS plist keys (e.g.
    UIBackgroundModes). apply_plugin_plist_keys! previously skipped any
    non-scalar ios.plist_keys value as unsupported; a list value now merges
    into the host Info.plist array (creating it if absent, appending only the
    missing string entries, deduped) instead of clobbering it. So one plugin can
    add bluetooth-central while another (e.g. mob_background) keeps audio.
    Merge decision extracted to the pure, tested NativeBuild.plist_array_additions/2.

0.6.15

Choose a tag to compare

@github-actions github-actions released this 23 Jun 05:31
c709cf7

Security

  • Bumped req 0.5.18 → 0.6.2 (pulls finch 0.22.0 → 0.23.0), clearing
    EEF-CVE-2026-49755 (HIGH) and EEF-CVE-2026-49756 (LOW) flagged by
    mix mob.security_scan. req is a transitive dep (via igniter); the bump
    stays within igniter's ~> 0.5 requirement.

Fixed

  • mix mob.new_plugin no longer scaffolds plugins pinned to the abandoned
    mob ~> 0.6.
    MobDev.Plugin.Scaffold hard-coded {:mob, "~> 0.6"} in the
    generated mix.exs and mob_version: "~> 0.6" in every tier's manifest, so a
    freshly scaffolded plugin could not activate against the published mob 0.7.x
    (installed :mob 0.7.x does not satisfy mob_version "~> 0.6"). The requirement
    is now derived at scaffold time from the mob actually resolved in the project
    (Scaffold.detect_mob_requirement/0), falling back to a single
    @fallback_mob_requirement constant ("~> 0.7") when mob isn't loadable.
    mix.exs and the manifest always agree. A Scaffold test pins the default and
    asserts a generated manifest validates against a matching mob version, so the
    pin can't silently lag a future mob release. (#21)

0.6.14

Choose a tag to compare

@github-actions github-actions released this 23 Jun 03:53

Added

  • :extra_static_libs hook on :static_nifs entries — a Mob app can now
    link external per-ABI static archives alongside its project NIF archives.
    Some project NIFs intentionally declare extern symbols and don't host-link
    their backing archive (avoiding a host/device archive mismatch during mix compile); this lets the native app link resolve those symbols against the
    correct per-ABI .a. Entries require concrete per-ABI keys (:ios_sim,
    :ios_device, :android_arm64, :android_arm32, :android_x86_64), and the
    matching archive paths are appended to the existing -Dproject_rust_libs=
    link argument. -D<module>_static=true is emitted only on the ABIs where the
    entry applies, and iOS project-NIF filtering is now per-ABI so a device-only
    guarded entry doesn't leak into simulator args. Also passes Zigler 0.16's
    required generated-build flags when re-driving staged Zig NIF builds and
    resolves Zigler dotfile sources with match_dot: true. Verified on a physical
    SM-T577U (arm64-v8a) tablet via a Ghostty VT NIF. (#24)

Changed

  • mix mob.deploy --native now preserves on-device app data when the signing
    key matches.
    The Android install path previously ran an unconditional
    adb uninstall before adb install, which wiped MOB_DATA_DIR (on-device
    identity, screen stores) on every native deploy — even an in-place update
    signed with the same (e.g. committed) debug keystore. It now attempts
    adb install -r first and only falls back to uninstall + install when the
    in-place update is genuinely rejected (INSTALL_FAILED_UPDATE_INCOMPATIBLE
    from a signature mismatch, INSTALL_FAILED_VERSION_DOWNGRADE, etc.). Apps that
    pin a committed debug keystore now keep their identity across --native
    redeploys. Decision logic extracted to NativeBuild.needs_clean_reinstall?/2
    and unit-tested.

Fixed

  • mix mob.deploy --native --android now fails fast with the real cause when
    zig is missing
    (landed in code before 0.6.13; previously undocumented).
    The Android JNI build is driven by build.zig; with zig off PATH it used to
    print a yellow "skipping build.zig step" warning and fall through to a CMake
    fallback that references C sources mob 0.7+ no longer ships, dying ~150 lines
    later with a misleading Cannot find source file: .../mob_nif.c. It now aborts
    before Gradle with an actionable message (install zig 0.15.x, verify with
    mix mob.doctor) when build.zig is present, zig is absent, and the legacy
    C sources are gone. Decision extracted to NativeBuild.zig_build_plan/3. (#20)

0.6.13

Choose a tag to compare

@github-actions github-actions released this 20 Jun 20:09

Changed

  • mix mob.deploy --native now preserves on-device app data when the signing
    key matches.
    The Android install path previously ran an unconditional
    adb uninstall before adb install, which wiped MOB_DATA_DIR (on-device
    identity, screen stores) on every native deploy — even an in-place update
    signed with the same (e.g. committed) debug keystore. It now attempts
    adb install -r first and only falls back to uninstall + install when the
    in-place update is genuinely rejected (INSTALL_FAILED_UPDATE_INCOMPATIBLE
    from a signature mismatch, INSTALL_FAILED_VERSION_DOWNGRADE, etc.). Apps that
    pin a committed debug keystore now keep their identity across --native
    redeploys. Decision logic extracted to NativeBuild.needs_clean_reinstall?/2
    and unit-tested.

Fixed

  • mix mob.deploy --native --android now fails fast with the real cause when
    zig is missing
    (landed in code before 0.6.13; previously undocumented).
    The Android JNI build is driven by build.zig; with zig off PATH it used to
    print a yellow "skipping build.zig step" warning and fall through to a CMake
    fallback that references C sources mob 0.7+ no longer ships, dying ~150 lines
    later with a misleading Cannot find source file: .../mob_nif.c. It now aborts
    before Gradle with an actionable message (install zig 0.15.x, verify with
    mix mob.doctor) when build.zig is present, zig is absent, and the legacy
    C sources are gone. Decision extracted to NativeBuild.zig_build_plan/3. (#20)

0.6.12

Choose a tag to compare

@github-actions github-actions released this 19 Jun 22:15

Fixed

  • 16 KB page-size alignment enforced at build time for every app. Android
    15+ devices use 16 KB memory pages and Google Play requires every bundled
    .so to have 16 KB-aligned LOAD segments. The -Wl,-z,max-page-size=16384
    link flag lives in the app's build.zig, which is copied once at mix mob.new
    and never regenerated — so apps generated before the template carried the flag
    kept linking 4 KB-aligned .so and failed Play. mix mob.deploy --native now
    reads the app's build.zig and, if its -shared link lacks the flag, injects
    it before linking (idempotent — a no-op when already present, e.g. the current
    mob_new template or a hand-fixed app). Pure core in inject_page_size_flag/1.

0.6.11

Choose a tag to compare

@github-actions github-actions released this 19 Jun 19:12

Added

  • mix mob.adopt — installs Mob into an existing Phoenix project,
    the Igniter-based install-into-existing counterpart to mix mob.new
    (which generates from scratch). Composable: the orchestrator runs the
    sub-installers mob.adopt.{deps,bridge,screen,mob_app,mob_exs,native,finalize},
    each invokable independently. Default LV-bridge mode wires window.mob
    through a LiveView phx-hook and generates a mob_app.ex that boots the
    host Phoenix endpoint on-device (SQLite Repo assumed); --no-live-view
    generates a thin-client shell whose WebView opens a deployed server.
    Pre-1.0: refuses loudly (via Igniter issues) on umbrella / non-Phoenix /
    heavily-customised app.js or root layout / non-SQLite LV hosts rather
    than risk breaking the app. The native Android/iOS trees (--android /
    --ios) render from mob_new's templates and require the mob_new archive
    installed
    (mix archive.install hex mob_new) — mob_new stays the single
    source of native templates; the Elixir-side adoption needs no archive.
    Contributed as mob_new#8
    by @ken-kost and relocated here — adopt is
    an Igniter task that mutates an existing project (like mob.add_nif /
    mob.enable), so it belongs in mob_dev (a Hex dep), not in mob_new (a
    self-contained Mix archive that can't carry Igniter). See
    decisions/2026-06-19-mob-adopt-lives-in-mob_dev.md. The shared
    patcher/generator helpers are duplicated from mob_new into
    MobDev.Adopt.{Patcher,Generator} pending the Phase-5 Igniter
    reunification.

0.6.10

Choose a tag to compare

@github-actions github-actions released this 19 Jun 07:01

Added

  • Plugin :cpp_archive NIFs — ship a C++ static library (e.g. an Nx
    backend) from a plugin. Manifest-driven cross-compile + --whole-archive
    static link (rule #11), with <module>_nif_init symbol verification and
    duplicate-init cross-validation. (#18)

Fixed

  • cpp_archive builds now fail fast with a named error on an unsupported
    Android ABI (e.g. the x86_64 emulator) instead of silently skipping — which
    previously deferred an unresolved <module>_nif_init to an on-device link
    failure.
  • The plugin manifest now requires a lowercase :module atom for
    :cpp_archive entries (fail-loud instead of fail-open / libnil.a).

0.6.9

Choose a tag to compare

@github-actions github-actions released this 19 Jun 04:47

Fixed

  • mix mob.publish --android now commits when Google requires
    changesNotSentForReview=true.
    Uploading a release while the app is under
    policy review (or otherwise can't auto-send for review) made the Play Edits
    :commit fail with HTTP 400 ("Please set the query parameter
    changesNotSentForReview to true"), discarding the whole edit so nothing
    reached the track. commit_edit/3 now detects that 400 and retries the commit
    with ?changesNotSentForReview=true; the changes land on the track and are
    sent for review from the Play Console UI. Verified uploading Io v13 to the
    internal track.

0.6.8

Choose a tag to compare

@github-actions github-actions released this 19 Jun 01:55

Added

  • mix mob.connect --only <serial> (alias --device/-d, repeatable).
    Restricts the run to devices whose serial/udid contains the given substring.
    Without it, connect attaches to every running device, so one slow or locked
    device (typically a plugged-in physical iPhone whose app restart blocks) could
    stall the whole session before any node connected. Verified end-to-end against
    a single Android phone: mix mob.connect --only ZY22CRLMWK tunnels, restarts,
    and connects livebook_mob_android_zy22crlmwk@127.0.0.1 on its serial-derived
    port 9633, then RPC into the device BEAM works (read live state, eval code).