@deeeed/metamask-harness 0.51.1 → 0.51.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.51.3 - 2026-09-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `fixtures set` on mobile bounds the setup-wallet leaf at six minutes instead of two: after an unlock the app hydrates every account before it answers the bridge again, and a large fixture on a loaded Mac took past the old bound while the wallet itself reached the unlocked home screen. `MM_HARNESS_FIXTURES_SET_TIMEOUT_MS` still overrides it.
|
|
10
|
+
## 0.51.2 - 2026-09-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Mobile native builds no longer pass `--no-bundler` to Expo: a Debug configuration starts the bundler regardless, so 0.51.1 left Expo attached to a stray Metro on 8081 and the launch never returned. Instead the build env answers Expo's one `lsof` lookup for the Metro listener from the harness's `metro.pid`; Expo's 350 ms lsof budget is what a busy Mac missed. A reused Metro listener now records its pid too.
|
|
15
|
+
|
|
5
16
|
## 0.51.1 - 2026-09-13
|
|
6
17
|
|
|
7
18
|
### Fixed
|
|
@@ -81,6 +81,46 @@ for _rb in "$SCRIPT_DIR/../shared/activate-repo-ruby.sh" "$SCRIPT_DIR/lib/activa
|
|
|
81
81
|
[ -f "$_rb" ] && { . "$_rb"; break; }
|
|
82
82
|
done
|
|
83
83
|
unset _rb
|
|
84
|
+
# shellcheck disable=SC1091
|
|
85
|
+
for _hp in "$SCRIPT_DIR/../shared/harness-path.sh" "$SCRIPT_DIR/lib/harness-path.sh"; do
|
|
86
|
+
[ -f "$_hp" ] && { . "$_hp"; break; }
|
|
87
|
+
done
|
|
88
|
+
unset _hp
|
|
89
|
+
|
|
90
|
+
# Expo's run:ios / run:android bookkeeping asks lsof which process listens on
|
|
91
|
+
# the Metro port, before and after the native build, under a 350 ms budget.
|
|
92
|
+
# lsof scans every process on the machine, so a busy Mac misses that budget
|
|
93
|
+
# and Expo aborts a finished build with "Port became busy running another
|
|
94
|
+
# process while the app was compiling". The harness started that listener and
|
|
95
|
+
# recorded it in metro.pid: answer that one query from the record and hand
|
|
96
|
+
# every other lsof call to the real binary.
|
|
97
|
+
write_lsof_shim() {
|
|
98
|
+
local dir="$1" real_lsof
|
|
99
|
+
real_lsof="$(command -v lsof 2>/dev/null || true)"
|
|
100
|
+
[ -n "$real_lsof" ] || return 0
|
|
101
|
+
{
|
|
102
|
+
printf '#!/usr/bin/env bash\n'
|
|
103
|
+
printf 'REAL_LSOF=%q\n' "$real_lsof"
|
|
104
|
+
cat <<'SHIM'
|
|
105
|
+
# Exactly Expo's listener query and nothing else. A recycled pid after a Metro
|
|
106
|
+
# death is the only way this can lie, and a dead Metro fails the build anyway.
|
|
107
|
+
if [ $# -eq 4 ] && [ "$1" = "-i:${MM_HARNESS_BUILD_WATCHER_PORT:-}" ] && [ "$2" = "-P" ] && [ "$3" = "-t" ] && [ "$4" = "-sTCP:LISTEN" ] \
|
|
108
|
+
&& [ -f "${MM_HARNESS_METRO_PID_FILE:-/nonexistent}" ]; then
|
|
109
|
+
pid="$(cat "$MM_HARNESS_METRO_PID_FILE" 2>/dev/null)"
|
|
110
|
+
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then printf '%s\n' "$pid"; exit 0; fi
|
|
111
|
+
fi
|
|
112
|
+
exec "$REAL_LSOF" "$@"
|
|
113
|
+
SHIM
|
|
114
|
+
} > "$dir/lsof"
|
|
115
|
+
chmod +x "$dir/lsof"
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
metro_pid_file() {
|
|
119
|
+
command -v recipe_runtime_dir >/dev/null 2>&1 || return 1
|
|
120
|
+
local runtime
|
|
121
|
+
runtime="$(recipe_runtime_dir)" || return 1
|
|
122
|
+
printf '%s/%s/metro.pid' "$TARGET" "$runtime"
|
|
123
|
+
}
|
|
84
124
|
|
|
85
125
|
# --- iOS helpers --------------------------------------------------------------
|
|
86
126
|
|
|
@@ -90,7 +130,7 @@ ios_app_installed() {
|
|
|
90
130
|
}
|
|
91
131
|
|
|
92
132
|
run_ios_native_build() (
|
|
93
|
-
local sim_target="$1" bundle_id="$2" reason="$3" build_env="" build_script="" build_type=""
|
|
133
|
+
local sim_target="$1" bundle_id="$2" reason="$3" build_env="" build_script="" build_type="" shim_dir=""
|
|
94
134
|
case "$bundle_id" in
|
|
95
135
|
io.metamask.MetaMask|io.metamask) build_script="start:ios"; build_type="main" ;;
|
|
96
136
|
io.metamask.MetaMask-Flask) build_script="start:ios:flask"; build_type="flask" ;;
|
|
@@ -102,11 +142,15 @@ run_ios_native_build() (
|
|
|
102
142
|
printf '%s; installing with yarn %s (WATCHER_PORT=%s)\n' "$reason" "$build_script" "$PORT" >&2
|
|
103
143
|
build_env="$(mktemp "${TMPDIR:-/tmp}/mm-harness-ios-build-env.XXXXXX")" || return 1
|
|
104
144
|
chmod 600 "$build_env" || { rm -f "$build_env"; return 1; }
|
|
105
|
-
|
|
145
|
+
shim_dir="$(mktemp -d "${TMPDIR:-/tmp}/mm-harness-build-shim.XXXXXX")" || { rm -f "$build_env"; return 1; }
|
|
146
|
+
trap 'rm -rf "$build_env" "$shim_dir"' EXIT HUP INT TERM
|
|
147
|
+
write_lsof_shim "$shim_dir"
|
|
106
148
|
{
|
|
107
149
|
printf 'export MM_HARNESS_BUILD_WATCHER_PORT=%q\n' "$PORT"
|
|
108
150
|
printf 'export MM_HARNESS_BUILD_IOS_SIMULATOR=%q\n' "$sim_target"
|
|
109
151
|
printf 'export MM_HARNESS_BUILD_TYPE=%q\n' "$build_type"
|
|
152
|
+
printf 'export MM_HARNESS_METRO_PID_FILE=%q\n' "$(metro_pid_file || true)"
|
|
153
|
+
printf 'export PATH=%q:"$PATH"\n' "$shim_dir"
|
|
110
154
|
cat <<'BUILD_ENV'
|
|
111
155
|
mm_harness_restore_build_target() {
|
|
112
156
|
export WATCHER_PORT="$MM_HARNESS_BUILD_WATCHER_PORT"
|
|
@@ -126,31 +170,6 @@ source() {
|
|
|
126
170
|
mm_harness_restore_build_target
|
|
127
171
|
return "$status"
|
|
128
172
|
}
|
|
129
|
-
# The harness owns Metro on WATCHER_PORT. Expo's own bundler management
|
|
130
|
-
# re-checks that port after the build with lsof under a 350 ms budget, which a
|
|
131
|
-
# loaded machine misses, and then aborts with "Port became busy". Build only:
|
|
132
|
-
# --no-bundler, which Expo refuses next to --port, so the port argument goes.
|
|
133
|
-
mm_harness_expo_build_args() {
|
|
134
|
-
local arg skip=false
|
|
135
|
-
MM_HARNESS_EXPO_ARGS=()
|
|
136
|
-
for arg in "$@"; do
|
|
137
|
-
if [ "$skip" = true ]; then skip=false; continue; fi
|
|
138
|
-
case "$arg" in
|
|
139
|
-
--port) skip=true; continue ;;
|
|
140
|
-
--port=*) continue ;;
|
|
141
|
-
esac
|
|
142
|
-
MM_HARNESS_EXPO_ARGS+=("$arg")
|
|
143
|
-
done
|
|
144
|
-
MM_HARNESS_EXPO_ARGS+=(--no-bundler)
|
|
145
|
-
}
|
|
146
|
-
yarn() {
|
|
147
|
-
if [ "${1:-}" = expo ] && [ "${2:-}" = run:ios ]; then
|
|
148
|
-
mm_harness_expo_build_args "$@"
|
|
149
|
-
command yarn "${MM_HARNESS_EXPO_ARGS[@]}"
|
|
150
|
-
else
|
|
151
|
-
command yarn "$@"
|
|
152
|
-
fi
|
|
153
|
-
}
|
|
154
173
|
mm_harness_restore_build_target
|
|
155
174
|
BUILD_ENV
|
|
156
175
|
} > "$build_env"
|
|
@@ -306,7 +325,7 @@ android_app_installed() {
|
|
|
306
325
|
}
|
|
307
326
|
|
|
308
327
|
run_android_native_build() (
|
|
309
|
-
local serial="$1" expo_device="$2" pkg="$3" reason="$4" build_env="" build_script=""
|
|
328
|
+
local serial="$1" expo_device="$2" pkg="$3" reason="$4" build_env="" build_script="" shim_dir=""
|
|
310
329
|
case "$pkg" in
|
|
311
330
|
io.metamask) build_script="start:android" ;;
|
|
312
331
|
io.metamask.flask) build_script="start:android:flask" ;;
|
|
@@ -318,11 +337,15 @@ run_android_native_build() (
|
|
|
318
337
|
printf '%s; installing with yarn %s (WATCHER_PORT=%s)\n' "$reason" "$build_script" "$PORT" >&2
|
|
319
338
|
build_env="$(mktemp "${TMPDIR:-/tmp}/mm-harness-android-build-env.XXXXXX")" || return 1
|
|
320
339
|
chmod 600 "$build_env" || { rm -f "$build_env"; return 1; }
|
|
321
|
-
|
|
340
|
+
shim_dir="$(mktemp -d "${TMPDIR:-/tmp}/mm-harness-build-shim.XXXXXX")" || { rm -f "$build_env"; return 1; }
|
|
341
|
+
trap 'rm -rf "$build_env" "$shim_dir"' EXIT HUP INT TERM
|
|
342
|
+
write_lsof_shim "$shim_dir"
|
|
322
343
|
{
|
|
323
344
|
printf 'export MM_HARNESS_BUILD_ANDROID_SERIAL=%q\n' "$serial"
|
|
324
345
|
printf 'export MM_HARNESS_BUILD_ANDROID_EXPO_DEVICE=%q\n' "$expo_device"
|
|
325
346
|
printf 'export MM_HARNESS_BUILD_WATCHER_PORT=%q\n' "$PORT"
|
|
347
|
+
printf 'export MM_HARNESS_METRO_PID_FILE=%q\n' "$(metro_pid_file || true)"
|
|
348
|
+
printf 'export PATH=%q:"$PATH"\n' "$shim_dir"
|
|
326
349
|
cat <<'BUILD_ENV'
|
|
327
350
|
mm_harness_restore_android_build_target() {
|
|
328
351
|
export WATCHER_PORT="$MM_HARNESS_BUILD_WATCHER_PORT"
|
|
@@ -342,24 +365,9 @@ source() {
|
|
|
342
365
|
mm_harness_restore_android_build_target
|
|
343
366
|
return "$status"
|
|
344
367
|
}
|
|
345
|
-
# --no-bundler without --port: the harness owns Metro on WATCHER_PORT (see the
|
|
346
|
-
# iOS build env for why).
|
|
347
|
-
mm_harness_expo_build_args() {
|
|
348
|
-
local arg skip=false
|
|
349
|
-
MM_HARNESS_EXPO_ARGS=()
|
|
350
|
-
for arg in "$@"; do
|
|
351
|
-
if [ "$skip" = true ]; then skip=false; continue; fi
|
|
352
|
-
case "$arg" in
|
|
353
|
-
--port) skip=true; continue ;;
|
|
354
|
-
--port=*) continue ;;
|
|
355
|
-
esac
|
|
356
|
-
MM_HARNESS_EXPO_ARGS+=("$arg")
|
|
357
|
-
done
|
|
358
|
-
}
|
|
359
368
|
yarn() {
|
|
360
369
|
if [ "${1:-}" = expo ] && [ "${2:-}" = run:android ]; then
|
|
361
|
-
|
|
362
|
-
command yarn "${MM_HARNESS_EXPO_ARGS[@]}" "$MM_HARNESS_BUILD_ANDROID_EXPO_DEVICE" --no-bundler
|
|
370
|
+
command yarn "$@" "$MM_HARNESS_BUILD_ANDROID_EXPO_DEVICE"
|
|
363
371
|
else
|
|
364
372
|
command yarn "$@"
|
|
365
373
|
fi
|
|
@@ -218,6 +218,12 @@ if metro_ready; then
|
|
|
218
218
|
rm -f "$PID_FILE"
|
|
219
219
|
elif metro_listener_valid; then
|
|
220
220
|
printf 'Metro already running and valid on port %s\n' "$PORT" >&2
|
|
221
|
+
# A reused listener still needs its record: the native build answers
|
|
222
|
+
# Expo's port lookup from metro.pid.
|
|
223
|
+
if [ ! -f "$PID_FILE" ]; then
|
|
224
|
+
lsof -nP -iTCP:"$PORT" -sTCP:LISTEN -t 2>/dev/null | head -1 > "$PID_FILE" || true
|
|
225
|
+
[ -s "$PID_FILE" ] || rm -f "$PID_FILE"
|
|
226
|
+
fi
|
|
221
227
|
exit 0
|
|
222
228
|
else
|
|
223
229
|
stop_metro_listener || exit 1
|
|
@@ -10,6 +10,7 @@ import { applyDeviceTargeting } from "./device-target.js";
|
|
|
10
10
|
import { ADAPTER_DETECT_NEXT, checkoutBusyOut, EXIT, flag, parseFlags, resolveAdapter, scriptOverride, spawnScript, spawnScriptStreaming, str, targetOf, usageOut } from "./shared.js";
|
|
11
11
|
const FIXTURES_BOOLEANS = /* @__PURE__ */ new Set(["dev", "force", "json"]);
|
|
12
12
|
const FIXTURE_STREAM_TIMEOUT_MS = 12e4;
|
|
13
|
+
const MOBILE_SETUP_WALLET_TIMEOUT_MS = 36e4;
|
|
13
14
|
async function handleFixtures(argv) {
|
|
14
15
|
const { positional, options } = parseFlags(argv, FIXTURES_BOOLEANS);
|
|
15
16
|
if (!positional[0]) return fixturesStatus(options);
|
|
@@ -246,8 +247,8 @@ async function handleFixturesLocked(argv) {
|
|
|
246
247
|
}
|
|
247
248
|
}
|
|
248
249
|
}
|
|
249
|
-
const configuredTimeout = Number(process.env.MM_HARNESS_FIXTURES_SET_TIMEOUT_MS ??
|
|
250
|
-
const timeoutMs = Number.isFinite(configuredTimeout) && configuredTimeout > 0 ? configuredTimeout :
|
|
250
|
+
const configuredTimeout = Number(process.env.MM_HARNESS_FIXTURES_SET_TIMEOUT_MS ?? MOBILE_SETUP_WALLET_TIMEOUT_MS);
|
|
251
|
+
const timeoutMs = Number.isFinite(configuredTimeout) && configuredTimeout > 0 ? configuredTimeout : MOBILE_SETUP_WALLET_TIMEOUT_MS;
|
|
251
252
|
if (!resetError) {
|
|
252
253
|
mobileSetupResult = await spawnScriptStreaming(
|
|
253
254
|
setupWalletSh,
|