Skip to content

Commit 21c766b

Browse files
Fix CI: Update scripts for robustness and timeouts
- Updated `scripts/ci/run-ios-simulator.sh`: - Replaced `simctl bootstatus` with a manual polling loop to support older simctl versions and avoid "illegal option" errors. - Logging is directed to stderr. - Updated `scripts/ci/start-android-emulator.sh`: - Explicitly create the log directory before redirection. - Fixed `pgrep` usage to avoid script failure if no process is found. - Improved `sdkmanager` invocation robustness against broken pipes. - Added timeout logic to boot wait loop. - Updated `.github/workflows/maven.yml`: - Added `timeout-minutes` to Android (20m) and iOS (20m) jobs to prevent long hangs.
1 parent 7fda350 commit 21c766b

File tree

3 files changed

+56
-33
lines changed

3 files changed

+56
-33
lines changed

.github/workflows/maven.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
jobs:
1010
build:
1111
runs-on: ubuntu-latest
12+
timeout-minutes: 15
1213
steps:
1314
- uses: actions/checkout@v2
1415
- name: Set up JDK 11
@@ -25,6 +26,7 @@ jobs:
2526

2627
android:
2728
runs-on: ubuntu-22.04
29+
timeout-minutes: 20
2830
steps:
2931
- uses: actions/checkout@v4
3032
- name: Install Java 17
@@ -73,6 +75,7 @@ jobs:
7375
7476
ios:
7577
runs-on: macos-15
78+
timeout-minutes: 20
7679
steps:
7780
- uses: actions/checkout@v4
7881
- name: Install Java 11

