Skip to content

Commit eb3dac9

Browse files
committed
Poll emulator with adb shell getprop sys.boot_completed and manually handle timeout
1 parent bf32aa7 commit eb3dac9

File tree

2 files changed

+194
-3
lines changed

2 files changed

+194
-3
lines changed

.github/workflows/android_sdk.yml

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# This workflow can be added to a branch of swift-docker
2+
# in order to test building the chages in a fork:
3+
#
4+
# ln ../android_sdk.yml .github/workflows/android_sdk.yml
5+
#
6+
# Note that the workflow should be removed before filing a PR
7+
# so it is not submitted to the upstream swiftlang/swift-docker repo
8+
name: Build Android SDK
9+
on: [push, pull_request]
10+
11+
jobs:
12+
build:
13+
name: Android ${{ matrix.build-type }} ${{ matrix.swift-version }} ${{ matrix.arch }} ${{ matrix.runner }} (compiler=${{ matrix.build-compiler }})
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
include:
18+
- runner: 'ubuntu-24.04'
19+
swift-version: 'scheme:main'
20+
build-type: 'docker'
21+
- runner: 'ubuntu-24.04'
22+
swift-version: 'scheme:release/6.2'
23+
build-type: 'docker'
24+
- runner: 'ubuntu-24.04'
25+
swift-version: 'tag:swift-6.2.3-RELEASE'
26+
build-type: 'docker'
27+
- runner: 'ubuntu-24.04'
28+
swift-version: 'tag:swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-24-a'
29+
build-type: 'docker'
30+
runs-on: ${{ matrix.runner }}
31+
# 16 hour timeout
32+
timeout-minutes: 960
33+
steps:
34+
- name: Free Disk Space
35+
if: ${{ matrix.runner != 'self-hosted' }}
36+
run: |
37+
df -h
38+
# brings available space from 25G to 32G
39+
# otherwise we sometimes run out of space during the build
40+
sudo rm -rf /opt/microsoft /opt/google /opt/az /usr/share/miniconda /usr/share/az* /usr/share/glade* /usr/local/share/chromium /usr/local/share/powershell /usr/share/dotnet /opt/ghc /opt/hostedtoolcache /usr/local/graalvm/ /usr/local/.ghcup/ /usr/local/lib/node_modules /usr/local/share/boost
41+
sudo docker image prune --all --force
42+
sudo docker builder prune -a
43+
df -h
44+
- name: Setup
45+
id: config
46+
run: |
47+
# these variabes are used by build-docker and build-local
48+
# to determine which Swift version to build for
49+
echo "SWIFT_VERSION=${{ matrix.swift-version }}" >> $GITHUB_ENV
50+
# pass the build-compiler matrix through to the build script
51+
echo "BUILD_COMPILER=${{ matrix.build-compiler }}" >> $GITHUB_ENV
52+
echo "TARGET_ARCHS=${{ matrix.arch }}" >> $GITHUB_ENV
53+
echo "WORKDIR=${{ runner.temp }}/swift-android-sdk" >> $GITHUB_ENV
54+
- name: Checkout repository
55+
uses: actions/checkout@v4
56+
- name: Build Android SDK (Local)
57+
if: ${{ matrix.build-type == 'local' }}
58+
working-directory: swift-ci/sdks/android
59+
run: |
60+
sudo apt install -q patchelf build-essential cmake ninja-build python3 golang git gnupg2 libcurl4-openssl-dev libedit-dev libicu-dev libncurses5-dev libpython3-dev libsqlite3-dev libxml2-dev rsync uuid-dev uuid-runtime tzdata curl unzip
61+
./build-local ${SWIFT_VERSION} ${WORKDIR}
62+
- name: Build Android SDK (Docker)
63+
if: ${{ matrix.build-type == 'docker' }}
64+
working-directory: swift-ci/sdks/android
65+
run: |
66+
./build-docker ${SWIFT_VERSION} ${WORKDIR}
67+
- name: Install Host Toolchain
68+
if: ${{ matrix.build-type == 'docker' }}
69+
working-directory: swift-ci/sdks/android
70+
run: |
71+
# when building in a Docker container, we don't have a local host toolchain,
72+
# but we need one in order to run the SDK validation tests, so we install it now
73+
HOST_OS=ubuntu$(lsb_release -sr)
74+
source ./scripts/toolchain-vars.sh
75+
mkdir -p ${WORKDIR}/host-toolchain
76+
./scripts/install-swift.sh ${WORKDIR}/host-toolchain/$SWIFT_BASE/usr
77+
ls ${WORKDIR}/host-toolchain
78+
${WORKDIR}/host-toolchain/*/usr/bin/swift --version
79+
- name: Get artifact info
80+
id: info
81+
shell: bash
82+
run: |
83+
set -ex
84+
SWIFT_ROOT=$(dirname ${WORKDIR}/host-toolchain/*/usr)
85+
echo "swift-root=${SWIFT_ROOT}" >> $GITHUB_OUTPUT
86+
echo "swift-path=${SWIFT_ROOT}/usr/bin/swift" >> $GITHUB_OUTPUT
87+
88+
ARTIFACT_PATH=$(realpath ${WORKDIR}/products/*.artifactbundle.tar.gz)
89+
echo "artifact-path=${ARTIFACT_PATH}" >> $GITHUB_OUTPUT
90+
echo "sdk-id=x86_64-unknown-linux-android28" >> $GITHUB_OUTPUT
91+
92+
ARTIFACT_EXT=".artifactbundle.tar.gz"
93+
ARTIFACT_NAME="$(basename ${ARTIFACT_PATH} ${ARTIFACT_EXT})"
94+
# depending on whether we are building locally or in a container, add a maker to the name
95+
if [[ "${{ matrix.build-type }}" == 'local' ]]; then
96+
ARTIFACT_NAME="${ARTIFACT_NAME}-local"
97+
fi
98+
if [[ "${{ matrix.build-compiler }}" == '1' ]]; then
99+
ARTIFACT_NAME="${ARTIFACT_NAME}-hostbuild"
100+
fi
101+
# artifacts need a unique name so we suffix with the matrix arch(s)
102+
if [[ ! -z "${{ matrix.arch }}" ]]; then
103+
ARTIFACT_NAME="${ARTIFACT_NAME}-$(echo ${{ matrix.arch }} | tr ',' '-')"
104+
fi
105+
ARTIFACT_NAME="${ARTIFACT_NAME}${ARTIFACT_EXT}"
106+
107+
# There is no way to prevent even a single-file artifact from being zipped:
108+
# https://github.com/actions/upload-artifact?tab=readme-ov-file#zip-archives
109+
# so the actual artifact download will look like:
110+
# swift-6.1-RELEASE_android-0.1-x86_64.artifactbundle.tar.gz.zip
111+
echo "artifact-name=${ARTIFACT_NAME}" >> $GITHUB_OUTPUT
112+
- name: Upload SDK artifactbundle
113+
uses: actions/upload-artifact@v4
114+
with:
115+
compression-level: 0
116+
name: ${{ steps.info.outputs.artifact-name }}
117+
path: ${{ steps.info.outputs.artifact-path }}
118+
- name: Cleanup
119+
if: ${{ matrix.runner != 'self-hosted' }}
120+
run: |
121+
# need to free up some space or else when installing we get: No space left on device
122+
df -h
123+
rm -rf ${WORKDIR}/{build,source}
124+
sudo docker image prune --all --force
125+
sudo docker builder prune -a
126+
df -h
127+
- name: Install artifactbundle
128+
if: ${{ matrix.runner != 'self-hosted' }}
129+
shell: bash
130+
run: |
131+
set -ex
132+
${{ steps.info.outputs.swift-path }} sdk install ${{ steps.info.outputs.artifact-path }}
133+
${{ steps.info.outputs.swift-path }} sdk configure --show-configuration $(${{ steps.info.outputs.swift-path }} sdk list | head -n 1) ${{ steps.info.outputs.sdk-id }}
134+
# recent releases require that ANDROID_NDK_ROOT *not* be set
135+
# see https://github.com/swiftlang/swift-driver/pull/1879
136+
echo "ANDROID_NDK_ROOT=" >> $GITHUB_ENV
137+
138+
- name: Create Demo Project
139+
if: ${{ matrix.runner != 'self-hosted' }}
140+
run: |
141+
cd ${{ runner.temp }}
142+
mkdir DemoProject
143+
cd DemoProject
144+
${{ steps.info.outputs.swift-path }} --version
145+
${{ steps.info.outputs.swift-path }} package init
146+
echo 'import Foundation' >> Sources/DemoProject/DemoProject.swift
147+
echo 'import FoundationEssentials' >> Sources/DemoProject/DemoProject.swift
148+
echo 'import FoundationXML' >> Sources/DemoProject/DemoProject.swift
149+
echo 'import FoundationNetworking' >> Sources/DemoProject/DemoProject.swift
150+
echo 'import Dispatch' >> Sources/DemoProject/DemoProject.swift
151+
echo 'import Android' >> Sources/DemoProject/DemoProject.swift
152+
- name: Test Demo Project on Android
153+
uses: skiptools/swift-android-action@main
154+
if: ${{ matrix.runner != 'self-hosted' }}
155+
with:
156+
# only test for the complete arch SDK build to speed up CI
157+
#run-tests: ${{ matrix.arch == '' }}
158+
package-path: ${{ runner.temp }}/DemoProject
159+
installed-sdk: ${{ steps.info.outputs.sdk-id }}
160+
installed-swift: ${{ steps.info.outputs.swift-root }}
161+
162+
- name: Checkout swift-algorithms
163+
if: ${{ matrix.runner != 'self-hosted' }}
164+
uses: actions/checkout@v4
165+
with:
166+
repository: apple/swift-algorithms
167+
path: swift-algorithms
168+
- name: Test swift-algorithms
169+
if: ${{ matrix.runner != 'self-hosted' }}
170+
uses: skiptools/swift-android-action@main
171+
with:
172+
package-path: swift-algorithms
173+
installed-sdk: ${{ steps.info.outputs.sdk-id }}
174+
installed-swift: ${{ steps.info.outputs.swift-root }}

.github/workflows/scripts/android/android-emulator-tests.sh

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,26 @@ nohup emulator -no-metrics -partition-size 1024 -memory 4096 -wipe-data -no-wind
9999
sleep 20
100100

101101
log "Waiting for Android emulator startup"
102-
adb start-server
103-
sleep 5
104-
timeout "${ANDROID_EMULATOR_TIMEOUT}" adb wait-for-any-device
102+
EMULATOR_CHECK_SECONDS_ELAPSED=0
103+
EMULATOR_CHECK_INTERVAL=5 # Seconds between status checks
104+
while true; do
105+
# Check if the boot is completed
106+
# 'adb shell getprop sys.boot_completed' returns 1 when done
107+
BOOT_STATUS=$(adb shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')
108+
109+
if [ "$BOOT_STATUS" == "1" ]; then
110+
log "Emulator is ready"
111+
break;
112+
fi
113+
114+
if [ "$EMULATOR_CHECK_SECONDS_ELAPSED" -ge "$ANDROID_EMULATOR_TIMEOUT" ]; then
115+
log "Timeout reached ($ANDROID_EMULATOR_TIMEOUT seconds). Aborting."
116+
exit 1
117+
fi
118+
119+
sleep "$EMULATOR_CHECK_INTERVAL"
120+
((EMULATOR_CHECK_SECONDS_ELAPSED+=EMULATOR_CHECK_INTERVAL))
121+
done
105122

106123
log "Prepare Swift test package"
107124
# create a staging folder where we copy the test executable

0 commit comments

Comments
 (0)