summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2025-10-16 12:16:54 +0200
committerAlbin <albin@mullvad.net>2025-10-17 10:57:37 +0200
commit8c0fb6ca90c29a455947266cf2fe170d900ef407 (patch)
tree2ebf7fba72c51a0ea200a6fa97bce6c4a51e1004
parent26fd91ac28ad810d97520313654325a57ff4ae80 (diff)
downloadmullvadvpn-8c0fb6ca90c29a455947266cf2fe170d900ef407.tar.xz
mullvadvpn-8c0fb6ca90c29a455947266cf2fe170d900ef407.zip
Migrate android build to self-hosted runner
-rw-r--r--.github/workflows/android-app.yml270
1 files changed, 33 insertions, 237 deletions
diff --git a/.github/workflows/android-app.yml b/.github/workflows/android-app.yml
index ea672c6bd9..774026f38b 100644
--- a/.github/workflows/android-app.yml
+++ b/.github/workflows/android-app.yml
@@ -66,6 +66,10 @@ on:
default: 'stagemole'
required: true
type: string
+ clean:
+ description: Clean before building.
+ type: boolean
+ required: false
# Build if main is updated to ensure up-to-date caches are available
push:
branches: [main]
@@ -111,78 +115,41 @@ jobs:
E2E_TEST_INFRA_FLAVOR: ${{ env.INNER_E2E_TEST_INFRA_FLAVOR }}
E2E_TEST_REPEAT: ${{ env.INNER_E2E_TEST_REPEAT }}
- build-native:
- name: Build native # Used by wait for jobs.
- needs: prepare
- runs-on: ubuntu-latest
- container:
- image: "${{ needs.prepare.outputs.container_image }}"
- strategy:
- matrix:
- include:
- - abi: "x86_64"
- task-variant: "X86_64"
- - abi: "x86"
- task-variant: "X86"
- - abi: "arm64-v8a"
- task-variant: "Arm64"
- - abi: "armeabi-v7a"
- task-variant: "Arm"
+ build-app:
+ name: Build app
+ needs: [prepare]
+ runs-on: app-gh-build
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@v4
- with:
- submodules: true
- - name: Checkout wireguard-go-rs recursively
+ - name: Fetch submodules
run: |
- git config --global --add safe.directory '*'
+ git submodule update --init android/rust-android-gradle-plugin
git submodule update --init wireguard-go-rs/libwg/wireguard-go
- - 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@v4
- id: cache-native-libs
- env:
- cache_hash: ${{ steps.native-lib-cache-hash.outputs.native_lib_hash }}
- with:
- path: ./android/app/build/rustJniLibs/android
- key: android-native-libs-${{ runner.os }}-${{ matrix.abi }}-${{ env.cache_hash }}
+ - name: Ensure correct container image is used
+ run: echo "${{ needs.prepare.outputs.container_image }}" > ./building/android-container-image.txt
- - name: Build native libraries
- if: steps.cache-native-libs.outputs.cache-hit != 'true'
- uses: burrunan/gradle-cache-action@v3
- with:
- job-id: jdk17
- arguments: cargoBuild${{ matrix.task-variant }}
- gradle-version: wrapper
- build-root-directory: android
- execution-only-caches: false
- # Disable if logs are hard to follow.
- concurrent: true
- read-only: ${{ github.ref != 'refs/heads/main' }}
+ - name: Clean gradle
+ if: github.event.inputs.clean == 'true'
+ run: >
+ ./building/container-run.sh android android/gradlew -p android --console plain
+ clean
+ - name: Build apks
+ run: >
+ ./building/container-run.sh android android/gradlew -p android --console plain
+ :app:assembleOssProdDebug
+ assembleOssProdAndroidTest
+ :test:mockapi:assemble
+ :test:e2e:assemble
- - name: Upload native libs
+ - name: Upload apks
uses: actions/upload-artifact@v4
with:
- name: native-libs-${{ matrix.abi }}
- path: android/app/build/rustJniLibs/android
+ name: apks
+ path: android/**/*.apk
if-no-files-found: error
retention-days: 7
@@ -229,165 +196,10 @@ jobs:
concurrent: true
read-only: ${{ github.ref != 'refs/heads/main' }}
- build-app:
- name: Build app
- 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: Checkout repository
- uses: actions/checkout@v4
- with:
- submodules: true
-
- - name: Prepare dummy debug keystore
- env:
- KEYSTORE: ${{ vars.ANDROID_DUMMY_DEBUG_KEYSTORE }}
- run: |
- echo "$KEYSTORE" | tr -d '\n\r' | base64 -d > /root/.android/debug.keystore
-
- - name: Compile app
- uses: burrunan/gradle-cache-action@v3
- with:
- job-id: jdk17
- arguments: |
- compileOssProdDebugKotlin
- -x cargoBuild
- gradle-version: wrapper
- build-root-directory: android
- execution-only-caches: false
- # Disable if logs are hard to follow.
- concurrent: true
- read-only: ${{ github.ref != 'refs/heads/main' }}
-
- - name: Wait for other jobs (native, relay list)
- uses: kachick/wait-other-jobs@v3.8.1
- with:
- wait-seconds-before-first-polling: '0'
- wait-list: |
- [
- {
- "workflowFile": "android-app.yml",
- "jobMatchMode": "prefix",
- "jobName": "Build native"
- }
- ]
-
- - uses: actions/download-artifact@v4
- with:
- pattern: native-libs-*
- path: android/app/build/rustJniLibs/android
- merge-multiple: true
-
- - name: Build app
- uses: burrunan/gradle-cache-action@v3
- with:
- job-id: jdk17
- arguments: |
- assembleOssProdDebug
- -x cargoBuild
- gradle-version: wrapper
- build-root-directory: android
- execution-only-caches: true
- # Disable if logs are hard to follow.
- concurrent: true
- read-only: ${{ github.ref != 'refs/heads/main' }}
-
- - name: Build stagemole app
- uses: burrunan/gradle-cache-action@v3
- if: >
- (needs.prepare.outputs.E2E_TEST_REPEAT != '0' &&
- needs.prepare.outputs.E2E_TEST_INFRA_FLAVOR == 'stagemole') ||
- github.event.inputs.run_firebase_tests == 'true'
- with:
- job-id: jdk17
- arguments: |
- assemblePlayStagemoleDebug
- -x cargoBuild
- gradle-version: wrapper
- build-root-directory: android
- execution-only-caches: true
- # Disable if logs are hard to follow.
- concurrent: true
- read-only: ${{ github.ref != 'refs/heads/main' }}
-
- - name: Upload apks
- uses: actions/upload-artifact@v4
- with:
- name: apks
- path: android/app/build/outputs/apk
- if-no-files-found: error
- retention-days: 7
-
- build-instrumented-tests:
- name: Build instrumented test packages
- needs: [prepare]
- runs-on: ubuntu-latest
- container:
- image: ${{ needs.prepare.outputs.container_image }}
- strategy:
- matrix:
- include:
- - test-type: app
- assemble-command: assembleOssProdAndroidTest
- artifact-path: android/app/build/outputs/apk
- - test-type: mockapi
- assemble-command: :test:mockapi:assemble
- artifact-path: android/test/mockapi/build/outputs/apk
- - test-type: e2e
- assemble-command: :test:e2e:assemble
- artifact-path: android/test/e2e/build/outputs/apk
- 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@v4
- with:
- submodules: true
-
- - name: Prepare dummy debug keystore
- env:
- KEYSTORE: ${{ vars.ANDROID_DUMMY_DEBUG_KEYSTORE }}
- run: |
- echo "$KEYSTORE" | tr -d '\n\r' | base64 -d > /root/.android/debug.keystore
-
- - name: Assemble instrumented test apk
- uses: burrunan/gradle-cache-action@v3
- with:
- job-id: jdk17
- arguments: |
- ${{ matrix.assemble-command }}
- -x cargoBuild
- -x mergeOssProdDebugJniLibFolders
- -x mergePlayStagemoleDebugJniLibFolders
- gradle-version: wrapper
- build-root-directory: android
- execution-only-caches: false
- # Disable if logs are hard to follow.
- concurrent: true
- read-only: ${{ github.ref != 'refs/heads/main' }}
-
- - name: Upload apks
- uses: actions/upload-artifact@v4
- with:
- name: ${{ matrix.test-type }}-instrumentation-apks
- path: ${{ matrix.artifact-path }}
- if-no-files-found: error
- retention-days: 7
-
instrumented-tests:
name: Run instrumented tests
runs-on: [self-hosted, android-device]
- needs: [build-app, build-instrumented-tests]
+ needs: [build-app]
strategy:
fail-fast: false
matrix:
@@ -418,13 +230,7 @@ jobs:
if: ${{ matrix.test-repeat != 0 }}
with:
name: apks
- path: android/app/build/outputs/apk
-
- - uses: actions/download-artifact@v4
- if: ${{ matrix.test-repeat != 0 }}
- with:
- name: ${{ matrix.test-type }}-instrumentation-apks
- path: ${{ matrix.path }}
+ path: android
- name: Calculate timeout
id: calculate-timeout
@@ -455,7 +261,7 @@ jobs:
instrumented-e2e-tests:
name: Run instrumented e2e tests
runs-on: [self-hosted, android-device]
- needs: [prepare, build-app, build-instrumented-tests]
+ needs: [prepare, build-app]
if: needs.prepare.outputs.E2E_TEST_REPEAT != '0'
steps:
- name: Resolve unique runner test account secret name
@@ -484,12 +290,7 @@ jobs:
- uses: actions/download-artifact@v4
with:
name: apks
- path: android/app/build/outputs/apk
-
- - uses: actions/download-artifact@v4
- with:
- name: e2e-instrumentation-apks
- path: android/test/e2e/build/outputs/apk
+ path: android
- name: Calculate timeout
id: calculate-timeout
@@ -530,7 +331,7 @@ jobs:
if: github.event.inputs.run_firebase_tests == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
- needs: [build-app, build-instrumented-tests]
+ needs: [build-app]
env:
FIREBASE_ENVIRONMENT_VARIABLES: "\
clearPackageData=true,\
@@ -558,12 +359,7 @@ jobs:
- uses: actions/download-artifact@v4
with:
name: apks
- path: android/app/build/outputs/apk
-
- - uses: actions/download-artifact@v4
- with:
- name: ${{ matrix.test-type }}-instrumentation-apks
- path: ${{ matrix.path }}
+ path: android
- name: Run tests on Firebase Test Lab
uses: asadmansr/Firebase-Test-Lab-Action@v1.0