| name: Android |
| on: |
| workflow_call: |
| inputs: |
| profile: |
| required: false |
| default: "release" |
| type: string |
| upload: |
| required: false |
| default: false |
| type: boolean |
| github-release-id: |
| required: false |
| type: string |
| bencher: |
| required: false |
| default: false |
| type: boolean |
| |
| workflow_dispatch: |
| inputs: |
| profile: |
| required: false |
| default: "release" |
| type: choice |
| options: ["release", "debug", "production"] |
| bencher: |
| required: false |
| default: false |
| type: boolean |
| |
| |
| env: |
| RUST_BACKTRACE: 1 |
| SHELL: /bin/bash |
| CARGO_INCREMENTAL: 0 |
| |
| jobs: |
| build: |
| name: Android Build |
| runs-on: ubuntu-22.04 |
| strategy: |
| matrix: |
| target: ['aarch64-linux-android', 'armv7-linux-androideabi', 'x86_64-linux-android'] |
| steps: |
| - name: Free Disk Space (Ubuntu) |
| uses: jlumbroso/free-disk-space@main |
| with: |
| tool-cache: false |
| android: false |
| large-packages: false |
| swap-storage: false |
| - uses: actions/checkout@v4 |
| if: github.event_name != 'pull_request_target' |
| with: |
| fetch-depth: 2 |
| # This is necessary to checkout the pull request if this run was triggered via a |
| # `pull_request_target` event. |
| - uses: actions/checkout@v4 |
| if: github.event_name == 'pull_request_target' |
| with: |
| ref: ${{ github.event.pull_request.head.sha }} |
| fetch-depth: 2 |
| - name: Install crown |
| run: cargo install --path support/crown |
| - name: Setup Python |
| uses: ./.github/actions/setup-python |
| - name: Bootstrap dependencies |
| run: sudo apt update && ./mach bootstrap --skip-lints |
| - name: Set up JDK 17 |
| uses: actions/setup-java@v4 |
| with: |
| java-version: '17' |
| distribution: 'temurin' |
| - name: Setup Android SDK |
| uses: android-actions/setup-android@v3 |
| with: |
| packages: 'tools platform-tools platforms;android-33' |
| - name: Install Android NDK |
| uses: nttld/setup-ndk@v1 |
| id: setup-ndk |
| with: |
| ndk-version: r28b |
| - name: Setup Gradle caches |
| uses: gradle/actions/setup-gradle@v4 |
| - name: Trigger initial download of Gradle with retries |
| run: | |
| for i in {1..4}; do |
| ./gradlew --version && break || { echo "Downloading Gradle failed (attempt $i)." && sleep $((3 ** $i)); }; |
| done |
| working-directory: ./support/android/apk/ |
| - name: Setup Key Store for APK Signing |
| env: |
| KEYSTORE_BASE64: ${{ secrets.APK_KEYSTORE_BASE64 }} |
| if: ${{ env.KEYSTORE_BASE64 != '' }} |
| run: | |
| APK_SIGNING_KEY_STORE_PATH="${PWD}/servo_keystore.jks" |
| echo "${KEYSTORE_BASE64}" | base64 -d > "${APK_SIGNING_KEY_STORE_PATH}" |
| echo "APK_SIGNING_KEY_STORE_PATH=${APK_SIGNING_KEY_STORE_PATH}" >> ${GITHUB_ENV} |
| - name: Build (arch ${{ matrix.target }} profile ${{ inputs.profile }}) |
| env: |
| ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }} |
| APK_SIGNING_KEY_STORE_PASS: ${{ secrets.APK_SIGNING_KEY_STORE_PASS }} |
| APK_SIGNING_KEY_ALIAS: ${{ secrets.APK_SIGNING_KEY_ALIAS }} |
| APK_SIGNING_KEY_PASS: ${{ secrets.APK_SIGNING_KEY_PASS }} |
| run: | |
| ./mach build --use-crown --locked --target ${{ matrix.target }} --${{ inputs.profile }} |
| cp -r target/cargo-timings target/cargo-timings-android-${{ matrix.target }} |
| # TODO: This is disabled since APK crashes during startup. |
| # See https://github.com/servo/servo/issues/31134 |
| # - name: Script tests |
| # run: ./mach test-android-startup |
| - name: Archive build timing |
| uses: actions/upload-artifact@v4 |
| with: |
| name: cargo-timings-android-${{ matrix.target }}-${{ inputs.profile }} |
| # Using a wildcard here ensures that the archive includes the path. |
| path: target/cargo-timings-* |
| - name: Upload nightly |
| if: ${{ inputs.upload && contains(matrix.target, 'aarch64') }} |
| run: | |
| ./mach upload-nightly android \ |
| --secret-from-environment \ |
| --github-release-id ${{ inputs.github-release-id }} |
| env: |
| S3_UPLOAD_CREDENTIALS: ${{ secrets.S3_UPLOAD_CREDENTIALS }} |
| NIGHTLY_REPO_TOKEN: ${{ secrets.NIGHTLY_REPO_TOKEN }} |
| NIGHTLY_REPO: ${{ github.repository_owner }}/servo-nightly-builds |
| - name: Generate artifact attestation for APK |
| if: ${{ inputs.upload }} |
| uses: actions/attest-build-provenance@v1 |
| with: |
| subject-path: target/android/${{ matrix.target }}/${{ inputs.profile }}/servoapp.apk |
| - name: Upload APK artifact |
| uses: actions/upload-artifact@v4 |
| with: |
| name: ${{ inputs.profile }}-binary-android-${{ matrix.target }} |
| path: target/android/${{ matrix.target }}/${{ inputs.profile }}/servoapp.apk |
| - name: Generate artifact attestation for AAR |
| if: ${{ inputs.upload }} |
| uses: actions/attest-build-provenance@v1 |
| with: |
| subject-path: target/android/${{ matrix.target }}/${{ inputs.profile }}/servoview.aar |
| - name: Upload AAR artifact |
| uses: actions/upload-artifact@v4 |
| with: |
| name: ${{ inputs.profile }}-library-android-${{ matrix.target }} |
| path: target/android/${{ matrix.target }}/${{ inputs.profile }}/servoview.aar |
| |
| bencher: |
| needs: ["build"] |
| strategy: |
| matrix: |
| target: ['aarch64-linux-android', 'armv7-linux-androideabi', 'x86_64-linux-android'] |
| if: ${{ inputs.bencher && inputs.profile != 'debug' && github.event_name != 'workflow_dispatch' && github.event_name != 'merge_group' }} |
| name: 'Bencher (${{ matrix.target }})' |
| uses: ./.github/workflows/bencher.yml |
| with: |
| target: android-${{ matrix.target }} |
| profile: ${{ inputs.profile }} |
| compressed-file-path: ${{ inputs.profile }}-binary-android-${{ matrix.target }}/servoapp.apk |
| binary-path: lib/${{ matrix.target == 'aarch64-linux-android' && 'arm64-v8a' || matrix.target == 'armv7-linux-androideabi' && 'armeabi-v7a' || matrix.target == 'x86_64-linux-android' && 'x86_64'}}/libservoshell.so |
| file-size: true |
| speedometer: false |
| dromaeo: false |
| secrets: inherit |