mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
426 lines
16 KiB
YAML
426 lines
16 KiB
YAML
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
|
|
|
|
trace-cases:
|
|
name: trace case matrix
|
|
runs-on: ubuntu-latest
|
|
needs: build
|
|
outputs:
|
|
android: ${{ steps.trace-cases.outputs.android }}
|
|
names: ${{ steps.trace-cases.outputs.names }}
|
|
steps:
|
|
- name: Checkout repo
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Load trace cases
|
|
id: trace-cases
|
|
run: |
|
|
echo "android=$(python3 tools/trace_replay/trace_cases.py --ci --format github-apk)" >> "$GITHUB_OUTPUT"
|
|
echo "names=$(python3 tools/trace_replay/trace_cases.py --ci --format names)" >> "$GITHUB_OUTPUT"
|
|
|
|
trace-fixtures:
|
|
name: trace fixture (${{ matrix.case }})
|
|
runs-on: ubuntu-latest
|
|
needs: trace-cases
|
|
strategy:
|
|
fail-fast: false
|
|
max-parallel: 4
|
|
matrix:
|
|
case: ${{ fromJSON(needs.trace-cases.outputs.names) }}
|
|
steps:
|
|
- name: Checkout repo
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Fetch trace fixture
|
|
run: bash .github/scripts/fetch-trace-fixture-lfs.sh '${{ matrix.case }}'
|
|
|
|
- name: Stage trace fixture
|
|
run: |
|
|
safe_case="$(printf '%s' '${{ matrix.case }}' | sed 's/[^A-Za-z0-9._-]/_/g')"
|
|
stage_dir="trace-fixtures/${safe_case}"
|
|
mkdir -p "${stage_dir}"
|
|
python3 tools/trace_replay/trace_cases.py --format fixture-files --case '${{ matrix.case }}' |
|
|
while IFS= read -r file; do
|
|
cp "${file}" "${stage_dir}/"
|
|
done
|
|
|
|
- name: Upload trace fixture
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: MobileGL-trace-fixture-${{ matrix.case }}
|
|
path: trace-fixtures/**
|
|
if-no-files-found: error
|
|
|
|
android-avd:
|
|
name: android avd image
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
AVD_NAME: mobilegl-ci
|
|
ANDROID_AVD_HOME: ${{ github.workspace }}/.android/avd
|
|
steps:
|
|
- name: Checkout repo
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Android SDK
|
|
uses: android-actions/setup-android@v3
|
|
|
|
- name: Restore Android AVD cache
|
|
id: android-avd-cache
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
${{ env.ANDROID_AVD_HOME }}
|
|
/usr/local/lib/android/sdk/emulator
|
|
/usr/local/lib/android/sdk/platform-tools
|
|
/usr/local/lib/android/sdk/platforms/android-35
|
|
/usr/local/lib/android/sdk/system-images/android-35/google_apis/x86_64
|
|
key: ${{ runner.os }}-mobilegl-avd-api35-google_apis-x86_64-pixel_6-v1-${{ hashFiles('android-plugin/run-avd-ci.sh') }}
|
|
|
|
- name: Create AVD
|
|
if: steps.android-avd-cache.outputs.cache-hit != 'true'
|
|
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}"
|
|
|
|
retrace:
|
|
name: retrace (${{ matrix.backend.name }}, ${{ matrix.case.name }})
|
|
runs-on: ubuntu-latest
|
|
needs:
|
|
- build
|
|
- android-avd
|
|
- trace-cases
|
|
- trace-fixtures
|
|
if: ${{ always() && needs.build.result == 'success' && needs.android-avd.result == 'success' && needs.trace-cases.result == 'success' }}
|
|
timeout-minutes: 75
|
|
env:
|
|
AVD_NAME: mobilegl-ci
|
|
ANDROID_AVD_HOME: ${{ github.workspace }}/.android/avd
|
|
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: ${{ fromJSON(needs.trace-cases.outputs.android) }}
|
|
steps:
|
|
- name: Set Swap Space
|
|
uses: pierotofy/set-swap-space@master
|
|
with:
|
|
swap-size-gb: 16
|
|
|
|
- name: Checkout repo
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Download trace fixture
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: MobileGL-trace-fixture-${{ matrix.case.name }}
|
|
path: trace-fixture-download
|
|
|
|
- name: Install trace fixture
|
|
run: |
|
|
mkdir -p tools/trace_replay/fixtures
|
|
find trace-fixture-download -type f -exec cp {} tools/trace_replay/fixtures/ \;
|
|
|
|
- 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: Restore Android AVD cache
|
|
id: android-avd-cache
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: |
|
|
${{ env.ANDROID_AVD_HOME }}
|
|
/usr/local/lib/android/sdk/emulator
|
|
/usr/local/lib/android/sdk/platform-tools
|
|
/usr/local/lib/android/sdk/platforms/android-35
|
|
/usr/local/lib/android/sdk/system-images/android-35/google_apis/x86_64
|
|
key: ${{ runner.os }}-mobilegl-avd-api35-google_apis-x86_64-pixel_6-v1-${{ hashFiles('android-plugin/run-avd-ci.sh') }}
|
|
|
|
- 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
|
|
if: steps.android-avd-cache.outputs.cache-hit != 'true'
|
|
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' }}
|
|
MOBILEGL_VULKAN_R11G11B10F_FALLBACK: ${{ matrix.backend.name == 'DirectVulkan' && '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
|