Skip to content

Android - Build and test #8731

Android - Build and test

Android - Build and test #8731

Workflow file for this run

---
name: Android - Build and test
on:
pull_request:
paths:
- '**'
- '!.github/workflows/**'
- '.github/workflows/android-app.yml'
- '!audits/**'
- '!ci/**'
- '!dist-assets/**'
- '!docs/**'
- '!graphics/**'
- '!gui/**'
- '!ios/**'
- '!scripts/**'
- '!windows/**'
- '!**/**.md'
schedule:
# At 06:20 UTC every day.
# Notifications for scheduled workflows are sent to the user who last modified the cron
# syntax in the workflow file. If you update this you must have notifications for
# Github Actions enabled, so these don't go unnoticed.
# https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/notifications-for-workflow-runs
- cron: '20 6 * * *'
workflow_dispatch:
inputs:
override_container_image:
description: Override container image
type: string
required: false
run_firebase_tests:
description: Run firebase tests
type: boolean
required: false
# Build if main is updated to ensure up-to-date caches are available
push:
branches: [main]
jobs:
prepare:
name: Prepare
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Use custom container image if specified
if: ${{ github.event.inputs.override_container_image != '' }}
run: echo "inner_container_image=${{ github.event.inputs.override_container_image }}"
>> $GITHUB_ENV
- name: Use default container image and resolve digest
if: ${{ github.event.inputs.override_container_image == '' }}
run: |
echo "inner_container_image=$(cat ./building/android-container-image.txt)" >> $GITHUB_ENV
outputs:
container_image: ${{ env.inner_container_image }}
generate-relay-list:
name: Generate relay list
needs: prepare
runs-on: ubuntu-latest
container:
image: ${{ needs.prepare.outputs.container_image }}
steps:
# Fix for HOME path overridden by GH runners when building in containers, see:
# https://github.com/actions/runner/issues/863
- name: Fix HOME path
run: echo "HOME=/root" >> $GITHUB_ENV
- name: Get date
id: get-date
shell: bash
run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
- name: Cache
uses: actions/cache@v3
id: cache-relay-list
with:
path: build/relays.json
key: relay-list-${{ steps.get-date.outputs.date }}
- name: Checkout repository
if: steps.cache-relay-list.outputs.cache-hit != 'true'
uses: actions/checkout@v3
- name: Generate
if: steps.cache-relay-list.outputs.cache-hit != 'true'
env:
RUSTFLAGS: --deny warnings
run: |
mkdir -p build
cargo run --bin relay_list > build/relays.json
- name: Upload
uses: actions/upload-artifact@v3
with:
name: relay-list
path: build/relays.json
if-no-files-found: error
retention-days: 1
build-native:
name: Build native
needs: prepare
runs-on: ubuntu-latest
container:
image: "${{ needs.prepare.outputs.container_image }}"
strategy:
matrix:
include:
- arch: "x86_64"
abi: "x86_64"
target: "x86_64-linux-android"
- arch: "i686"
abi: "x86"
target: "i686-linux-android"
- arch: "aarch64"
abi: "arm64-v8a"
target: "aarch64-linux-android"
- arch: "armv7"
abi: "armeabi-v7a"
target: "armv7-linux-androideabi"
steps:
# Fix for HOME path overridden by GH runners when building in containers, see:
# https://github.com/actions/runner/issues/863
- name: Fix HOME path
run: echo "HOME=/root" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v3
- name: Calculate native lib cache hash
id: native-lib-cache-hash
shell: bash
run: |
git config --global --add safe.directory $(pwd)
non_android_hash="$(git grep --cached -l '' -- ':!android/' \
| xargs -d '\n' sha1sum \
| sha1sum \
| awk '{print $1}')"
echo "native_lib_hash=$non_android_hash" >> $GITHUB_OUTPUT
- name: Cache native libraries
uses: actions/cache@v3
id: cache-native-libs
env:
cache_hash: ${{ steps.native-lib-cache-hash.outputs.native_lib_hash }}
with:
path: ./android/app/build/extraJni
key: android-native-libs-${{ runner.os }}-${{ matrix.abi }}-${{ env.cache_hash }}
- name: Build native libraries
if: steps.cache-native-libs.outputs.cache-hit != 'true'
env:
RUSTFLAGS: --deny warnings
BUILD_TYPE: debug
run: |
ARCHITECTURES="${{ matrix.abi }}"
UNSTRIPPED_LIB_PATH="$CARGO_TARGET_DIR/${{ matrix.target }}/$BUILD_TYPE/libmullvad_jni.so"
STRIPPED_LIB_PATH="./android/app/build/extraJni/${{ matrix.abi }}/libmullvad_jni.so"
NDK_TOOLCHAIN_STRIP_TOOL="$NDK_TOOLCHAIN_DIR/llvm-strip"
./wireguard/build-wireguard-go.sh --android --no-docker
cargo build --target ${{ matrix.target }} --verbose --package mullvad-jni --features api-override
$NDK_TOOLCHAIN_STRIP_TOOL --strip-debug --strip-unneeded -o "$STRIPPED_LIB_PATH" "$UNSTRIPPED_LIB_PATH"
- name: Upload native libs
uses: actions/upload-artifact@v3
with:
name: native-libs
path: android/app/build/extraJni
if-no-files-found: error
retention-days: 1
build-app:
name: Build app and run unit tests
needs: [prepare, build-native, generate-relay-list]
runs-on: ubuntu-latest
container:
image: ${{ needs.prepare.outputs.container_image }}
steps:
# Fix for HOME path overridden by GH runners when building in containers, see:
# https://github.com/actions/runner/issues/863
- name: Fix HOME path
run: echo "HOME=/root" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: native-libs
path: android/app/build/extraJni
- uses: actions/download-artifact@v3
with:
name: relay-list
path: build
- name: Build Android app
uses: burrunan/gradle-cache-action@v1
with:
job-id: jdk17
arguments: assembleOssProdDebug
gradle-version: wrapper
build-root-directory: android
- name: Run unit tests
uses: burrunan/gradle-cache-action@v1
with:
job-id: jdk17
arguments: |
testDebugUnitTest -x :test:arch:testDebugUnitTest
:app:testOssProdDebugUnitTest
:service:testOssProdDebugUnitTest
gradle-version: wrapper
build-root-directory: android
execution-only-caches: true
- name: Run arch tests
uses: burrunan/gradle-cache-action@v1
with:
job-id: jdk17
arguments: :test:arch:test --rerun-tasks
gradle-version: wrapper
build-root-directory: android
execution-only-caches: true
# Running the AGP lint here rather than in the separate lint workflow
# (android-kotlin-format-check.yml) since it's easier to make use of the running container,
# cache and previously ran tasks.
- name: Run AGP lint
uses: burrunan/gradle-cache-action@v1
with:
job-id: jdk17
arguments: lint
gradle-version: wrapper
build-root-directory: android
execution-only-caches: true
- name: Assemble instrumented test apk (app)
uses: burrunan/gradle-cache-action@v1
with:
job-id: jdk17
arguments: assembleOssProdAndroidTest
gradle-version: wrapper
build-root-directory: android
execution-only-caches: true
- name: Assemble instrumented test apk (mockapi)
uses: burrunan/gradle-cache-action@v1
with:
job-id: jdk17
arguments: :test:mockapi:assemble
gradle-version: wrapper
build-root-directory: android
execution-only-caches: true
- name: Upload apks
uses: actions/upload-artifact@v3
with:
name: apks
path: |
android/app/build/outputs/apk
android/test/mockapi/build/outputs/apk
if-no-files-found: error
retention-days: 1
instrumented-tests:
name: Run instrumented tests
runs-on: [self-hosted, android-emulator]
timeout-minutes: 30
needs: [build-app]
strategy:
fail-fast: false
matrix:
test-type: [app, mockapi]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: apks
path: android
- name: Run instrumented test script
shell: bash -ieo pipefail {0}
env:
AUTO_FETCH_TEST_HELPER_APKS: true
run: |
./android/scripts/run-instrumented-tests.sh ${{ matrix.test-type }}
- name: Upload instrumentation report (${{ matrix.test-type }})
uses: actions/upload-artifact@v3
if: always()
with:
name: ${{ matrix.test-type }}-instrumentation-report
path: /tmp/mullvad-${{ matrix.test-type }}-instrumentation-report
if-no-files-found: ignore
retention-days: 1
instrumented-firebase-tests:
name: Run instrumented firebase tests
if: github.event_name == 'schedule' || github.event.inputs.run_firebase_tests == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
needs: [build-app]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: apks
path: android
- name: Run tests on Firebase Test Lab
uses: asadmansr/Firebase-Test-Lab-Action@v1.0
env:
SERVICE_ACCOUNT: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
with:
arg-spec: 'android/test/firebase-test-lab.yml:default'