@deeeed/metamask-harness 0.2.0 → 0.3.1
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 +33 -0
- package/README.md +47 -17
- package/{orchestration → adapters}/core/cleanup.sh +2 -2
- package/{orchestration → adapters}/core/inject.sh +8 -8
- package/{orchestration → adapters}/extension/cleanup.mjs +1 -1
- package/{orchestration → adapters}/extension/console-tail.mjs +3 -0
- package/{orchestration → adapters}/extension/ensure-browser.sh +4 -4
- package/{orchestration → adapters}/extension/inject.mjs +27 -31
- package/{orchestration → adapters}/extension/launch.sh +4 -4
- package/{orchestration → adapters}/extension/live.sh +5 -5
- package/{orchestration → adapters}/extension/readiness.mjs +12 -2
- package/{orchestration → adapters}/extension/refresh-build.sh +1 -1
- package/{orchestration → adapters}/extension/seed-fixture.sh +1 -1
- package/{orchestration → adapters}/extension/start-watch.sh +7 -7
- package/{runner → adapters}/extension/verify.sh +11 -11
- package/{orchestration → adapters}/extension/wallet-fixture-state.cjs +2 -2
- package/{orchestration → adapters}/manifest.json +96 -96
- package/{library/actions → adapters}/mobile/bridge-runtime/cdp-bridge.cjs +5 -5
- package/{orchestration → adapters}/mobile/cleanup.sh +3 -3
- package/{orchestration → adapters}/mobile/inject.sh +22 -24
- package/adapters/mobile/open-device.sh +260 -0
- package/{orchestration/compat-overlays → adapters/mobile/overlay/compat}/README.md +13 -4
- package/adapters/mobile/prewarm-bundle.sh +95 -0
- package/adapters/mobile/start-metro.sh +228 -0
- package/{runner → adapters}/mobile/verify.sh +6 -6
- package/adapters/mobile/wait-for-bridge.sh +108 -0
- package/adapters/mobile/yarn-setup.sh +20 -0
- package/{orchestration/lib → adapters/shared}/cli-ux.sh +5 -9
- package/{orchestration/lib → adapters/shared}/log-tui.mjs +57 -1
- package/{orchestration/lib → adapters/shared}/open-debug.mjs +32 -10
- package/{orchestration/lib → adapters/shared}/resolve-farmslot-ports.sh +47 -0
- package/adapters/shared/sync-wallet-fixture.sh +78 -0
- package/bin/mm-harness +37 -6
- package/docs/CLI-SPEC.md +41 -2
- package/docs/architecture.md +69 -38
- package/docs/runtime-file-conventions.md +3 -3
- package/library/actions/core/perps/_controller.mjs +1 -1
- package/library/actions/extension/platform/cdp.mjs +2 -2
- package/library/actions/extension/wallet/ensure_unlocked.mjs +1 -1
- package/library/actions/mobile/platform/bridge.mjs +1 -1
- package/library/actions/mobile/wallet/ensure_unlocked.mjs +1 -1
- package/library/actions/mobile/wallet/setup.mjs +2 -2
- package/library/library.json +1 -1
- package/package.json +8 -8
- package/{orchestration → src/adapters}/extension/runtime-decision.ts +5 -5
- package/{orchestration → src/adapters}/extension/runtime.ts +1 -1
- package/src/adapters/mobile/prepare.ts +210 -0
- package/{orchestration → src/adapters}/mobile/runtime-decision.ts +105 -5
- package/{runner/src → src}/adapters.ts +3 -3
- package/{orchestration/lib/cli-color.mjs → src/cli-color.ts} +21 -13
- package/{orchestration/lib/cli-commands.mjs → src/cli-commands.ts} +52 -45
- package/{orchestration/lib/cli-version.mjs → src/cli-version.ts} +35 -17
- package/{runner/src → src}/cli.ts +48 -40
- package/src/commands/debug.ts +63 -0
- package/src/commands/fixtures.ts +193 -0
- package/{runner/src → src}/commands/launch.ts +200 -54
- package/src/commands/logs.ts +83 -0
- package/{runner/src → src}/commands/shared.ts +40 -30
- package/src/commands/update.ts +316 -0
- package/{runner/src → src}/harness.ts +119 -16
- package/{runner/src → src}/heal-bounds.ts +20 -1
- package/src/index.ts +15 -0
- package/{runner/src → src}/live-adapter-contract.ts +1 -1
- package/{runner/src → src}/mm-harness-cli.ts +64 -3
- package/{runner/src → src}/paths.ts +2 -2
- package/{orchestration/lib/progress.mjs → src/progress.ts} +31 -21
- package/docs/extension-runtime-commands.md +0 -60
- package/docs/harness-cli.md +0 -43
- package/orchestration/compat-overlays/mobile/README.md +0 -13
- package/orchestration/doctor.mjs +0 -72
- package/orchestration/lib/cli-home.mjs +0 -354
- package/orchestration/lib/recipe-paths.mjs +0 -26
- package/orchestration/mobile/launch.sh +0 -137
- package/orchestration/mobile/live.sh +0 -125
- package/orchestration/porcelain/metamask-recipe +0 -99
- package/orchestration/porcelain/mm-recipe +0 -1591
- package/orchestration/porcelain/mme-recipe +0 -1181
- package/runner/src/commands/debug.ts +0 -44
- package/runner/src/commands/fixtures.ts +0 -99
- package/runner/src/commands/logs.ts +0 -60
- package/runner/src/index.ts +0 -6
- /package/{orchestration → adapters}/extension/launch-browser.cjs +0 -0
- /package/{orchestration → adapters}/extension/pin-remote-flags.cjs +0 -0
- /package/{orchestration → adapters}/extension/sidepanel-toggle.sh +0 -0
- /package/{orchestration → adapters}/extension/snapshot-dist.sh +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/config.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/issue-capture.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/target-discovery.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/ws-client.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/setup-wallet.sh +0 -0
- /package/{library/actions/mobile/app-overlay → adapters/mobile/overlay}/app/dev-tools/AgenticService/AgentStepHud.tsx.patch +0 -0
- /package/{library/actions/mobile/app-overlay → adapters/mobile/overlay}/app/dev-tools/AgenticService/AgenticService.ts.patch +0 -0
- /package/{orchestration/compat-overlays/mobile → adapters/mobile/overlay/compat}/rn81-message-event-source.patch +0 -0
- /package/{orchestration/lib → adapters/shared}/activate-repo-node.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/ensure-runner-deps.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/harness-path.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/hash-helpers.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/json-field.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/path-defaults.json +0 -0
- /package/{orchestration → src/adapters}/extension/ensure-ready.ts +0 -0
- /package/{orchestration → src/adapters}/extension/extension-id.ts +0 -0
- /package/{orchestration → src/adapters}/mobile/deps-markers.ts +0 -0
- /package/{runner/src → src}/completions-cache.ts +0 -0
- /package/{runner/src → src}/doctor.ts +0 -0
- /package/{runner/src → src}/manifest.ts +0 -0
- /package/{runner/src → src}/recording-target.ts +0 -0
- /package/{runner/src → src}/run-recording.ts +0 -0
- /package/{runner/src → src}/runner.ts +0 -0
- /package/{runner/src → src}/types.ts +0 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# start-metro — ensure the Metro bundler is running for this MetaMask Mobile checkout.
|
|
3
|
+
#
|
|
4
|
+
# Checks if Metro is already running and owned by this checkout with required env vars.
|
|
5
|
+
# Clears stale or foreign listeners before starting. Uses yarn expo start --port (not
|
|
6
|
+
# yarn start), sources .js.env/.env/.env.local, sets EXPO_NO_TYPESCRIPT_SETUP=1, and
|
|
7
|
+
# caps METRO_MAX_WORKERS to 6 (or the physical CPU count).
|
|
8
|
+
#
|
|
9
|
+
# Inputs:
|
|
10
|
+
# --target <metamask-mobile dir> (default $PWD)
|
|
11
|
+
# --port <number> (default: WATCHER_PORT env, else METRO_PORT, else 8081)
|
|
12
|
+
# --clear reset Metro bundler cache before starting
|
|
13
|
+
# Outputs:
|
|
14
|
+
# Progress on stderr; exit 0 Metro ready; 1 failed to start; 2 bad args.
|
|
15
|
+
#
|
|
16
|
+
# Single device op: ensure Metro is running. Does not open the dev client or install deps.
|
|
17
|
+
set -uo pipefail
|
|
18
|
+
|
|
19
|
+
TARGET="$PWD"
|
|
20
|
+
PORT="${WATCHER_PORT:-${METRO_PORT:-8081}}"
|
|
21
|
+
CLEAR=false
|
|
22
|
+
|
|
23
|
+
while [ "$#" -gt 0 ]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
--target) TARGET="$2"; shift 2 ;;
|
|
26
|
+
--port) PORT="$2"; shift 2 ;;
|
|
27
|
+
--clear) CLEAR=true; shift ;;
|
|
28
|
+
-h|--help)
|
|
29
|
+
printf 'Usage: start-metro.sh [--target <dir>] [--port <port>] [--clear]\n'
|
|
30
|
+
printf ' --target MetaMask Mobile checkout directory\n'
|
|
31
|
+
printf ' --port Metro port (default: WATCHER_PORT env or 8081)\n'
|
|
32
|
+
printf ' --clear restart with cleared cache\n'
|
|
33
|
+
exit 0
|
|
34
|
+
;;
|
|
35
|
+
*) printf 'start-metro: unknown arg: %s\n' "$1" >&2; exit 2 ;;
|
|
36
|
+
esac
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
TARGET="$(cd "$TARGET" && pwd)"
|
|
40
|
+
LOG_DIR="$TARGET/temp/recipe/runtime"
|
|
41
|
+
mkdir -p "$LOG_DIR"
|
|
42
|
+
LOG_FILE="$LOG_DIR/metro.log"
|
|
43
|
+
PID_FILE="$LOG_DIR/metro.pid"
|
|
44
|
+
|
|
45
|
+
# --- helpers ------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
metro_ready() {
|
|
48
|
+
curl -sf --max-time 2 "http://localhost:${PORT}/status" 2>/dev/null | grep -q 'packager-status:running'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
metro_listener_pids() {
|
|
52
|
+
lsof -nP -iTCP:"${PORT}" -sTCP:LISTEN -t 2>/dev/null | tr '\n' ' ' || true
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
metro_listener_valid() {
|
|
56
|
+
local pids pid command rv
|
|
57
|
+
pids="$(metro_listener_pids)"
|
|
58
|
+
[ -n "$(printf '%s' "$pids" | tr -d ' ')" ] || return 1
|
|
59
|
+
rv=0
|
|
60
|
+
for pid in $pids; do
|
|
61
|
+
command="$(ps eww -p "$pid" -o command= 2>/dev/null || true)"
|
|
62
|
+
case "$command" in
|
|
63
|
+
*"$TARGET"*) ;;
|
|
64
|
+
*)
|
|
65
|
+
printf 'Metro on port %s not owned by this checkout (pid %s); restarting\n' "$PORT" "$pid" >&2
|
|
66
|
+
rv=1; break
|
|
67
|
+
;;
|
|
68
|
+
esac
|
|
69
|
+
for required_var in ${MOBILE_METRO_REQUIRED_ENV:-MM_INFURA_PROJECT_ID}; do
|
|
70
|
+
if ! printf '%s\n' "$command" | grep -Eq "(^|[[:space:]])${required_var}="; then
|
|
71
|
+
printf 'Metro on port %s missing required env %s (pid %s); restarting\n' "$PORT" "$required_var" "$pid" >&2
|
|
72
|
+
rv=1; break 2
|
|
73
|
+
fi
|
|
74
|
+
done
|
|
75
|
+
done
|
|
76
|
+
return "$rv"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
stop_metro_listener() {
|
|
80
|
+
local pids i
|
|
81
|
+
pids="$(metro_listener_pids)"
|
|
82
|
+
[ -n "$(printf '%s' "$pids" | tr -d ' ')" ] || return 0
|
|
83
|
+
printf 'Stopping Metro listener on port %s: %s\n' "$PORT" "$pids" >&2
|
|
84
|
+
# shellcheck disable=SC2086
|
|
85
|
+
kill $pids 2>/dev/null || true
|
|
86
|
+
for i in $(seq 1 20); do
|
|
87
|
+
pids="$(metro_listener_pids)"
|
|
88
|
+
[ -z "$(printf '%s' "$pids" | tr -d ' ')" ] && return 0
|
|
89
|
+
sleep 0.25
|
|
90
|
+
done
|
|
91
|
+
printf 'Metro listener still held; force-killing: %s\n' "$pids" >&2
|
|
92
|
+
# shellcheck disable=SC2086
|
|
93
|
+
kill -KILL $pids 2>/dev/null || true
|
|
94
|
+
for i in $(seq 1 20); do
|
|
95
|
+
pids="$(metro_listener_pids)"
|
|
96
|
+
[ -z "$(printf '%s' "$pids" | tr -d ' ')" ] && return 0
|
|
97
|
+
sleep 0.25
|
|
98
|
+
done
|
|
99
|
+
printf 'start-metro: port %s still occupied after force-kill: %s\n' "$PORT" "$pids" >&2
|
|
100
|
+
return 1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
default_metro_workers() {
|
|
104
|
+
local cores=""
|
|
105
|
+
if command -v sysctl >/dev/null 2>&1; then
|
|
106
|
+
cores="$(sysctl -n hw.perflevel0.physicalcpu 2>/dev/null || sysctl -n hw.physicalcpu 2>/dev/null || true)"
|
|
107
|
+
fi
|
|
108
|
+
if printf '%s' "${cores:-}" | grep -Eq '^[0-9]+$' && [ "${cores:-0}" -gt 0 ]; then
|
|
109
|
+
[ "${cores:-4}" -gt 6 ] && cores=6
|
|
110
|
+
printf '%s\n' "$cores"
|
|
111
|
+
else
|
|
112
|
+
printf '4\n'
|
|
113
|
+
fi
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
start_viewer_window() {
|
|
117
|
+
local metro_log="$1"
|
|
118
|
+
command -v tmux >/dev/null 2>&1 || return 0
|
|
119
|
+
local window="metro-${PORT}"
|
|
120
|
+
local metro_tmux="$LOG_DIR/metro.tmux"
|
|
121
|
+
local session=""
|
|
122
|
+
if [ -n "${slot:-}" ] && tmux has-session -t "=mm-${slot}" 2>/dev/null; then
|
|
123
|
+
session="mm-${slot}"
|
|
124
|
+
fi
|
|
125
|
+
if [ -z "$session" ]; then
|
|
126
|
+
session="$(tmux display-message -p '#S' 2>/dev/null || true)"
|
|
127
|
+
fi
|
|
128
|
+
[ -n "$session" ] || return 0
|
|
129
|
+
tmux kill-window -t "${session}:${window}" >/dev/null 2>&1 || true
|
|
130
|
+
tmux new-window -d -t "$session" -n "$window" "exec tail -n +1 -F $(printf '%q' "$metro_log")"
|
|
131
|
+
printf '%s:%s\n' "$session" "$window" > "$metro_tmux"
|
|
132
|
+
printf 'Metro log viewer → tmux %s:%s\n' "$session" "$window" >&2
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# --- main ---------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
# Decide whether to (re)start or skip.
|
|
138
|
+
if metro_ready; then
|
|
139
|
+
if [ "$CLEAR" = true ]; then
|
|
140
|
+
printf 'Restarting Metro on port %s with cleared cache\n' "$PORT" >&2
|
|
141
|
+
stop_metro_listener || exit 1
|
|
142
|
+
rm -f "$PID_FILE"
|
|
143
|
+
elif metro_listener_valid; then
|
|
144
|
+
printf 'Metro already running and valid on port %s\n' "$PORT" >&2
|
|
145
|
+
exit 0
|
|
146
|
+
else
|
|
147
|
+
stop_metro_listener || exit 1
|
|
148
|
+
rm -f "$PID_FILE"
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
stop_metro_listener || exit 1
|
|
153
|
+
|
|
154
|
+
METRO_WORKERS="${METRO_MAX_WORKERS:-$(default_metro_workers)}"
|
|
155
|
+
CLEAR_SUFFIX=""
|
|
156
|
+
[ "$CLEAR" = true ] && CLEAR_SUFFIX=" --clear"
|
|
157
|
+
|
|
158
|
+
printf 'Starting Metro on port %s (workers=%s%s)\n' \
|
|
159
|
+
"$PORT" "$METRO_WORKERS" "${CLEAR:+, clear}" >&2
|
|
160
|
+
printf '(Full log: %s — recipe logs | recipe logs --full)\n' "$LOG_FILE" >&2
|
|
161
|
+
|
|
162
|
+
# Metro runs detached, writing to the log. The tmux window is a read-only tail.
|
|
163
|
+
(
|
|
164
|
+
cd "$TARGET"
|
|
165
|
+
: > "$LOG_FILE"
|
|
166
|
+
# Source product env files (provides MM_INFURA_PROJECT_ID and friends).
|
|
167
|
+
set -a
|
|
168
|
+
# shellcheck disable=SC1091
|
|
169
|
+
[ ! -f .js.env ] || . ./.js.env
|
|
170
|
+
# shellcheck disable=SC1091
|
|
171
|
+
[ ! -f .env ] || . ./.env
|
|
172
|
+
# shellcheck disable=SC1091
|
|
173
|
+
[ ! -f .env.local ] || . ./.env.local
|
|
174
|
+
set +a
|
|
175
|
+
export EXPO_NO_TYPESCRIPT_SETUP=1
|
|
176
|
+
export WATCHER_PORT="${PORT}" METRO_PORT="${PORT}"
|
|
177
|
+
export METRO_MAX_WORKERS="${METRO_WORKERS}"
|
|
178
|
+
# shellcheck disable=SC2094
|
|
179
|
+
bash -c "exec yarn expo start --port ${PORT}${CLEAR_SUFFIX}" \
|
|
180
|
+
</dev/null >> "$LOG_FILE" 2>&1 &
|
|
181
|
+
echo "$!" > "$PID_FILE"
|
|
182
|
+
)
|
|
183
|
+
# Disown the background process so it outlives this script.
|
|
184
|
+
disown "$(cat "$PID_FILE" 2>/dev/null || true)" 2>/dev/null || true
|
|
185
|
+
|
|
186
|
+
start_viewer_window "$LOG_FILE"
|
|
187
|
+
|
|
188
|
+
# Attach a log-tui watcher for compact event display (best-effort; non-blocking).
|
|
189
|
+
LOG_TUI="$(dirname "$0")/../shared/log-tui.mjs"
|
|
190
|
+
TAIL_PID=""
|
|
191
|
+
if [ -f "$LOG_TUI" ] && command -v node >/dev/null 2>&1 \
|
|
192
|
+
&& [ "${METAMASK_RECIPE_AUTO_HUD:-1}" != "0" ]; then
|
|
193
|
+
node "$LOG_TUI" watch \
|
|
194
|
+
--log "$LOG_FILE" \
|
|
195
|
+
--events "${RECIPE_LOG_EVENTS:-12}" \
|
|
196
|
+
--mode compact \
|
|
197
|
+
--label "Metro bundler" \
|
|
198
|
+
--success-pattern 'Dev server ready' &
|
|
199
|
+
TAIL_PID=$!
|
|
200
|
+
fi
|
|
201
|
+
|
|
202
|
+
# Ready-poll: 90 × 1s = 90 s timeout.
|
|
203
|
+
READY=false
|
|
204
|
+
for _i in $(seq 1 90); do
|
|
205
|
+
if metro_ready; then
|
|
206
|
+
READY=true
|
|
207
|
+
break
|
|
208
|
+
fi
|
|
209
|
+
sleep 1
|
|
210
|
+
done
|
|
211
|
+
|
|
212
|
+
[ -n "$TAIL_PID" ] && { kill "$TAIL_PID" 2>/dev/null; wait "$TAIL_PID" 2>/dev/null || true; }
|
|
213
|
+
|
|
214
|
+
if [ "$READY" = true ]; then
|
|
215
|
+
printf 'Metro ready on port %s\n' "$PORT" >&2
|
|
216
|
+
printf ' Next: mm-harness logs (tail Metro)\n' >&2
|
|
217
|
+
exit 0
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
# Failure: dump log events for diagnosis.
|
|
221
|
+
if [ -f "$LOG_TUI" ] && command -v node >/dev/null 2>&1; then
|
|
222
|
+
node "$LOG_TUI" events --log "$LOG_FILE" --events 20 >&2 || true
|
|
223
|
+
else
|
|
224
|
+
tail -40 "$LOG_FILE" >&2 || true
|
|
225
|
+
fi
|
|
226
|
+
printf 'start-metro: Metro did not become ready on port %s within 90s\n' "$PORT" >&2
|
|
227
|
+
printf ' Next: check %s for errors, or run mm-harness logs\n' "$LOG_FILE" >&2
|
|
228
|
+
exit 1
|
|
@@ -58,12 +58,12 @@ esac
|
|
|
58
58
|
|
|
59
59
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
60
60
|
# shellcheck disable=SC1091
|
|
61
|
-
for _hp in "$SCRIPT_DIR/lib/harness-path.sh" "$SCRIPT_DIR/../../
|
|
61
|
+
for _hp in "$SCRIPT_DIR/lib/harness-path.sh" "$SCRIPT_DIR/../../adapters/shared/harness-path.sh" "$SCRIPT_DIR/../shared/harness-path.sh"; do
|
|
62
62
|
[ -f "$_hp" ] && { . "$_hp"; break; }
|
|
63
63
|
done
|
|
64
64
|
unset _hp
|
|
65
65
|
if ! command -v harness_root >/dev/null 2>&1; then
|
|
66
|
-
echo "mobile verify: shared lib
|
|
66
|
+
echo "mobile verify: shared lib adapters/shared/harness-path.sh not found; reinstall the runner." >&2
|
|
67
67
|
exit 1
|
|
68
68
|
fi
|
|
69
69
|
TARGET="$(cd "$TARGET" && pwd)"
|
|
@@ -71,7 +71,7 @@ RUNTIME_DIR="$(recipe_runtime_dir)"
|
|
|
71
71
|
HARNESS_ROOT="$(harness_root)"
|
|
72
72
|
HARNESS_REL="$HARNESS_ROOT/mobile"
|
|
73
73
|
HARNESS_DIR="$(harness_dir "$TARGET" mobile)"
|
|
74
|
-
RUNNER_BIN="$HARNESS_DIR/runner/bin/
|
|
74
|
+
RUNNER_BIN="$HARNESS_DIR/runner/bin/mm-harness"
|
|
75
75
|
ARTIFACTS="${ARTIFACTS:-$HARNESS_DIR/verify/$(date -u +%Y%m%dT%H%M%SZ)}"
|
|
76
76
|
mkdir -p "$ARTIFACTS/logs"
|
|
77
77
|
|
|
@@ -221,7 +221,7 @@ check_file() {
|
|
|
221
221
|
|
|
222
222
|
check_file "$HARNESS_REL/manifest.json"
|
|
223
223
|
check_file "$HARNESS_REL/action-manifest.json"
|
|
224
|
-
check_file "$HARNESS_REL/runner/bin/
|
|
224
|
+
check_file "$HARNESS_REL/runner/bin/mm-harness"
|
|
225
225
|
check_file "package.json"
|
|
226
226
|
check_file "app/dev-tools/AgenticService/AgenticService.ts"
|
|
227
227
|
|
|
@@ -263,7 +263,7 @@ if (!runnerDir) {
|
|
|
263
263
|
process.stdout.write(JSON.stringify({ name, status: 'warn', detail: 'runner source unavailable; overlay freshness compare skipped' }));
|
|
264
264
|
process.exit(0);
|
|
265
265
|
}
|
|
266
|
-
const overlayDir = path.join(runnerDir, '
|
|
266
|
+
const overlayDir = path.join(runnerDir, 'adapters', 'mobile', 'overlay', 'app', 'core', 'AgenticService');
|
|
267
267
|
let checked = 0;
|
|
268
268
|
const drifted = [];
|
|
269
269
|
const missing = [];
|
|
@@ -289,7 +289,7 @@ if (checked === 0) {
|
|
|
289
289
|
const parts = [];
|
|
290
290
|
if (drifted.length) parts.push('behind runner: ' + drifted.join(', '));
|
|
291
291
|
if (missing.length) parts.push('absent in repo: ' + missing.join(', '));
|
|
292
|
-
process.stdout.write(JSON.stringify({ name, status: 'warn', detail: parts.join('; ') + ' — rerun
|
|
292
|
+
process.stdout.write(JSON.stringify({ name, status: 'warn', detail: parts.join('; ') + ' — rerun mm-harness install --force-overlay or recipe sync to refresh the in-repo HUD/AgenticService from the runner' }));
|
|
293
293
|
} else {
|
|
294
294
|
process.stdout.write(JSON.stringify({ name, status: 'pass' }));
|
|
295
295
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# wait-for-bridge — poll the CDP bridge until a route target is registered.
|
|
3
|
+
#
|
|
4
|
+
# Calls cdp-bridge.cjs status in a poll loop. Emits structured diagnostics on
|
|
5
|
+
# each probe failure: Metro reachability, React Native target visibility, bundle
|
|
6
|
+
# progress. Fails with non-zero if the bridge is not ready within the poll limit.
|
|
7
|
+
#
|
|
8
|
+
# Inputs:
|
|
9
|
+
# --target <metamask-mobile dir> (default $PWD)
|
|
10
|
+
# --port <number> (default WATCHER_PORT env, else METRO_PORT, else 8081)
|
|
11
|
+
# --max-polls <n> (default MOBILE_BRIDGE_READY_POLLS env, else 90; 2s each = 180s)
|
|
12
|
+
# Outputs:
|
|
13
|
+
# Progress on stderr; exit 0 bridge ready; 1 timeout.
|
|
14
|
+
#
|
|
15
|
+
# Single device op: wait for bridge readiness. Does not start Metro or open the dev client.
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
|
|
18
|
+
TARGET="$PWD"
|
|
19
|
+
PORT="${WATCHER_PORT:-${METRO_PORT:-8081}}"
|
|
20
|
+
MAX_POLLS="${MOBILE_BRIDGE_READY_POLLS:-90}"
|
|
21
|
+
|
|
22
|
+
while [ "$#" -gt 0 ]; do
|
|
23
|
+
case "$1" in
|
|
24
|
+
--target) TARGET="$2"; shift 2 ;;
|
|
25
|
+
--port) PORT="$2"; shift 2 ;;
|
|
26
|
+
--max-polls) MAX_POLLS="$2"; shift 2 ;;
|
|
27
|
+
-h|--help)
|
|
28
|
+
printf 'Usage: wait-for-bridge.sh [--target <dir>] [--port <n>] [--max-polls <n>]\n'
|
|
29
|
+
exit 0
|
|
30
|
+
;;
|
|
31
|
+
*) printf 'wait-for-bridge: unknown arg: %s\n' "$1" >&2; exit 2 ;;
|
|
32
|
+
esac
|
|
33
|
+
done
|
|
34
|
+
|
|
35
|
+
TARGET="$(cd "$TARGET" && pwd)"
|
|
36
|
+
LOG_DIR="$TARGET/temp/recipe/runtime"
|
|
37
|
+
mkdir -p "$LOG_DIR"
|
|
38
|
+
|
|
39
|
+
BRIDGE_CJS="$(dirname "$0")/bridge-runtime/cdp-bridge.cjs"
|
|
40
|
+
STATUS_LOG="$LOG_DIR/bridge-status.log"
|
|
41
|
+
METRO_LOG="$LOG_DIR/metro.log"
|
|
42
|
+
|
|
43
|
+
if [ ! -f "$BRIDGE_CJS" ]; then
|
|
44
|
+
printf 'wait-for-bridge: cdp-bridge.cjs not found at %s\n' "$BRIDGE_CJS" >&2
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
metro_ready() {
|
|
49
|
+
curl -sf --max-time 2 "http://localhost:${PORT}/status" 2>/dev/null | grep -q 'packager-status:running'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
bundle_progress() {
|
|
53
|
+
local log="$1"
|
|
54
|
+
[ -f "$log" ] || return 0
|
|
55
|
+
local p
|
|
56
|
+
p="$(grep -E '^[[:space:]]*(iOS|Android).*index\.(js|tsx?).*%|Bundl(ed|ing)|Finished' "$log" 2>/dev/null | tail -1 | tr -d '\r' || true)"
|
|
57
|
+
[ -n "$p" ] && printf ' (%s)' "$p"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
bridge_wait_reason() {
|
|
61
|
+
if ! metro_ready; then
|
|
62
|
+
printf 'Metro not reachable on port %s' "$PORT"
|
|
63
|
+
return
|
|
64
|
+
fi
|
|
65
|
+
local targets
|
|
66
|
+
targets="$(curl -sf --max-time 2 "http://localhost:${PORT}/json/list" 2>/dev/null || true)"
|
|
67
|
+
if [ "$targets" = "[]" ] || [ -z "$targets" ]; then
|
|
68
|
+
printf 'Metro running; no React Native debug target yet'
|
|
69
|
+
bundle_progress "$METRO_LOG"
|
|
70
|
+
return
|
|
71
|
+
fi
|
|
72
|
+
if [ -s "$STATUS_LOG" ] && grep -qxF '[]' "$STATUS_LOG"; then
|
|
73
|
+
printf 'React Native target visible; in-app bridge not ready yet'
|
|
74
|
+
bundle_progress "$METRO_LOG"
|
|
75
|
+
return
|
|
76
|
+
fi
|
|
77
|
+
printf 'bridge probe failed'
|
|
78
|
+
bundle_progress "$METRO_LOG"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
bridge_has_route() {
|
|
82
|
+
(cd "$TARGET" && APP_ROOT="$TARGET" node "$BRIDGE_CJS" status > "$STATUS_LOG" 2>&1) \
|
|
83
|
+
&& node - "$STATUS_LOG" <<'NODE'
|
|
84
|
+
const fs = require('fs');
|
|
85
|
+
try {
|
|
86
|
+
const value = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
|
87
|
+
const targets = Array.isArray(value) ? value : [value];
|
|
88
|
+
if (!targets.some((t) => t && typeof t === 'object' && t.route)) process.exit(1);
|
|
89
|
+
} catch { process.exit(1); }
|
|
90
|
+
NODE
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for ATTEMPT in $(seq 1 "$MAX_POLLS"); do
|
|
94
|
+
if bridge_has_route; then
|
|
95
|
+
printf 'Mobile bridge ready\n' >&2
|
|
96
|
+
exit 0
|
|
97
|
+
fi
|
|
98
|
+
if [ "$ATTEMPT" = "1" ] || [ $((ATTEMPT % 5)) -eq 0 ]; then
|
|
99
|
+
printf 'Waiting for Mobile bridge (%s/%s): %s\n' "$ATTEMPT" "$MAX_POLLS" "$(bridge_wait_reason)" >&2
|
|
100
|
+
fi
|
|
101
|
+
sleep 2
|
|
102
|
+
done
|
|
103
|
+
|
|
104
|
+
cat "$STATUS_LOG" >&2 || true
|
|
105
|
+
printf 'wait-for-bridge: bridge did not become ready on port %s (%s polls × 2s = %ss)\n' \
|
|
106
|
+
"$PORT" "$MAX_POLLS" "$((MAX_POLLS * 2))" >&2
|
|
107
|
+
printf ' Next: check %s — or run mm-harness app-status\n' "$STATUS_LOG" >&2
|
|
108
|
+
exit 1
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# yarn-setup — install node_modules for MetaMask Mobile.
|
|
3
|
+
#
|
|
4
|
+
# Inputs: --target <metamask-mobile dir> (default $PWD)
|
|
5
|
+
# Outputs: yarn install output on stderr; exit 0 pass, 1 install failed, 2 bad args.
|
|
6
|
+
#
|
|
7
|
+
# Single device op: install node_modules. No other sequencing.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
TARGET="$PWD"
|
|
11
|
+
while [ "$#" -gt 0 ]; do
|
|
12
|
+
case "$1" in
|
|
13
|
+
--target) TARGET="$2"; shift 2 ;;
|
|
14
|
+
-h|--help) printf 'Usage: yarn-setup.sh [--target <dir>]\n'; exit 0 ;;
|
|
15
|
+
*) printf 'yarn-setup: unknown arg: %s\n' "$1" >&2; exit 2 ;;
|
|
16
|
+
esac
|
|
17
|
+
done
|
|
18
|
+
|
|
19
|
+
TARGET="$(cd "$TARGET" && pwd)"
|
|
20
|
+
cd "$TARGET" && exec yarn setup
|
|
@@ -26,19 +26,15 @@ recipe_color() {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
recipe_progress_script() {
|
|
29
|
-
printf '%s' "${RECIPE_PROGRESS_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
recipe_home_script() {
|
|
33
|
-
printf '%s' "${RECIPE_HOME_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/orchestration/lib/cli-home.mjs}"
|
|
29
|
+
printf '%s' "${RECIPE_PROGRESS_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/src/progress.ts}"
|
|
34
30
|
}
|
|
35
31
|
|
|
36
32
|
recipe_log_tui_script() {
|
|
37
|
-
printf '%s' "${RECIPE_LOG_TUI_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/
|
|
33
|
+
printf '%s' "${RECIPE_LOG_TUI_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/adapters/shared/log-tui.mjs}"
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
recipe_version_script() {
|
|
41
|
-
printf '%s' "${RECIPE_VERSION_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/
|
|
37
|
+
printf '%s' "${RECIPE_VERSION_SCRIPT:-${RECIPE_RUNNER_ROOT:?}/src/cli-version.ts}"
|
|
42
38
|
}
|
|
43
39
|
|
|
44
40
|
recipe_log_ui_mode() {
|
|
@@ -79,7 +75,7 @@ recipe_instant_hint() {
|
|
|
79
75
|
|
|
80
76
|
recipe_progress() {
|
|
81
77
|
local verb="$1" phase="$2" message="$3" elapsed="${4:-}"
|
|
82
|
-
local args=(emit --
|
|
78
|
+
local args=(emit --command "$verb" --phase "$phase" --message "$message")
|
|
83
79
|
[ -n "$elapsed" ] && args+=(--elapsed-ms "$elapsed")
|
|
84
80
|
[ "${RECIPE_PROGRESS_JSON:-}" = "1" ] && args+=(--json)
|
|
85
81
|
node "$(recipe_progress_script)" "${args[@]}" || true
|
|
@@ -87,7 +83,7 @@ recipe_progress() {
|
|
|
87
83
|
|
|
88
84
|
recipe_done() {
|
|
89
85
|
local verb="$1" status="$2" message="$3" elapsed="${4:-}"
|
|
90
|
-
local args=(done --
|
|
86
|
+
local args=(done --command "$verb" --status "$status" --message "$message")
|
|
91
87
|
[ -n "$elapsed" ] && args+=(--elapsed-ms "$elapsed")
|
|
92
88
|
[ "${RECIPE_PROGRESS_JSON:-}" = "1" ] && args+=(--json)
|
|
93
89
|
node "$(recipe_progress_script)" "${args[@]}" || true
|
|
@@ -4,7 +4,63 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import { parseArgs } from 'node:util';
|
|
7
|
-
|
|
7
|
+
// Inline color helpers — self-contained so both the runner copy and any
|
|
8
|
+
// installed copy work without an external module dependency.
|
|
9
|
+
const STYLES = {
|
|
10
|
+
reset: '\x1b[0m',
|
|
11
|
+
bold: '\x1b[1m',
|
|
12
|
+
dim: '\x1b[2m',
|
|
13
|
+
label: '\x1b[1;36m',
|
|
14
|
+
cmd: '\x1b[1m',
|
|
15
|
+
ok: '\x1b[1;32m',
|
|
16
|
+
warn: '\x1b[1;33m',
|
|
17
|
+
err: '\x1b[1;31m',
|
|
18
|
+
info: '\x1b[0;37m',
|
|
19
|
+
accent: '\x1b[1;35m',
|
|
20
|
+
path: '\x1b[2m',
|
|
21
|
+
comment: '\x1b[2m',
|
|
22
|
+
active: '\x1b[1m',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function colorEnabled(stream = process.stderr) {
|
|
26
|
+
if (process.env.NO_COLOR != null && process.env.NO_COLOR !== '' && process.env.NO_COLOR !== '0') {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (process.env.RECIPE_NO_COLOR === '1') return false;
|
|
30
|
+
if (process.env.RECIPE_COLOR === '1' || process.env.FORCE_COLOR === '1') return true;
|
|
31
|
+
return Boolean(stream?.isTTY);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function color(style, text, { stream = process.stderr } = {}) {
|
|
35
|
+
const value = String(text);
|
|
36
|
+
if (!colorEnabled(stream)) return value;
|
|
37
|
+
const code = STYLES[style];
|
|
38
|
+
if (!code) return value;
|
|
39
|
+
return `${code}${value}${STYLES.reset}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function classifyLogEvent(event) {
|
|
43
|
+
const text = String(event || '');
|
|
44
|
+
if (/Module build failed|^ERROR in |BUILD FAILED|compiled with [1-9][0-9]* error/iu.test(text)) {
|
|
45
|
+
return 'err';
|
|
46
|
+
}
|
|
47
|
+
if (/compiled successfully|compiled with [0-9]+ warning|PASS runtime-launch|launch pass|verify pass|build complete/iu.test(text)) {
|
|
48
|
+
return 'ok';
|
|
49
|
+
}
|
|
50
|
+
if (/phase [0-9]\/[0-9]|prepare pipeline|snapshot|fixture:|dist-freshness|build-health/iu.test(text)) {
|
|
51
|
+
return 'label';
|
|
52
|
+
}
|
|
53
|
+
if (/webpack [0-9]+%|Bundl(ed|ing)|(iOS|Android).*%/iu.test(text)) {
|
|
54
|
+
return 'warn';
|
|
55
|
+
}
|
|
56
|
+
return 'info';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function colorLogEvent(event, { latest = false, stream = process.stderr } = {}) {
|
|
60
|
+
const style = classifyLogEvent(event);
|
|
61
|
+
const painted = color(style === 'label' ? 'label' : style, event, { stream });
|
|
62
|
+
return latest ? color('active', painted, { stream }) : painted;
|
|
63
|
+
}
|
|
8
64
|
|
|
9
65
|
const DEFAULT_EVENTS = 10;
|
|
10
66
|
|
|
@@ -115,16 +115,34 @@ function openUrl(url) {
|
|
|
115
115
|
return null;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// CDP-eval fallback: invoke DevSettings native module directly via the bridge
|
|
119
|
+
// when the Metro HTTP endpoint is unreachable or returns a non-OK response.
|
|
120
|
+
// Used for both debug (openDebugger) and dev-menu (show).
|
|
121
|
+
async function tryDevSettingsCdpFallback(numericPort, normalizedAction) {
|
|
122
|
+
const bridgePath = new URL('cdp-bridge.cjs', import.meta.url).pathname;
|
|
123
|
+
const expression =
|
|
124
|
+
normalizedAction === 'dev-menu'
|
|
125
|
+
? 'NativeModules.DevSettings.show()'
|
|
126
|
+
: 'NativeModules.DevSettings.openDebugger()';
|
|
127
|
+
const result = spawnSync(process.execPath, [bridgePath, 'eval', expression], {
|
|
128
|
+
encoding: 'utf8',
|
|
129
|
+
env: { ...process.env, WATCHER_PORT: String(numericPort) },
|
|
130
|
+
timeout: 15000,
|
|
131
|
+
});
|
|
132
|
+
return result.status === 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
118
135
|
async function openMobileDebugger(port, action, shouldOpen) {
|
|
119
136
|
const normalizedAction = action === 'dev-menu' ? 'dev-menu' : 'debug';
|
|
120
|
-
const
|
|
137
|
+
const urlPath = normalizedAction === 'dev-menu' ? '/open-dev-menu' : '/open-debugger';
|
|
121
138
|
const numericPort = Number.parseInt(String(port), 10);
|
|
122
139
|
if (!Number.isInteger(numericPort) || numericPort <= 0) {
|
|
123
140
|
return { ok: false, adapter: 'mobile', action: normalizedAction, error: 'invalid-port', port };
|
|
124
141
|
}
|
|
125
142
|
|
|
143
|
+
let metroError = null;
|
|
126
144
|
try {
|
|
127
|
-
const opened = await fetchOk(`http://127.0.0.1:${numericPort}${
|
|
145
|
+
const opened = await fetchOk(`http://127.0.0.1:${numericPort}${urlPath}`, { method: 'POST' });
|
|
128
146
|
if (opened) {
|
|
129
147
|
return {
|
|
130
148
|
ok: true,
|
|
@@ -135,16 +153,21 @@ async function openMobileDebugger(port, action, shouldOpen) {
|
|
|
135
153
|
opened: shouldOpen,
|
|
136
154
|
};
|
|
137
155
|
}
|
|
156
|
+
metroError = 'metro-http-nok';
|
|
138
157
|
} catch (error) {
|
|
158
|
+
metroError = error instanceof Error ? error.message : String(error);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// CDP-eval fallback via DevSettings native module.
|
|
162
|
+
const cdpOk = await tryDevSettingsCdpFallback(numericPort, normalizedAction);
|
|
163
|
+
if (cdpOk) {
|
|
139
164
|
return {
|
|
140
|
-
ok:
|
|
165
|
+
ok: true,
|
|
141
166
|
adapter: 'mobile',
|
|
142
167
|
action: normalizedAction,
|
|
143
|
-
method: '
|
|
168
|
+
method: 'cdp-eval',
|
|
144
169
|
port: numericPort,
|
|
145
|
-
|
|
146
|
-
hint: 'Metro may be down or the debug target is not ready. Try recipe refresh, then recipe runtime-status.',
|
|
147
|
-
fallback: 'cdp-eval',
|
|
170
|
+
opened: shouldOpen,
|
|
148
171
|
};
|
|
149
172
|
}
|
|
150
173
|
|
|
@@ -154,9 +177,8 @@ async function openMobileDebugger(port, action, shouldOpen) {
|
|
|
154
177
|
action: normalizedAction,
|
|
155
178
|
method: 'metro-http',
|
|
156
179
|
port: numericPort,
|
|
157
|
-
error:
|
|
158
|
-
hint: 'Metro
|
|
159
|
-
fallback: 'cdp-eval',
|
|
180
|
+
error: metroError,
|
|
181
|
+
hint: 'Metro may be down or the debug target is not ready. Check metro status and try again.',
|
|
160
182
|
};
|
|
161
183
|
}
|
|
162
184
|
|
|
@@ -142,3 +142,50 @@ apply_resolved_extension_ports() {
|
|
|
142
142
|
esac
|
|
143
143
|
done <<< "$resolved"
|
|
144
144
|
}
|
|
145
|
+
|
|
146
|
+
# Mobile slot defaults: derive Metro port + iOS simulator name from directory suffix.
|
|
147
|
+
# Port formula: 8060 + N (slot 1 → 8061). iOS simulator: mm-N.
|
|
148
|
+
# Mirrors the extension convention (6660+N / 9010+N) for multi-slot mobile farms.
|
|
149
|
+
resolve_mobile_slot_defaults() {
|
|
150
|
+
local repo="$1" n
|
|
151
|
+
n="$(infer_extension_slot_suffix "$repo" || true)"
|
|
152
|
+
[ -n "$n" ] || return 1
|
|
153
|
+
printf 'WATCHER_PORT=%s\n' "$((8060 + n))"
|
|
154
|
+
printf 'IOS_SIMULATOR=mm-%s\n' "$n"
|
|
155
|
+
printf 'SLOT_ID=local-mobile-%s\n' "$n"
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
resolve_mobile_runtime_ports() {
|
|
159
|
+
local repo="${1:-.}"
|
|
160
|
+
if resolve_farmslot_ports_by_repo "$repo"; then
|
|
161
|
+
return 0
|
|
162
|
+
fi
|
|
163
|
+
resolve_mobile_slot_defaults "$repo"
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
apply_resolved_mobile_ports() {
|
|
167
|
+
local repo="${1:-.}" line key val from_pool=false resolved=""
|
|
168
|
+
if resolved="$(resolve_farmslot_ports_by_repo "$repo" 2>/dev/null)"; then
|
|
169
|
+
from_pool=true
|
|
170
|
+
elif resolved="$(resolve_mobile_slot_defaults "$repo" 2>/dev/null)"; then
|
|
171
|
+
from_pool=false
|
|
172
|
+
else
|
|
173
|
+
return 0
|
|
174
|
+
fi
|
|
175
|
+
while IFS= read -r line; do
|
|
176
|
+
[ -n "$line" ] || continue
|
|
177
|
+
key="${line%%=*}"
|
|
178
|
+
val="${line#*=}"
|
|
179
|
+
case "$key" in
|
|
180
|
+
WATCHER_PORT)
|
|
181
|
+
if [ "$from_pool" = true ] || [ -z "${WATCHER_PORT:-}" ]; then WATCHER_PORT="$val"; fi
|
|
182
|
+
;;
|
|
183
|
+
IOS_SIMULATOR)
|
|
184
|
+
if [ "$from_pool" = true ] || [ -z "${IOS_SIMULATOR:-}" ]; then IOS_SIMULATOR="$val"; fi
|
|
185
|
+
;;
|
|
186
|
+
SLOT_ID)
|
|
187
|
+
if [ "$from_pool" = true ] || [ -z "${RECIPE_SLOT_ID:-}" ]; then RECIPE_SLOT_ID="$val"; fi
|
|
188
|
+
;;
|
|
189
|
+
esac
|
|
190
|
+
done <<< "$resolved"
|
|
191
|
+
}
|