From 5f39be805d6c32a8ac22638e162389c015c11eb8 Mon Sep 17 00:00:00 2001 From: GenericJam Date: Fri, 11 Sep 2026 23:18:09 -0600 Subject: [PATCH] =?UTF-8?q?MOB-73=20=E2=80=94=20fix=20--slim=20gate:=20pub?= =?UTF-8?q?lish=20MOB=5FSLIM=20env=20var=20instead=20of=20Process=20dict?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `mix mob.deploy --slim` was a silent no-op. `NativeBuild.build_all/1` stored the boolean in `Process.put(:mob_slim, slim)` but the actual strip-pass gate at `maybe_slim_otp_bundle/2` reads `System.get_env("MOB_SLIM")` (mirroring `release.ex`, which explicitly sets the env var for its subprocess call chain). Nothing ever read back from the process dict. Fix: replace the Process.put call with a public-for-testing helper `__apply_slim_env__/1` that sets `MOB_SLIM=1` or `=0`, matching what `release.ex` already does. The gate at `maybe_slim_otp_bundle/2` is unchanged. Both paths (mob.deploy + mob.release) now use the same env-var mechanism. Two revert-verified tests in `NativeBuildTest`: setting `MOB_SLIM=0` then calling `__apply_slim_env__(true)` must leave the env at `"1"`, and vice versa. Setup/on_exit save-restore MOB_SLIM for isolation (module is already async: false). Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 10 +++++++++ lib/mob_dev/native_build.ex | 14 ++++++++++++- test/mob_dev/native_build_test.exs | 33 ++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd79ed8..668b797 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ ### Fixed +- **`mix mob.deploy --slim` is no longer a silent no-op** (MOB-73). + `NativeBuild.build_all/1` stored `slim` in the process dict + (`Process.put(:mob_slim, slim)`) but the actual gate at + `maybe_slim_otp_bundle/2` reads `System.get_env("MOB_SLIM")` — so + `--slim` from the CLI never reached the strip pass. Only + `mix mob.release` produced a slim OTP bundle, because that path + explicitly sets the env var. Fixed by publishing `MOB_SLIM=1` / `=0` + in `__apply_slim_env__/1`, which the gate already knows how to read. + Two revert-verified tests lock the env-var contract. + - **Plugin signature verification now runs before `Code.eval_file`** on the manifest (MOB-74). The v1 signature covered the eval'd manifest map, so verifiers needed the eval to run first to rebuild the payload — letting diff --git a/lib/mob_dev/native_build.ex b/lib/mob_dev/native_build.ex index 4494a45..4eac5d0 100644 --- a/lib/mob_dev/native_build.ex +++ b/lib/mob_dev/native_build.ex @@ -40,7 +40,7 @@ defmodule MobDev.NativeBuild do do: narrow_platforms_for_device(platforms, device_id), else: platforms - Process.put(:mob_slim, slim) + __apply_slim_env__(slim) # Always regenerate the runtime plugin manifest from the CURRENT activated # plugins before bundling priv — like the driver_tab, it's derived state, not @@ -5857,6 +5857,18 @@ defmodule MobDev.NativeBuild do :ok end + @doc false + # Publish the --slim flag into MOB_SLIM so `maybe_slim_otp_bundle/2` (which + # mirrors `release.ex`'s env-var gate) actually sees it. Before MOB-73 this + # went into `Process.put(:mob_slim, ...)` and nothing consulted it — so + # `mix mob.deploy --slim` was a silent no-op. Public-for-testing so the + # env-var contract is regression-guarded. + @spec __apply_slim_env__(boolean()) :: :ok + def __apply_slim_env__(slim) when is_boolean(slim) do + System.put_env("MOB_SLIM", if(slim, do: "1", else: "0")) + :ok + end + defp maybe_slim_otp_bundle(app_path, cfg) do if System.get_env("MOB_SLIM") == "1" do otp_bundle = Path.join(app_path, "otp") diff --git a/test/mob_dev/native_build_test.exs b/test/mob_dev/native_build_test.exs index 7c22ac4..f2e6bd3 100644 --- a/test/mob_dev/native_build_test.exs +++ b/test/mob_dev/native_build_test.exs @@ -10,6 +10,39 @@ defmodule MobDev.NativeBuildTest do alias MobDev.NativeBuild + describe "__apply_slim_env__/1 (MOB-73 --slim gate)" do + setup do + # Save/restore MOB_SLIM across the test since it's process-global. + previous = System.get_env("MOB_SLIM") + + on_exit(fn -> + case previous do + nil -> System.delete_env("MOB_SLIM") + val -> System.put_env("MOB_SLIM", val) + end + end) + + :ok + end + + test "true publishes MOB_SLIM=1 so the slim gate actually fires" do + # Before MOB-73 this went through `Process.put(:mob_slim, true)` and + # `maybe_slim_otp_bundle/2` never consulted the dict — so `mix mob.deploy + # --slim` was a silent no-op. The env-var read at native_build.ex:5861 + # is what the strip pass gates on; the helper's job is to set it. Revert + # to Process.put and this fails. + System.put_env("MOB_SLIM", "0") + :ok = NativeBuild.__apply_slim_env__(true) + assert System.get_env("MOB_SLIM") == "1" + end + + test "false publishes MOB_SLIM=0 so --no-slim is explicit and observable" do + System.put_env("MOB_SLIM", "1") + :ok = NativeBuild.__apply_slim_env__(false) + assert System.get_env("MOB_SLIM") == "0" + end + end + describe "build_zig_supports_abi?/2" do test "true when the build.zig declares the ABI as a quoted string literal" do src = ~s|