scripts/ci/run-ios-simulator.sh

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function info() {
3939

4040
function ensure_device() {
4141
# Try to find the exact runtime first, or fallback to the latest available iOS runtime
42-
# We extract the last column which is the runtime identifier (e.g. com.apple.CoreSimulator.SimRuntime.iOS-17-2)
42+
# We extract the last column which is the runtime identifier
4343
local runtime_id
4444
runtime_id=$(xcrun simctl list runtimes | awk -v r="$SIM_RUNTIME" '/com.apple.CoreSimulator.SimRuntime/ && $0 ~ r {print $NF}' | sort | tail -n 1)
4545

@@ -57,10 +57,7 @@ function ensure_device() {
5757
info "Selected runtime: $runtime_id"
5858

5959
local existing
60-
# Escape parenthesis for awk regex or use index
61-
# We look for: Name (UUID) ... RuntimeID
62-
# awk '$0 ~ n" (" ...' failed because of the open parenthesis in regex.
63-
# We can check if line starts with "$SIM_DEVICE_NAME ("
60+
# Safely extract UDID using grep and delimiter-based awk to avoid regex issues with parenthesis
6461
existing=$(xcrun simctl list devices "$runtime_id" | grep -F "$SIM_DEVICE_NAME (" | head -n 1 | awk -F '[()]' '{print $2}')
6562

6663
if [[ -n $existing ]]; then
@@ -69,11 +66,7 @@ function ensure_device() {
6966
fi
7067

7168
# Create device
72-
# Usage: xcrun simctl create <name> <device_type_id> <runtime_id>
7369
local device_type="com.apple.CoreSimulator.SimDeviceType.iPhone-15"
74-
# Verify device type exists, fallback to generic if iPhone 15 missing?
75-
# For now assume iPhone-15 exists on macos-15 runner.
76-
7770
local udid
7871
udid=$(xcrun simctl create "$SIM_DEVICE_NAME" "$device_type" "$runtime_id")
7972
echo "$udid"
@@ -83,7 +76,26 @@ function boot_device() {
8376
local udid=$1
8477
info "Booting simulator $SIM_DEVICE_NAME ($udid)"
8578
xcrun simctl boot "$udid" >/dev/null 2>&1 || true
86-
xcrun simctl bootstatus "$udid" -b --timeout "$SIM_TIMEOUT"
79+
80+
# Wait for boot completion manually since --timeout might be unsupported on some versions
81+
info "Waiting for boot status..."
82+
local attempts=0
83+
local booted="false"
84+
while [[ "$booted" == "false" ]]; do
85+
local state
86+
state=$(xcrun simctl list devices | grep "$udid" | grep "(Booted)" || true)
87+
if [[ -n "$state" ]]; then
88+
booted="true"
89+
else
90+
sleep 5
91+
((attempts+=5))
92+
if (( attempts > SIM_TIMEOUT )); then
93+
echo "Timeout waiting for simulator boot" >&2
94+
exit 1
95+
fi
96+
fi
97+
done
98+
info "Simulator booted"
8799
}
88100

89101
function install_and_launch() {

scripts/ci/start-android-emulator.sh

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,26 @@ function info() {
4747

4848
function ensure_sdk_tools() {
4949
local sdkmanager_bin
50-
# Prefer explicitly installed latest tools
50+
51+
# Try to find sdkmanager in standard locations
5152
if [[ -x "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" ]]; then
5253
sdkmanager_bin="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager"
54+
elif [[ -x "$ANDROID_SDK_ROOT/cmdline-tools/16.0/bin/sdkmanager" ]]; then
55+
# GitHub Actions often has 16.0 explicitly
56+
sdkmanager_bin="$ANDROID_SDK_ROOT/cmdline-tools/16.0/bin/sdkmanager"
5357
else
54-
sdkmanager_bin=$(command -v sdkmanager)
58+
sdkmanager_bin=$(command -v sdkmanager || true)
5559
fi
5660

5761
if [[ -z "$sdkmanager_bin" ]]; then
5862
echo "sdkmanager not found in ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT" >&2
5963
exit 1
6064
fi
6165

62-
info "Updating SDK tools..."
63-
# Update cmdline-tools first to avoid XML parsing errors with newer repos
64-
yes | "$sdkmanager_bin" --licenses >/dev/null || true
65-
"$sdkmanager_bin" --install "cmdline-tools;latest" >/dev/null
66-
67-
# Refresh binary path
68-
sdkmanager_bin="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager"
69-
70-
info "Installing system image..."
71-
yes | "$sdkmanager_bin" --licenses >/dev/null || true
72-
"$sdkmanager_bin" --install "platform-tools" "emulator" "$AVD_PACKAGE" >/dev/null
66+
info "Installing system image using $sdkmanager_bin..."
67+
# Use yes to accept licenses, suppress broken pipe errors if yes continues after sdkmanager exits
68+
# We invoke sdkmanager with --sdk_root to be explicit
69+
yes | "$sdkmanager_bin" --sdk_root="$ANDROID_SDK_ROOT" "platform-tools" "emulator" "$AVD_PACKAGE" >/dev/null || true
7370
}
7471

7572
function create_avd() {
@@ -92,11 +89,16 @@ function start_emulator() {
9289
exit 1
9390
fi
9491
info "Starting emulator $AVD_NAME on port $EMULATOR_PORT"
95-
# Avoid stale instances
96-
if pgrep -f "-avd $AVD_NAME" >/dev/null; then
97-
pkill -9 -f "-avd $AVD_NAME"
92+
93+
# Avoid stale instances safely
94+
if pgrep -f "emulator -avd $AVD_NAME" >/dev/null; then
95+
pkill -9 -f "emulator -avd $AVD_NAME" || true
9896
fi
9997

98+
# Ensure log directory exists
99+
local log_dir="$HOME/.android/avd/$AVD_NAME"
100+
mkdir -p "$log_dir"
101+
100102
# Launch headless emulator
101103
"${emulator_bin}" -avd "$AVD_NAME" \
102104
-port "$EMULATOR_PORT" \
@@ -109,7 +111,7 @@ function start_emulator() {
109111
-camera-front none \
110112
-verbose \
111113
${EMULATOR_FLAGS:-} \
112-
>"$HOME/.android/avd/$AVD_NAME/emulator.log" 2>&1 &
114+
>"$log_dir/emulator.log" 2>&1 &
113115
}
114116

115117
function wait_for_boot() {
@@ -121,12 +123,18 @@ function wait_for_boot() {
121123
local attempts=0
122124
until [[ "$booted" == "1" ]]; do
123125
booted=$(adb shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')
124-
sleep 3
125-
((attempts++))
126-
if (( attempts > 120 )); then
127-
info "Emulator failed to boot"
128-
tail -n 200 "$HOME/.android/avd/$AVD_NAME/emulator.log" || true
129-
exit 1
126+
if [[ "$booted" != "1" ]]; then
127+
sleep 3
128+
((attempts++))
129+
if (( attempts > 120 )); then
130+
info "Emulator failed to boot"
131+
if [[ -f "$HOME/.android/avd/$AVD_NAME/emulator.log" ]]; then
132+
tail -n 200 "$HOME/.android/avd/$AVD_NAME/emulator.log" || true
133+
else
134+
echo "No emulator log found."
135+
fi
136+
exit 1
137+
fi
130138
fi
131139
done
132140
info "Emulator booted"

0 commit comments

Comments
 (0)