name: MobileGL APK on: push: branches: - dev - Feat/Backend-Direct-GLES - Feat/Backend-Direct-Vulkan workflow_dispatch: jobs: build: runs-on: ubuntu-latest env: CCACHE_BASEDIR: ${{ github.workspace }} CCACHE_COMPRESS: "true" CCACHE_DIR: ${{ github.workspace }}/.ccache CCACHE_MAXSIZE: 4G CCACHE_NOHASHDIR: "true" MOBILEGL_CMAKE_COMPILER_LAUNCHER: ccache steps: - name: Checkout repo uses: actions/checkout@v4 with: submodules: recursive - name: Set artifact metadata run: | echo "date_today=$(date +'%Y-%m-%d')" >> "$GITHUB_ENV" echo "short_sha=${GITHUB_SHA::7}" >> "$GITHUB_ENV" - name: Set up JDK uses: actions/setup-java@v4 with: distribution: zulu java-version: '17' - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: gradle-version: 8.10.2 - name: Restore ccache uses: actions/cache@v4 with: path: .ccache key: ${{ runner.os }}-apk-${{ github.job }}-ccache-${{ github.ref_name }}-${{ github.run_id }} restore-keys: | ${{ runner.os }}-apk-${{ github.job }}-ccache-${{ github.ref_name }}- ${{ runner.os }}-apk-${{ github.job }}-ccache- - name: Install ccache run: | sudo apt-get update sudo apt-get install -y ccache ccache --version - name: Setup Android SDK uses: android-actions/setup-android@v3 - name: Install Android NDK run: | sdkmanager "ndk;27.3.13750724" echo "ndk.dir=$ANDROID_HOME/ndk/27.3.13750724" >> android-plugin/local.properties - name: Update glslang external sources working-directory: 3rdparty/glslang run: python update_glslang_sources.py - name: Build plugin APKs run: gradle --no-daemon -p android-plugin :app:assembleEsprytPluginRelease :app:assembleMagmaPluginRelease -Pmobilegl.logLevel=MOBILEGL_LOG_LEVEL_INFO --parallel --max-workers "$(nproc)" env: SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} - name: Download ANGLE x86_64 libraries run: | angle_dir="android-plugin/app/src/trace/jniLibs/x86_64" angle_base="https://raw.githubusercontent.com/FCL-Team/FoldCraftLauncher/main/FCLauncher/src/main/jniLibs/x86_64" mkdir -p "${angle_dir}" curl -L --fail --retry 3 -o "${angle_dir}/libEGL_angle.so" "${angle_base}/libEGL_angle.so" curl -L --fail --retry 3 -o "${angle_dir}/libGLESv2_angle.so" "${angle_base}/libGLESv2_angle.so" test -s "${angle_dir}/libEGL_angle.so" test -s "${angle_dir}/libGLESv2_angle.so" - name: Build retrace APKs run: gradle --no-daemon -p android-plugin :app:assembleEsprytTraceRelease :app:assembleMagmaTraceRelease -Pmobilegl.abis=all -Pmobilegl.debuggableRelease=true -Pmobilegl.logLevel=MOBILEGL_LOG_LEVEL_INFO --parallel --max-workers "$(nproc)" env: SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} - name: Show ccache stats if: always() run: ccache --show-stats - name: Verify signed APKs run: | APKSIGNER="$(find "$ANDROID_HOME/build-tools" -name apksigner -type f | sort -V | tail -n 1)" mapfile -t APKS < <(find android-plugin/app/build/outputs/apk -type f -path '*/release/*.apk' | sort) if [ "${#APKS[@]}" -eq 0 ]; then echo "::error::No release APKs found under android-plugin/app/build/outputs/apk" find android-plugin/app/build/outputs/apk -type f -print || true exit 1 fi for APK in "${APKS[@]}"; do if [[ "$APK" == *-unsigned.apk ]]; then echo "::error::Unsigned release APK produced: $APK" exit 1 fi "$APKSIGNER" verify --verbose "$APK" done - name: Upload plugin APK uses: actions/upload-artifact@v4 with: name: MobileGL-plugin-${{ env.date_today }}-${{ env.short_sha }} path: android-plugin/app/build/outputs/apk/*Plugin/release/*.apk if-no-files-found: error - name: Upload retrace APK uses: actions/upload-artifact@v4 with: name: MobileGL-retrace-apk-${{ env.date_today }}-${{ env.short_sha }} path: android-plugin/app/build/outputs/apk/*Trace/release/*.apk if-no-files-found: error retrace: name: retrace (${{ matrix.backend.name }}, ${{ matrix.case.name }}) runs-on: ubuntu-latest needs: build timeout-minutes: 75 env: AVD_NAME: mobilegl-${{ matrix.backend.id }} strategy: fail-fast: false max-parallel: 4 matrix: backend: - name: DirectGLES id: espryt apk: MobileGL-EsprytTrace-release.apk package: top.mobilegl.plugin.espryt.trace gpu: software - name: DirectVulkan id: magma apk: MobileGL-MagmaTrace-release.apk package: top.mobilegl.plugin.magma.trace gpu: lavapipe case: - name: OpenRA trace_archive: tools/trace_replay/fixtures/openra.tgz trace_file: openra.trace golden: tools/trace_replay/fixtures/openra.0000031249.png target_call: 31249 width: 640 height: 480 crop_x: 1 crop_y: 1 crop_width: 638 crop_height: 478 timeout_seconds: 180 - name: minecraft-1.21.4-startup trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-startup.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-startup.0000092195.png target_call: 92195 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 180 - name: minecraft-1.21.4-main-menu trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-main-menu.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-main-menu.0000481787.png alternate_golden: tools/trace_replay/fixtures/minecraft-1.21.4-main-menu.0000481787-mali.png target_call: 481787 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 180 - name: minecraft-1.21.4-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-in-world.0000280000.png target_call: 280000 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-sodium-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-sodium-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-sodium-in-world.0000923340.png target_call: 923340 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-common-mods-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-common-mods-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-common-mods-in-world.0000522084.png target_call: 522084 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-common-mods-inventory trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-common-mods-inventory.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-common-mods-inventory.0000728558.png target_call: 728558 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-rei-inventory trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-rei-inventory.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-rei-inventory.0005431826.png target_call: 5431826 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-xaero-minimap-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-minimap-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-minimap-in-world.0002553500.png target_call: 2553500 width: 854 height: 480 crop_x: 0 crop_y: 10 crop_width: 140 crop_height: 158 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-xaero-world-map-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-world-map-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-world-map-in-world.0001598209.png target_call: 1598209 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-journeymap-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-journeymap-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-journeymap-in-world.0002632392.png target_call: 2632392 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-modernui-inventory trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-modernui-inventory.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-modernui-inventory.0004907381.png target_call: 4907381 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-rei-inventory-normal-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-rei-inventory-normal-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-rei-inventory-normal-world.0006599207.png target_call: 6599207 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-xaero-minimap-in-world-normal-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-minimap-in-world-normal-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-minimap-in-world-normal-world.0003893975.png target_call: 3893975 width: 854 height: 480 crop_x: 0 crop_y: 10 crop_width: 140 crop_height: 158 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-xaero-world-map-in-world-normal-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-world-map-in-world-normal-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-xaero-world-map-in-world-normal-world.0002099794.png target_call: 2099794 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-journeymap-in-world-normal-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-journeymap-in-world-normal-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-journeymap-in-world-normal-world.0005099482.png target_call: 5099482 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-modernui-inventory-normal-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-modernui-inventory-normal-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-modernui-inventory-normal-world.0008585354.png target_call: 8585354 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 1800 - name: minecraft-1.21.4-fabric-iris-bsl-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725.png alternate_golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725-mali.png target_call: 110725 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world.0000095322.png target_call: 95322 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world.0000141559.png target_call: 141559 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-sundial-lite-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-sundial-lite-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-sundial-lite-in-world.0000150023.png target_call: 150023 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world.0000151297.png target_call: 151297 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-complementary-unbound-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-unbound-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-unbound-in-world.0000146559.png target_call: 146559 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-mellow-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-mellow-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-mellow-in-world.0000096143.png target_call: 96143 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-nostalgia-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-nostalgia-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-nostalgia-in-world.0000153808-linux-mesa.png alternate_golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-nostalgia-in-world.0000153808.png target_call: 153808 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-bliss-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bliss-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bliss-in-world.0000113511.png target_call: 113511 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.0000125124-linux-mesa.png target_call: 125124 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-iterationt-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.0000110538.png target_call: 110538 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world.0000115019.png target_call: 115019 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-photon-v1.1-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.1-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.1-in-world.0000159866.png target_call: 159866 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-photon-v1.3b-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.3b-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.3b-in-world.0000172128.png target_call: 172128 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 - name: minecraft-1.21.4-fabric-iris-derivative-main-d24.4.14-in-world trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-derivative-main-d24.4.14-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-derivative-main-d24.4.14-in-world.0000145353.png target_call: 145353 width: 854 height: 480 crop_x: 0 crop_y: 0 crop_width: 0 crop_height: 0 timeout_seconds: 900 steps: - name: Checkout repo uses: actions/checkout@v4 - name: Fetch trace fixture run: bash .github/scripts/fetch-trace-fixture-lfs.sh '${{ matrix.case.name }}' - name: Set artifact metadata run: | echo "date_today=$(date +'%Y-%m-%d')" >> "$GITHUB_ENV" echo "short_sha=${GITHUB_SHA::7}" >> "$GITHUB_ENV" echo "EMULATOR_LOG=${RUNNER_TEMP}/mobilegl-emulator.log" >> "$GITHUB_ENV" echo "EMULATOR_PID_FILE=${RUNNER_TEMP}/mobilegl-emulator.pid" >> "$GITHUB_ENV" - name: Setup Android SDK uses: android-actions/setup-android@v3 - name: Download retrace APKs uses: actions/download-artifact@v4 with: pattern: MobileGL-retrace-apk-* path: android-retrace-apks merge-multiple: true - 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: Create AVD run: | sh android-plugin/run-avd-ci.sh create \ --api-level 35 \ --target google_apis \ --arch x86_64 \ --profile pixel_6 \ --avd-name "${AVD_NAME}" - name: Launch Emulator run: | sh android-plugin/run-avd-ci.sh start \ --avd-name "${AVD_NAME}" \ --gpu "${{ matrix.backend.gpu }}" \ --emulator-log "${EMULATOR_LOG}" \ --pid-file "${EMULATOR_PID_FILE}" \ --boot-timeout 300 - name: Retrace and validate env: MOBILEGL_RETRACE_USE_ANGLE: ${{ matrix.backend.name == 'DirectGLES' && '1' || '0' }} run: | apk_file="$(find android-retrace-apks -name '${{ matrix.backend.apk }}' -print -quit)" timeout "$(( ${{ matrix.case.timeout_seconds }} + 300 ))" sh android-plugin/trace-replay-ci.sh \ --apk-file "${apk_file}" \ --package "${{ matrix.backend.package }}" \ --backend "${{ matrix.backend.name }}" \ --result-root android-retrace-result \ --fixture-root android-retrace-fixture \ --case "${{ matrix.case.name }}" \ --trace-archive "${{ matrix.case.trace_archive }}" \ --trace-file "${{ matrix.case.trace_file }}" \ --golden "${{ matrix.case.golden }}" \ --alternate-golden "${{ matrix.case.alternate_golden || '' }}" \ --target-call "${{ matrix.case.target_call }}" \ --width "${{ matrix.case.width }}" \ --height "${{ matrix.case.height }}" \ --ssim-threshold "${{ matrix.case.ssim_threshold || '0.99' }}" \ --crop-x "${{ matrix.case.crop_x }}" \ --crop-y "${{ matrix.case.crop_y }}" \ --crop-width "${{ matrix.case.crop_width }}" \ --crop-height "${{ matrix.case.crop_height }}" \ --timeout-seconds "${{ matrix.case.timeout_seconds }}" - name: Collect retrace summary inputs if: always() run: | safe_case="$(printf '%s' '${{ matrix.case.name }}' | sed 's/[^A-Za-z0-9._-]/_/g')" result_dir="android-retrace-result/${safe_case}-${{ matrix.backend.name }}" mkdir -p "${result_dir}" if [ -s "${{ matrix.case.golden }}" ]; then cp "${{ matrix.case.golden }}" "${result_dir}/${safe_case}-${{ matrix.backend.name }}-golden.png" fi if [ -n "${{ matrix.case.alternate_golden || '' }}" ] && [ -s "${{ matrix.case.alternate_golden || '' }}" ]; then cp "${{ matrix.case.alternate_golden || '' }}" "${result_dir}/${safe_case}-${{ matrix.backend.name }}-alternate-golden.png" fi - name: Collect emulator diagnostics if: always() run: | mkdir -p android-retrace-result/diagnostics adb devices -l > android-retrace-result/diagnostics/adb-devices.txt || true timeout 30 adb logcat -d -t 1000 > android-retrace-result/diagnostics/logcat.txt || true if [ -f "${EMULATOR_LOG}" ]; then cp "${EMULATOR_LOG}" android-retrace-result/diagnostics/emulator.log fi - name: Stop Emulator if: always() run: | sh android-plugin/run-avd-ci.sh stop \ --avd-name "${AVD_NAME}" \ --emulator-log "${EMULATOR_LOG}" \ --pid-file "${EMULATOR_PID_FILE}" - name: Upload Android retrace result if: always() uses: actions/upload-artifact@v4 with: name: MobileGL-android-retrace-result-${{ env.date_today }}-${{ env.short_sha }}-${{ matrix.backend.name }}-${{ matrix.case.name }} path: android-retrace-result/** if-no-files-found: warn retrace-summary: name: retrace summary runs-on: ubuntu-latest needs: retrace if: always() steps: - name: Checkout repo uses: actions/checkout@v4 - name: Set artifact metadata run: | echo "date_today=$(date +'%Y-%m-%d')" >> "$GITHUB_ENV" echo "short_sha=${GITHUB_SHA::7}" >> "$GITHUB_ENV" - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '22' - name: Download Android retrace results uses: actions/download-artifact@v4 with: pattern: MobileGL-android-retrace-result-* path: retrace-artifacts - name: Render retrace summary run: | node tools/trace_replay/render_retrace_summary.mjs \ --input retrace-artifacts \ --output-dir android-retrace-summary \ --title "MobileGL Android retrace overview" \ --group-label "Android Emulator" \ --html mobilegl-android-retrace-overview.html - name: Upload Android retrace summary uses: actions/upload-artifact@v7 with: path: android-retrace-summary/mobilegl-android-retrace-overview.html archive: false if-no-files-found: error