-
Notifications
You must be signed in to change notification settings - Fork 0
/
entrypoint.sh
executable file
·396 lines (347 loc) · 12.4 KB
/
entrypoint.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
#!/bin/bash
. /opt/debug.sh
. /opt/logger.sh
logger "INFO" "\n\n\n\t\tMCLOUD-IOS-CONNECTOR\n\n"
#### Preparation steps
# If HOST_OS is null or unset use default value
HOST_OS="${HOST_OS:-"LINUX"}"
#### Establish and check usbmuxd connection
# Check if $USBMUXD_PORT port is free
declare -i index=0
isLocalPortFree=0
# TODO: adjust timeout based on real usage
while [[ $index -lt 10 ]]; do
# If we can connect to the port, then someone is already waiting for a connection on this port
if nc -z localhost "$USBMUXD_PORT"; then
logger "ERROR" "localhost $USBMUXD_PORT port is busy. One more attempt..."
index+=1
sleep 1
else
isLocalPortFree=1
break
fi
done; index=0
if [[ $isLocalPortFree -eq 1 ]]; then
logger "localhost $USBMUXD_PORT port is free."
else
logger "ERROR" "localhost $USBMUXD_PORT port is busy. Exiting!"
exit 0
fi
# Check if selected usbmuxd socket available
declare -i index=0
isUsbmuxdConnected=0
if [[ -z $USBMUXD_SOCKET_ADDRESS ]]; then
logger "Start containerized usbmuxd service/process."
usbmuxd -f &
# Check if '/var/run/usbmuxd' exists
while [[ $index -lt 10 ]]; do
if ! socat /dev/null UNIX-CONNECT:/var/run/usbmuxd; then
logger "ERROR" "Can't connect to '/var/run/usbmuxd'. One more attempt..."
index+=1
sleep 1
else
isUsbmuxdConnected=1
socat TCP-LISTEN:"$USBMUXD_PORT",reuseaddr,fork UNIX-CONNECT:/var/run/usbmuxd &
break
fi
done; index=0
else
# rm /var/run/usbmuxd in advance to be able to start socat and join it to $USBMUXD_SOCKET_ADDRESS
# rm -f /var/run/usbmuxd
# socat UNIX-LISTEN:/var/run/usbmuxd,fork,reuseaddr,mode=777 TCP:"$USBMUXD_SOCKET_ADDRESS" &
# Check if 'USBMUXD_SOCKET_ADDRESS' exists
while [[ $index -lt 10 ]]; do
if ! socat /dev/null TCP:"$USBMUXD_SOCKET_ADDRESS"; then
logger "ERROR" "Can't connect to USBMUXD_SOCKET_ADDRESS: '$USBMUXD_SOCKET_ADDRESS'. One more attempt..."
index+=1
sleep 1
else
isUsbmuxdConnected=1
socat TCP-LISTEN:"$USBMUXD_PORT",reuseaddr,fork TCP:"$USBMUXD_SOCKET_ADDRESS" &
break
fi
done; index=0
fi
if [[ $isUsbmuxdConnected -eq 1 ]]; then
logger "Usbmuxd socket is available."
else
logger "ERROR" "Usbmuxd socket is not available. Exiting!"
exit 0
fi
# Check if localhost $USBMUXD_PORT port is accessible now
declare -i index=0
isPortAccessible=0
while [[ $index -lt 10 ]]; do
if ! nc -z localhost "$USBMUXD_PORT"; then
logger "ERROR" "Usbmuxd forwarding is not established. One more attempt..."
index+=1
sleep 1
else
isPortAccessible=1
break
fi
done; index=0
if [[ $isPortAccessible -eq 1 ]]; then
logger "Usbmuxd forwarding established."
else
logger "ERROR" "Usbmuxd forwarding is not established. Exiting!"
exit 0
fi
#### Check device connection
declare -i index=0
isAvailable=0
while [[ $index -lt 10 ]]; do
if deviceInfo=$(ios info --udid="$DEVICE_UDID" 2>&1); then
logger "Device '$DEVICE_UDID' is available."
logger "Device info:"
echo "$deviceInfo" | jq --raw-input '. as $line | try (fromjson) catch $line'
isAvailable=1
break
elif [[ "${deviceInfo}" == *"failed getting info"* ]]; then
logger "WARN" "Failed getting info."
elif [[ "${deviceInfo}" == *"Timed out waiting for response for message"* ]]; then
# Timed out error.
# {"channel_id":"com.apple.instruments.server.services.deviceinfo","error":"Timed out waiting for response for message:5 channel:0","level":"error","msg":"failed requesting channel","time":"2023-09-05T15:19:27Z"}
logger "WARN" "Timed out waiting for response. Device reboot is recommended!"
isAvailable=1
break
else
logger "WARN" "Device is not found '$DEVICE_UDID'!"
fi
logger "WARN" "Waiting for ${POLLING_SEC} seconds."
sleep "${POLLING_SEC}"
index+=1
done; index=0
if [[ $isAvailable -eq 0 ]]; then
logger "ERROR" "Device is not available:"
echo "$deviceInfo" | jq --raw-input '. as $line | try (fromjson) catch $line'
logger "ERROR" "Restarting!"
exit 1
fi
#### Detect device OS version
ios17plus=0
deviceOsVersion=$(echo "$deviceInfo" | sed -n 's/.*"ProductVersion":"\([^"]*\).*/\1/p')
logger "Detected device os version: $deviceOsVersion"
# removes everything from the first dot '.' onwards
majorOsVersion="${deviceOsVersion%%.*}"
if [[ "$majorOsVersion" -gt 0 ]] 2>/dev/null; then
logger "Major os version detected as '$majorOsVersion'"
if [[ "$majorOsVersion" -ge 17 ]]; then
ios17plus=1
fi
else
logger "WARN" "Can't detect major os version: $majorOsVersion"
fi
#### Run go-ncm and check connection
if [[ "$ios17plus" -eq 1 ]] && [[ ${HOST_OS^^} = "LINUX" ]]; then
logger "Starting go-ncm and its reporting on 3030 port."
# To check 'curl localhost:3030/metrics'
go-ncm --prometheusport=3030 &
declare -i index=0
isNcmConnected=0
# TODO: adjust timeout based on real usage
while [[ $index -lt 10 ]]; do
curl -Is localhost:3030/metrics | head -1 | grep -q '200 OK'
if [[ $? -ne 0 ]]; then
logger "Ncm '/metrics' endpoint is not available."
else
deviceCount=$(curl -s localhost:3030/metrics | grep "^device_count" | cut -d ' ' -f2)
logger "Found $deviceCount device connected with ncm."
[[ "$deviceCount" -ge 1 ]] && isNcmConnected=1 && break
fi
logger "WARN" "Waiting for ${POLLING_SEC} seconds."
sleep "${POLLING_SEC}"
index+=1
done; index=0
if [[ $isNcmConnected -eq 0 ]]; then
logger "ERROR" "Ncm can't connect with device. Restarting!"
exit 1
fi
fi
#### Start and check tunnel
if [[ "$ios17plus" -eq 1 ]] && [[ ${HOST_OS^^} = "LINUX" ]]; then
tunnelLogFile="/tmp/log/tunnel.log"
touch $tunnelLogFile
logger "Starting tunnel for --udid=$DEVICE_UDID"
ios tunnel start --pair-record-path=/var/lib/lockdown --udid="$DEVICE_UDID" > "$tunnelLogFile" 2>&1 &
tail -f "$tunnelLogFile" &
declare -i index=0
isTunnelStarted=0
# TODO: adjust timeout based on real usage
while [[ $index -lt 10 ]]; do
curl -Is localhost:60105/tunnels | head -1 | grep -q '200 OK'
if [[ $? -ne 0 ]]; then
logger "Go-ios '/tunnels' endpoint is not available."
else
logger "Go-ios '/tunnels' endpoint is available:"
tunnels=$(curl -s localhost:60105/tunnels)
echo "$tunnels"
echo "$tunnels" | grep -q "$DEVICE_UDID" && isTunnelStarted=1 && break
fi
logger "WARN" "Waiting for ${POLLING_SEC} seconds."
sleep "${POLLING_SEC}"
index+=1
done; index=0
# TODO: add reasons processing and possibly exit
if [[ $isTunnelStarted -eq 0 ]]; then
logger "ERROR" "Can't start tunnel to device. Restarting!"
exit 1
fi
fi
#### Mount DeveloperDiscImage
logger "Allow to download and mount DeveloperDiskImages automatically."
# Parse error to detect anomaly with mounting and/or pairing. It might be use case when user cleared already trusted computer
# {"err":"failed connecting to image mounter: Could not start service:com.apple.mobile.mobile_image_mounter with reason:'SessionInactive'. Have you mounted the Developer Image?","image":"/tmp/DeveloperDiskImages/16.4.1/DeveloperDiskImage.dmg","level":"error","msg":"error mounting image","time":"2023-08-04T11:25:53Z","udid":"d6afc6b3a65584ca0813eb8957c6479b9b6ebb11"}
if res=$(ios image auto --basedir /tmp/DeveloperDiskImages --udid="$DEVICE_UDID" 2>&1); then
logger "Developer Image auto mount succeed:"
echo "$res" | jq --raw-input '. as $line | try (fromjson) catch $line'
sleep 3
elif [[ "${res}" == *"error mounting image"* ]]; then
logger "ERROR" "Developer Image mounting is broken:"
echo "$res" | jq --raw-input '. as $line | try (fromjson) catch $line'
logger "ERROR" "Restarting!"
exit 0
else
logger "ERROR" "Unhandled exception:"
echo "$res" | jq --raw-input '. as $line | try (fromjson) catch $line'
logger "ERROR" "Exiting!"
exit 0
fi
#### Check if WDA is already installed
if ios apps --udid="$DEVICE_UDID" | grep -v grep | grep "$WDA_BUNDLEID" > /dev/null 2>&1; then
logger "'$WDA_BUNDLEID' app is already installed"
else
logger "'$WDA_BUNDLEID' app is not installed"
if [[ ${HOST_OS^^} = "LINUX" ]]; then
if [[ ! -f "$WDA_FILE" ]]; then
logger "ERROR" "'$WDA_FILE' file is not exist or not a regular file. Exiting!"
exit 0
fi
logger "Installing WDA application on device:"
wdaInstall=$(ios install --path="$WDA_FILE" --udid="$DEVICE_UDID" 2>&1)
if [[ $wdaInstall == *'"err":'* ]]; then
logger "ERROR" "Error while installing WDA_FILE: '$WDA_FILE'."
echo "$wdaInstall" | jq --raw-input '. as $line | try (fromjson) catch $line'
logger "ERROR" "Trying to uninstall WDA:"
wdaUninstall=$(ios uninstall "$WDA_BUNDLEID" --udid="$DEVICE_UDID" 2>&1)
echo "$wdaUninstall" | jq --raw-input '. as $line | try (fromjson) catch $line'
logger "ERROR" "Exiting!"
exit 0
fi
else
logger "ERROR" "Can't continue without WDA installed. Exiting!"
exit 0
fi
fi
#### Start WDA
runWda() {
touch "${WDA_LOG_FILE}"
tail -f "${WDA_LOG_FILE}" &
# This is temporary solution for modal dialogs which prevent WDA startup.
logger "Resetting springboard process and waiting for 5 seconds."
ios kill com.apple.springboard --udid="$DEVICE_UDID"
sleep 5
declare -i index=0
isWdaStarted=0
while [[ $index -lt 10 ]]; do
if ! (pgrep -f "ios runwda" > /dev/null 2>&1); then
ios runwda \
--bundleid="${WDA_BUNDLEID:="com.facebook.WebDriverAgentRunner.xctrunner"}" \
--testrunnerbundleid="${TEST_RUNNER_BUNDLE_ID:=$WDA_BUNDLEID}" \
--xctestconfig="${XCTEST_CONFIG:="WebDriverAgentRunner.xctest"}" \
--env USE_PORT="$WDA_PORT" \
--env MJPEG_SERVER_PORT="$MJPEG_PORT" \
--env UITEST_DISABLE_ANIMATIONS=YES \
--log-output="${WDA_LOG_FILE}" \
--udid="$DEVICE_UDID"
logger "WARN" "'ios runwda' process broke. Attempt to recover."
isWdaStarted=0
else
logger "WARN" "WDA already started"
isWdaStarted=1
break
fi
sleep 1
index+=1
done; index=0
if [[ $isWdaStarted -eq 0 ]]; then
logger "ERROR" "Can't run WDA. Exiting!"
exit 0
fi
}
forwardPort() {
if [[ -n $1 ]]; then
port=$1
logger "Forwarding port: $port"
else
logger "WARN" "Port value is empty or not provided!"
return 1
fi
declare -i index=0
isPortForwarded=0
# TODO: adjust timeout based on real usage
while [[ $index -lt 30 ]]; do
if ! (pgrep -f "ios forward $port" > /dev/null 2>&1); then
ios forward "$port" "$port" --udid="$DEVICE_UDID" > /dev/null 2>&1
logger "WARN" "Port '$port' forwarding broke. Attempt to recover."
isPortForwarded=0
else
logger "WARN" "Port '$port' already forwarded"
isPortForwarded=1
break
fi
sleep 1
index+=1
done; index=0
if [[ $isPortForwarded -eq 0 ]]; then
logger "ERROR" "Can't forward port '$port'. Restarting!"
exit 1
fi
}
if [[ ${HOST_OS^^} = "LINUX" ]]; then
curl -Is "http://${WDA_HOST}:${WDA_PORT}/status" | head -1 | grep -q '200 OK'
if [[ $? -ne 0 ]]; then
logger "WARN" "Running WDA not detected."
logger "Starting WebDriverAgent application on port '$WDA_PORT'."
runWda &
sleep 3
# #148: ios: reuse proxy for redirecting wda requests through appium container
forwardPort "$WDA_PORT" &
sleep 1
forwardPort "$MJPEG_PORT" &
fi
else
# On macOS platform reset springboard only for ios version lower than 17
if [[ "$ios17plus" -eq 1 ]]; then
sleep 1
else
logger "Resetting springboard process and waiting for 5 seconds."
ios kill com.apple.springboard --udid="$DEVICE_UDID"
sleep 5
fi
forwardPort "$WDA_PORT" &
sleep 1
forwardPort "$MJPEG_PORT" &
fi
#### Wait for WDA start
startTime=$(date +%s)
wdaStarted=0
while [[ $((startTime + WDA_WAIT_TIMEOUT)) -gt "$(date +%s)" ]]; do
curl -Is "http://${WDA_HOST}:${WDA_PORT}/status" | head -1 | grep -q '200 OK'
if [[ $? -eq 0 ]]; then
logger "Wda status is OK!"
wdaStarted=1
break
fi
logger "WARN" "Bad or no response from 'http://${WDA_HOST}:${WDA_PORT}/status'. One more attempt..."
sleep 2
done
if [[ $wdaStarted -eq 0 ]]; then
logger "ERROR" "No response from WDA, or WDA is unhealthy. Restarting!"
exit 1
fi
# TODO: to improve better 1st super slow session startup we have to investigate extra xcuitest caps: https://github.com/appium/appium-xcuitest-driver
# customSnapshotTimeout, waitForIdleTimeout, animationCoolOffTimeout etc
# TODO: also find a way to override default snapshot generation 60 sec timeout building WebDriverAgent.ipa
#### Entrypoint holder
sleep infinity