name: android-ci on: push: branches: - main tags: - "android-*" pull_request: branches: - "*" concurrency: # cancel jobs on PRs only group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: pre_job: runs-on: ubuntu-latest outputs: should_skip: ${{ github.event_name != 'workflow_dispatch' && steps.changed-files.outputs.android_any_changed != 'true' }} steps: - uses: actions/checkout@v4 - name: Get all Android files that have changed if: github.event_name != 'workflow_dispatch' id: changed-files uses: tj-actions/changed-files@v40 with: files_yaml_from_source_file: .github/changed-files.yml android-build: runs-on: ${{ github.event.pull_request && !github.event.pull_request.draft && 'MapLibre_Native_Linux_16_core' || 'ubuntu-22.04' }} needs: - pre_job if: needs.pre_job.outputs.should_skip != 'true' defaults: run: working-directory: platform/android env: JOBS: 8 BUILDTYPE: Debug IS_LOCAL_DEVELOPMENT: false MLN_ANDROID_STL: c++_static steps: - name: Free Disk Space (Ubuntu) if: startsWith(runner.name, 'GitHub Actions') uses: jlumbroso/free-disk-space@main with: tool-cache: false android: false dotnet: true haskell: true large-packages: true docker-images: true swap-storage: false - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - run: echo "cmake.dir=$(dirname "$(dirname "$(command -v cmake)")")" >> local.properties - uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "17" - name: Cache node modules uses: actions/cache@v3 env: cache-name: cache-node-modules with: path: ~/.npm key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - name: npm install run: npm install --ignore-scripts working-directory: platform/android - uses: hendrikmuhs/ccache-action@v1.2 with: key: ${{ github.job }} - name: restore-gradle-cache uses: actions/cache@v3 env: cache-name: gradle-v1 with: path: ~/.gradle key: ${{ env.cache-name }}-${{ hashFiles('platform/android/gradle/dependencies.gradle') }}-${{ hashFiles('platform/android/build.gradle') }}-${{ hashFiles('platform/android/local.properties') }}-${{ hashFiles('platform/android/gradle/wrapper/gradle-wrapper.properties') }} restore-keys: | - ${{ env.cache-name }} - name: Check code style run: make android-check - name: Run Android unit tests run: make run-android-unit-test - name: Build libmapbox-gl.so for arm-v8 run: make android-lib-arm-v8 - name: Copy developer config with API key for UI tests if: github.ref == 'refs/heads/main' run: | MAPLIBRE_DEVELOPER_CONFIG_XML='${{ secrets.MAPLIBRE_DEVELOPER_CONFIG_XML }}' if [ -n "${MAPLIBRE_DEVELOPER_CONFIG_XML}" ]; then echo "${MAPLIBRE_DEVELOPER_CONFIG_XML}" > MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml else echo "No secrets.MAPLIBRE_DEVELOPER_CONFIG_XML variable set, not copying..." fi - name: Build Benchmark, copy to platform/android if: github.ref != 'refs/heads/main' run: | ./gradlew assembleDrawableRelease assembleDrawableReleaseAndroidTest cp MapboxGLAndroidSDKTestApp/build/outputs/apk/drawable/release/MapboxGLAndroidSDKTestApp-drawable-release.apk . cp MapboxGLAndroidSDKTestApp/build/outputs/apk/androidTest/drawable/release/MapboxGLAndroidSDKTestApp-drawable-release-androidTest.apk . - name: Create artifact for benchmark APKs uses: actions/upload-artifact@v4 if: github.ref != 'refs/heads/main' with: if-no-files-found: error name: benchmarkAPKs path: | platform/android/MapboxGLAndroidSDKTestApp-drawable-release.apk platform/android/MapboxGLAndroidSDKTestApp-drawable-release-androidTest.apk - if: github.event_name == 'pull_request' uses: ./.github/actions/save-pr-number - name: Build UI tests if: github.ref == 'refs/heads/main' run: make android-ui-test-arm-v8 - name: Configure AWS Credentials if: github.ref == 'refs/heads/main' uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 role-to-assume: ${{ vars.AWS_ROLE_TO_ASSUME }} role-duration-seconds: 21600 role-session-name: MySessionName - name: Create upload if: github.ref == 'refs/heads/main' uses: realm/aws-devicefarm/create-upload@master id: upload-android-app with: project_arn: ${{ vars.AWS_DEVICE_FARM_PROJECT_ARN }} name: MapboxGLAndroidSDKTestApp-debug.apk type: ANDROID_APP - name: Create upload if: github.ref == 'refs/heads/main' uses: realm/aws-devicefarm/create-upload@master id: upload-android-test with: project_arn: ${{ vars.AWS_DEVICE_FARM_PROJECT_ARN }} name: MapboxGLAndroidSDKTestApp-debug-androidTest.apk type: INSTRUMENTATION_TEST_PACKAGE - name: Upload Android UI test if: github.ref == 'refs/heads/main' run: | curl -T MapboxGLAndroidSDKTestApp/build/outputs/apk/legacy/release/MapboxGLAndroidSDKTestApp-legacy-debug.apk '${{ steps.upload-android-app.outputs.url }}' curl -T MapboxGLAndroidSDKTestApp/build/outputs/apk/androidTest/legacy/release/MapboxGLAndroidSDKTestApp-legacy-debug-androidTest.apk '${{ steps.upload-android-test.outputs.url }}' - name: Write uploads.env if: github.ref == 'refs/heads/main' working-directory: . run: | echo "ANDROID_APP_ARN=${{ steps.upload-android-app.outputs.arn }}" >> uploads.env echo "ANDROID_TEST_ARN=${{ steps.upload-android-test.outputs.arn }}" >> uploads.env - uses: actions/upload-artifact@v4 if: github.ref == 'refs/heads/main' with: if-no-files-found: error name: uploadsEnv path: uploads.env # render test - name: Build Render Test App run: | ./gradlew assemble assembleAndroidTest cp app/build/outputs/apk/release/app-release.apk RenderTestsApp.apk cp app/build/outputs/apk/androidTest/release/app-release-androidTest.apk RenderTests.apk working-directory: ./render-test/android - name: Store Render Test .apk files uses: actions/upload-artifact@v4 with: name: android-render-tests if-no-files-found: error path: | ./render-test/android/RenderTestsApp.apk ./render-test/android/RenderTests.apk - name: Store debug artifacts uses: actions/upload-artifact@v4 with: name: debug-artifacts path: | MapboxGLAndroidSDKTestApp/build/outputs/apk/debug MapboxGLAndroidSDK/build/reports/lint-results.html MapboxGLAndroidSDK/lint-baseline.xml MapboxGLAndroidSDKTestApp/build/reports/lint-results.html MapboxGLAndroidSDKTestApp/build/reports/lint-results.xml MapboxGLAndroidSDKTestApp/lint-baseline.xml MapboxGLAndroidSDK/build/intermediates/cmake/debug/obj android-instrumentation-test: needs: android-build runs-on: ubuntu-latest if: github.repository_owner == 'maplibre' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/android-annotations') steps: - uses: actions/download-artifact@v4 with: name: uploadsEnv - name: Read uploads.env run: cat uploads.env >> "$GITHUB_ENV" - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 role-to-assume: ${{ vars.AWS_ROLE_TO_ASSUME }} role-duration-seconds: 21600 role-session-name: MySessionName - name: Schedule test run uses: realm/aws-devicefarm/test-application@master with: name: MapLibre Native Android Instrumentation Test project_arn: ${{ vars.AWS_DEVICE_FARM_PROJECT_ARN }} device_pool_arn: ${{ vars.AWS_DEVICE_FARM_DEVICE_POOL_ARN }} app_arn: ${{ env.ANDROID_APP_ARN }} test_spec_arn: ${{ vars.AWS_DEVICE_FARM_TEST_SPEC_ARN_ANDROID_UI_TESTS }} app_type: ANDROID_APP test_type: INSTRUMENTATION test_package_arn: ${{ env.ANDROID_TEST_ARN }} timeout: 28800 android-ci-result: runs-on: ubuntu-latest if: needs.pre_job.outputs.should_skip != 'true' && always() needs: - pre_job - android-build steps: - name: Mark result as failed if: needs.android-build.result != 'success' run: exit 1