Skip to content

Merge pull request #5 from iamjosephmj/feat/app-bundle-integrity #16

Merge pull request #5 from iamjosephmj/feat/app-bundle-integrity

Merge pull request #5 from iamjosephmj/feat/app-bundle-integrity #16

# Instrumented smoke tests for the :deviceintelligence SDK.
#
# Runs the 11-test suite under :deviceintelligence:src/androidTest on
# three API levels in parallel — 28 (minSdk floor), 33 (modal target
# SDK), 35 (latest stable + 16 KB page-size path) — each on its own
# AGP-managed emulator inside a GitHub Actions runner. Linux runners
# gained KVM/nested-virt support in mid-2024, which is what makes
# managed devices viable without a third-party emulator action.
#
# Image-source choice per API:
# - API 33 / 35: aosp_atd (Android Test Device — headless, ~250 MB,
# boots in seconds, purpose-built for CI smoke runs).
# - API 28: aosp default image (~700 MB, ~30 sec boot). ATD images
# only exist from API 30+, so the floor entry uses the standard
# AOSP system image.
#
# Local invocation mirror (single device):
# ./gradlew :deviceintelligence:api33DebugAndroidTest
# Full matrix:
# ./gradlew :deviceintelligence:allDevicesDebugAndroidTest
name: Instrumented tests
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: instrumented-tests-${{ github.ref }}
cancel-in-progress: true
jobs:
smoke:
name: SDK smoke (API ${{ matrix.api-level }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
# Independent per-API insight. A flake or genuine regression on
# one API level should not cancel the others — knowing it only
# repros on API 28 (or only on 35) is exactly the actionable
# signal this matrix exists to surface.
fail-fast: false
matrix:
include:
- api-level: 28
system-image: "system-images;android-28;default;x86_64"
gradle-task: api28DebugAndroidTest
- api-level: 33
system-image: "system-images;android-33;aosp_atd;x86_64"
gradle-task: api33DebugAndroidTest
- api-level: 35
system-image: "system-images;android-35;aosp_atd;x86_64"
gradle-task: api35DebugAndroidTest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
# KVM is the gate for AGP managed devices on Linux. Without it
# the emulator falls back to TCG (software CPU) which times out
# on CI. The runner ships kvm-ok / kvm modules; this step ensures
# the user namespace has access.
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Install Android SDK (matches AGP / CMake / NDK in module build.gradle.kts)
shell: bash
run: |
set -eu
export ANDROID_SDK_ROOT="$HOME/android-sdk"
export ANDROID_HOME="$ANDROID_SDK_ROOT"
mkdir -p "$ANDROID_SDK_ROOT/cmdline-tools"
curl -sSLo /tmp/cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
unzip -qo /tmp/cmdline-tools.zip -d "$ANDROID_SDK_ROOT/cmdline-tools"
mv "$ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools" "$ANDROID_SDK_ROOT/cmdline-tools/latest"
export PATH="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/emulator:$PATH"
mkdir -p "$ANDROID_SDK_ROOT/licenses"
printf '\n24333f8a63b6825ea9c5514f748d145ef07021\n' > "$ANDROID_SDK_ROOT/licenses/android-sdk-license"
printf '\n84831b9409646a918e30573bab4c9c91346d8abd\n' > "$ANDROID_SDK_ROOT/licenses/android-sdk-preview-license"
# GitHub Actions runs `bash -eo pipefail`, so a `yes | sdkmanager`
# pipeline fails the step when sdkmanager finishes and closes
# stdin: `yes` then gets SIGPIPE on its next write and exits
# non-zero, which under pipefail propagates as a pipeline
# failure even though sdkmanager itself succeeded. Drop
# pipefail just for the license / install pipes; restore it
# immediately after so the rest of the script keeps strict
# pipe semantics.
set +o pipefail
yes | sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --licenses
# `yes |` on the install command too: the system image (ATD
# or default) may carry an additional vendor evaluation
# license that `--licenses` does NOT pre-accept (it's
# prompted at install-time, not registered as an SDK license
# hash).
yes | sdkmanager --sdk_root="$ANDROID_SDK_ROOT" --install \
"platform-tools" "emulator" \
"platforms;android-36" "build-tools;36.0.0" \
"ndk;27.0.12077973" "cmake;3.22.1" \
"${{ matrix.system-image }}"
set -o pipefail
{
echo "ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
echo "ANDROID_HOME=$ANDROID_SDK_ROOT"
echo "PATH=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/emulator:$PATH"
} >> "$GITHUB_ENV"
- name: Run :deviceintelligence:${{ matrix.gradle-task }}
run: |
chmod +x ./gradlew
./gradlew :deviceintelligence:${{ matrix.gradle-task }} \
--no-daemon \
--stacktrace \
-Pandroid.testoptions.manageddevices.emulator.gpu=swiftshader_indirect
- name: Upload test report (always)
if: always()
uses: actions/upload-artifact@v7
with:
name: instrumented-test-report-api${{ matrix.api-level }}
path: |
deviceintelligence/build/reports/androidTests/managedDevice/**
deviceintelligence/build/outputs/androidTest-results/managedDevice/**
if-no-files-found: ignore
retention-days: 7