Skip to content

Commit 98964d6

Browse files
committed
ci(android): revert to emulator-runner action
1 parent 8214a2b commit 98964d6

1 file changed

Lines changed: 85 additions & 131 deletions

File tree

Lines changed: 85 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: 'Appium E2E - Local Android'
2-
description: 'Boot an Android emulator, start Appium, and run the shared OneSignal Appium E2E tests against a local .apk. Uses raw sdkmanager/avdmanager/emulator commands so each phase is a separate, cacheable, debuggable step.'
2+
description: 'Boot an Android emulator via reactivecircus/android-emulator-runner, start Appium, and run the shared OneSignal Appium E2E tests against a local .apk.'
33

44
inputs:
55
app-path:
@@ -34,7 +34,7 @@ inputs:
3434
description: 'Port Appium listens on'
3535
required: false
3636
default: '4723'
37-
boot-timeout-seconds:
37+
emulator-boot-timeout:
3838
description: 'Max seconds to wait for emulator boot completion'
3939
required: false
4040
default: '900'
@@ -45,172 +45,126 @@ runs:
4545
- name: Setup Bun
4646
uses: oven-sh/setup-bun@v2
4747

48-
- name: Resolve paths
48+
- name: Resolve appium dir
4949
shell: bash
5050
run: |
5151
APPIUM_DIR=$(cd "${{ github.action_path }}/../../../appium" && pwd -P)
5252
echo "APPIUM_DIR=$APPIUM_DIR" >> "$GITHUB_ENV"
5353
54-
if [ -z "${ANDROID_HOME:-}" ]; then
55-
if [ -n "${ANDROID_SDK_ROOT:-}" ]; then
56-
ANDROID_HOME="$ANDROID_SDK_ROOT"
57-
else
58-
ANDROID_HOME="/usr/local/lib/android/sdk"
59-
fi
60-
echo "ANDROID_HOME=$ANDROID_HOME" >> "$GITHUB_ENV"
61-
fi
62-
63-
CMDLINE_BIN=$(ls -d "$ANDROID_HOME"/cmdline-tools/*/bin 2>/dev/null | tail -1 || true)
64-
if [ -z "$CMDLINE_BIN" ]; then
65-
echo "::error::No Android cmdline-tools found under $ANDROID_HOME/cmdline-tools/"
66-
ls -la "$ANDROID_HOME/cmdline-tools" 2>/dev/null || true
67-
exit 1
68-
fi
69-
echo "$CMDLINE_BIN" >> "$GITHUB_PATH"
70-
echo "$ANDROID_HOME/emulator" >> "$GITHUB_PATH"
71-
echo "$ANDROID_HOME/platform-tools" >> "$GITHUB_PATH"
72-
echo "Using cmdline-tools at: $CMDLINE_BIN"
73-
7454
- name: Enable KVM
7555
shell: bash
7656
run: |
7757
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
7858
sudo udevadm control --reload-rules
7959
sudo udevadm trigger --name-match=kvm
8060
81-
- name: Cache Android system image
61+
- name: AVD cache
8262
uses: actions/cache@v4
63+
id: avd-cache
8364
with:
84-
path: ${{ env.ANDROID_HOME }}/system-images/android-${{ inputs.api-level }}/${{ inputs.target }}/${{ inputs.arch }}
85-
key: android-sysimg-${{ inputs.api-level }}-${{ inputs.target }}-${{ inputs.arch }}
86-
87-
- name: Install SDK packages
88-
shell: bash
89-
env:
90-
API_LEVEL: ${{ inputs.api-level }}
91-
TARGET: ${{ inputs.target }}
92-
ARCH: ${{ inputs.arch }}
93-
run: |
94-
yes | sdkmanager --licenses >/dev/null 2>&1 || true
95-
sdkmanager --install \
96-
"platforms;android-$API_LEVEL" \
97-
"system-images;android-$API_LEVEL;$TARGET;$ARCH" \
98-
"emulator" \
99-
"platform-tools" > /tmp/sdkmanager.log 2>&1 || {
100-
echo "::error::sdkmanager install failed"
101-
tail -40 /tmp/sdkmanager.log
102-
exit 1
103-
}
104-
105-
- name: Create AVD
106-
shell: bash
107-
env:
108-
API_LEVEL: ${{ inputs.api-level }}
109-
TARGET: ${{ inputs.target }}
110-
ARCH: ${{ inputs.arch }}
111-
PROFILE: ${{ inputs.profile }}
112-
run: |
113-
echo "no" | avdmanager create avd \
114-
-n test \
115-
-k "system-images;android-$API_LEVEL;$TARGET;$ARCH" \
116-
-d "$PROFILE" \
117-
--force
65+
path: |
66+
~/.android/avd/*
67+
~/.android/adb*
68+
key: avd-${{ inputs.api-level }}-${{ inputs.target }}-${{ inputs.arch }}-${{ inputs.profile }}
11869

119-
- name: Boot emulator
70+
- name: Create AVD snapshot
71+
if: steps.avd-cache.outputs.cache-hit != 'true'
72+
uses: reactivecircus/android-emulator-runner@v2
73+
with:
74+
api-level: ${{ inputs.api-level }}
75+
target: ${{ inputs.target }}
76+
arch: ${{ inputs.arch }}
77+
profile: ${{ inputs.profile }}
78+
ram-size: 4096M
79+
heap-size: 1024M
80+
disable-animations: false
81+
force-avd-creation: false
82+
emulator-options: -no-window -gpu swiftshader_indirect -no-boot-anim -no-snapshot-save
83+
emulator-boot-timeout: ${{ inputs.emulator-boot-timeout }}
84+
script: echo "Generated AVD snapshot for caching"
85+
86+
# reactivecircus/android-emulator-runner@v2 executes `script:` line-by-line
87+
# via separate `sh -c` calls, which breaks multi-line constructs and state
88+
# (e.g. APPIUM_PID=$! ends up in a throwaway shell). We stage the full test
89+
# flow to a file here and invoke it from the action as a single line.
90+
- name: Stage Appium test script
12091
shell: bash
121-
env:
122-
BOOT_TIMEOUT: ${{ inputs.boot-timeout-seconds }}
12392
run: |
124-
nohup "$ANDROID_HOME/emulator/emulator" \
125-
-avd test \
126-
-no-window -no-audio -no-boot-anim \
127-
-gpu swiftshader_indirect \
128-
-no-snapshot-save \
129-
-memory 4096 \
130-
> emulator.log 2>&1 &
131-
echo "EMULATOR_PID=$!" >> "$GITHUB_ENV"
132-
133-
adb wait-for-device
134-
135-
echo "Waiting for boot completion (timeout ${BOOT_TIMEOUT}s)..."
136-
deadline=$(( $(date +%s) + BOOT_TIMEOUT ))
137-
while :; do
138-
boot=$(adb shell getprop sys.boot_completed 2>/dev/null | tr -d '\r' || true)
139-
if [ "$boot" = "1" ]; then
140-
break
141-
fi
142-
if [ "$(date +%s)" -ge "$deadline" ]; then
143-
echo "::error::Emulator boot timed out"
144-
echo "--- emulator.log (last 100 lines) ---"
145-
tail -100 emulator.log || true
146-
exit 1
147-
fi
148-
sleep 2
149-
done
150-
adb shell input keyevent 82 >/dev/null 2>&1 || true
151-
echo "Emulator booted"
93+
cat > "$RUNNER_TEMP/appium-android.sh" <<'SCRIPT_EOF'
94+
#!/usr/bin/env bash
95+
set -euo pipefail
15296
153-
- name: Install Appium and driver
154-
shell: bash
155-
run: |
97+
echo "::group::Install Appium + uiautomator2 driver"
15698
bun add -g appium@3
15799
appium driver install uiautomator2
100+
echo "::endgroup::"
158101
159-
- name: Start Appium
160-
shell: bash
161-
env:
162-
APPIUM_PORT: ${{ inputs.appium-port }}
163-
run: |
164-
appium --port "$APPIUM_PORT" --log-level error > appium.log 2>&1 &
165-
echo "APPIUM_PID=$!" >> "$GITHUB_ENV"
166-
i=0
167-
while [ "$i" -lt 30 ]; do
102+
echo "::group::Start Appium"
103+
appium --port "$APPIUM_PORT" --log-level error > "$GITHUB_WORKSPACE/appium.log" 2>&1 &
104+
APPIUM_PID=$!
105+
echo "APPIUM_PID=$APPIUM_PID"
106+
107+
for _ in $(seq 1 60); do
168108
if curl -sf "http://localhost:$APPIUM_PORT/status" >/dev/null; then
169-
echo "Appium ready"
170-
exit 0
109+
break
171110
fi
172111
sleep 1
173-
i=$((i + 1))
174112
done
175-
echo "::error::Appium did not become ready on port $APPIUM_PORT"
176-
cat appium.log || true
177-
exit 1
113+
if ! curl -sf "http://localhost:$APPIUM_PORT/status" >/dev/null; then
114+
echo "::error::Appium did not become ready on port $APPIUM_PORT"
115+
tail -100 "$GITHUB_WORKSPACE/appium.log" || true
116+
exit 1
117+
fi
118+
echo "Appium ready"
119+
echo "::endgroup::"
178120
179-
- name: Install test dependencies
180-
shell: bash
181-
working-directory: ${{ env.APPIUM_DIR }}
182-
run: bun install --frozen-lockfile
121+
echo "::group::Install test dependencies"
122+
cd "$APPIUM_DIR"
123+
bun install --frozen-lockfile
124+
echo "::endgroup::"
125+
126+
echo "::group::Run WDIO tests"
127+
set +e
128+
bunx wdio run wdio.android.conf.ts
129+
WDIO_EXIT=$?
130+
set -e
131+
echo "::endgroup::"
132+
133+
echo "::group::Stop Appium"
134+
kill "$APPIUM_PID" 2>/dev/null || true
135+
echo "::endgroup::"
136+
137+
exit "$WDIO_EXIT"
138+
SCRIPT_EOF
139+
chmod +x "$RUNNER_TEMP/appium-android.sh"
183140
184141
- name: Run Appium tests
185-
shell: bash
186-
working-directory: ${{ env.APPIUM_DIR }}
142+
uses: reactivecircus/android-emulator-runner@v2
187143
env:
188-
SDK_TYPE: ${{ inputs.sdk-type }}
189-
PLATFORM: android
144+
APPIUM_PORT: ${{ inputs.appium-port }}
190145
APP_PATH: ${{ inputs.app-path }}
146+
SDK_TYPE: ${{ inputs.sdk-type }}
191147
ONESIGNAL_APP_ID: ${{ inputs.onesignal-app-id }}
192148
ONESIGNAL_API_KEY: ${{ inputs.onesignal-api-key }}
193-
run: bunx wdio run wdio.android.conf.ts
194-
195-
- name: Shut down emulator and Appium
196-
if: always()
197-
shell: bash
198-
run: |
199-
adb emu kill 2>/dev/null || true
200-
if [ -n "${APPIUM_PID:-}" ]; then
201-
kill "$APPIUM_PID" 2>/dev/null || true
202-
fi
203-
if [ -n "${EMULATOR_PID:-}" ]; then
204-
kill "$EMULATOR_PID" 2>/dev/null || true
205-
fi
206-
207-
- name: Upload Appium + emulator logs
149+
with:
150+
api-level: ${{ inputs.api-level }}
151+
target: ${{ inputs.target }}
152+
arch: ${{ inputs.arch }}
153+
profile: ${{ inputs.profile }}
154+
ram-size: 4096M
155+
heap-size: 1024M
156+
disable-animations: true
157+
force-avd-creation: false
158+
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -no-boot-anim
159+
emulator-boot-timeout: ${{ inputs.emulator-boot-timeout }}
160+
script: bash "$RUNNER_TEMP/appium-android.sh"
161+
162+
- name: Upload Appium + test results
208163
if: always()
209164
uses: actions/upload-artifact@v5
210165
with:
211166
name: appium-local-android-${{ inputs.sdk-type }}
212167
path: |
213168
${{ env.APPIUM_DIR }}/results/
214-
${{ github.workspace }}/emulator.log
215169
${{ github.workspace }}/appium.log
216170
if-no-files-found: ignore

0 commit comments

Comments
 (0)