Skip to content

Workflow - Tests on Mobile #31

Workflow - Tests on Mobile

Workflow - Tests on Mobile #31

name: Workflow - Tests on Mobile
on:
workflow_call:
inputs:
repository:
required: true
type: string
default: "bevyengine/bevy"
gitref:
required: true
type: string
default: "main"
mobile_percy_project:
required: false
type: string
pixeleagle_project:
required: true
type: string
branch:
required: true
type: string
workflow_dispatch:
inputs:
repository:
required: true
type: string
default: "bevyengine/bevy"
description: "Bevy repository to use"
gitref:
required: true
type: string
default: "main"
description: "Commit or branch name to run on"
mobile_percy_project:
required: false
type: string
description: "Percy project to send results to"
pixeleagle_project:
required: true
type: string
default: "B25A040A-A980-4602-B90C-D480AB84076D"
description: "Pixel Eagle project to send results to"
branch:
required: true
type: string
description: "Branch name to use as a tag in Pixel Eagle"
jobs:
create-pixel-eagle-run:
runs-on: ubuntu-latest
outputs:
pixeleagle_run: ${{ steps.run.outputs.pixeleagle_run }}
steps:
- name: Create Run
id: run
run: |
run=`curl https://pixel-eagle.com/${{ inputs.pixeleagle_project }}/runs -H 'Content-Type: application/json' -d '{"os":"mobile", "gitref": "${{ inputs.gitref }}", "branch": "${{ inputs.branch }}"}' --oauth2-bearer ${{ secrets.PIXELEAGLE }} | jq '.id'`
echo "pixeleagle_run=$run" >> $GITHUB_OUTPUT
build-for-iOS:
runs-on: macos-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
repository: ${{ inputs.repository }}
ref: ${{ inputs.gitref }}
- name: Checkout patches
uses: actions/checkout@v4
with:
path: "runner-patches"
- name: Apply patches
shell: pwsh
run: |
Get-ChildItem "runner-patches/patches" -Filter *.patch |
Foreach-Object {
Write-Output "Processing $($_.FullName)"
git apply --ignore-whitespace $($_.FullName)
}
- uses: dtolnay/rust-toolchain@stable
- name: Add iOS targets
run: rustup target add aarch64-apple-ios x86_64-apple-ios
- name: Build app for iOS
run: |
cd examples/mobile
make xcodebuild-iphone
mkdir Payload
mv build/Build/Products/Debug-iphoneos/bevy_mobile_example.app Payload
zip -r bevy_mobile_example.zip Payload
mv bevy_mobile_example.zip bevy_mobile_example.ipa
- name: Upload to Browser Stack
run: |
curl -u "${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESS_KEY }}" \
-X POST "https://api-cloud.browserstack.com/app-automate/upload" \
-F "file=@examples/mobile/bevy_mobile_example.ipa" \
-F "custom_id=$GITHUB_RUN_ID"
- uses: actions/upload-artifact@v4
with:
name: app.ipa
path: examples/mobile/bevy_mobile_example.ipa
retention-days: 2
build-for-Android:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
repository: ${{ inputs.repository }}
ref: ${{ inputs.gitref }}
- name: Checkout patches
uses: actions/checkout@v4
with:
path: "runner-patches"
- name: Apply patches
shell: pwsh
run: |
Get-ChildItem "runner-patches/patches" -Filter *.patch |
Foreach-Object {
Write-Output "Processing $($_.FullName)"
git apply --ignore-whitespace $($_.FullName)
}
- uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-gnu,aarch64-linux-android,armv7-linux-androideabi
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: "17"
distribution: "temurin"
- name: Install Cargo NDK
run: cargo install --force cargo-ndk
- name: Build .so file
run: cargo ndk -t arm64-v8a -o examples/mobile/android_example/app/src/main/jniLibs build --package bevy_mobile_example --release
- name: Build app for Android
run: cd examples/mobile/android_example && chmod +x gradlew && ./gradlew build
- name: Upload to Browser Stack
run: |
curl -u "${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESS_KEY }}" \
-X POST "https://api-cloud.browserstack.com/app-automate/upload" \
-F "file=@examples/mobile/android_example/app/build/outputs/apk/debug/app-debug.apk" \
-F "custom_id=$GITHUB_RUN_ID"
- uses: actions/upload-artifact@v4
with:
name: app.apk
path: examples/mobile/android_example/app/build/outputs/apk/debug/app-debug.apk
retention-days: 2
take-screenshots:
runs-on: ubuntu-latest
timeout-minutes: 30
needs: [build-for-iOS, build-for-Android, create-pixel-eagle-run]
strategy:
fail-fast: false
max-parallel: 7
matrix:
include:
- os: "iOS"
device: "iPhone 13"
os_version: "15"
adapter: ""
- os: "iOS"
device: "iPhone 14"
os_version: "16"
adapter: ""
- os: "iOS"
device: "iPhone 15"
os_version: "17"
adapter: ""
- os: "iOS"
device: "iPhone 14"
os_version: "18"
adapter: ""
- os: "Android"
device: "Google Pixel 6"
os_version: "12.0"
adapter: "Mali-G78"
- os: "Android"
device: "Google Pixel 7"
os_version: "13.0"
adapter: "Mali-G710"
- os: "Android"
device: "Google Pixel 8"
os_version: "14.0"
adapter: "Mali-G715"
- os: "Android"
device: "Google Pixel 9"
os_version: "15.0"
adapter: "Mali-G715"
- os: "Android"
device: "Samsung Galaxy S23"
os_version: "13.0"
adapter: "Adreno (TM) 740"
- os: "Android"
device: "Samsung Galaxy S24"
os_version: "14.0"
adapter: "Samsung Xclipse 940"
- os: "Android"
device: "Samsung Galaxy S25"
os_version: "15.0"
adapter: "Adreno (TM) 830"
- os: "Android"
device: "OnePlus 11R"
os_version: "13.0"
adapter: "Adreno (TM) 730"
- os: "Android"
device: "OnePlus 12R"
os_version: "14.0"
adapter: "Adreno (TM) 740"
steps:
- uses: actions/checkout@v4
with:
repository: ${{ inputs.repository }}
ref: ${{ inputs.gitref }}
- name: Checkout patches
uses: actions/checkout@v4
with:
path: "runner-patches"
- name: Apply patches
shell: pwsh
run: |
Get-ChildItem "runner-patches/patches" -Filter *.patch |
Foreach-Object {
Write-Output "Processing $($_.FullName)"
git apply --ignore-whitespace $($_.FullName)
}
- name: Set Percy Token if needed
if: "${{ inputs.mobile_percy_project != '' }}"
run: echo "PERCY_TOKEN=${{ secrets.PERCY_TOKEN_MOBILE }}" >> $GITHUB_ENV
- name: Run Example
run: |
cd .github/start-mobile-example
npm install
npm install -g @percy/cli@latest
npx percy app:exec --parallel -- npm run mobile
env:
BROWSERSTACK_APP_ID: ${{ github.run_id }}
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
DEVICE: ${{ matrix.device }}
OS_VERSION: ${{ matrix.os_version }}
PERCY_COMMIT: ${{ inputs.gitref }}
PERCY_PARALLEL_NONCE: ${{ github.run_id }}
PERCY_PARALLEL_TOTAL: ${{ strategy.job-total }}
- name: Save screenshots
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: screenshots-${{ matrix.device }}-${{ matrix.os_version }}
path: .github/start-mobile-example/*.png
- name: Send to Pixel Eagle
run: |
cd .github/start-mobile-example
for screenshot in $(find . -type f -maxdepth 1 -name "*.png");
do
file=${screenshot:2}
name="${{ matrix.os }}-${{ matrix.device }}-${{ matrix.os_version }}-$file"
echo $name
curl https://pixel-eagle.com/${{ inputs.pixeleagle_project }}/runs/${{ needs.create-pixel-eagle-run.outputs.pixeleagle_run }}/screenshots -F "data=@./$file" -F "screenshot=$name" --oauth2-bearer ${{ secrets.PIXELEAGLE }}
done
mobile-check-result:
runs-on: ubuntu-latest
timeout-minutes: 30
needs: [take-screenshots]
if: always()
steps:
- name: Wait for screenshots comparison
if: ${{ inputs.mobile_percy_project != '' }}
run: |
# npm install -g @percy/cli@latest
# npx percy build:wait --project ${{ inputs.mobile_percy_project }} --commit ${{ inputs.gitref }}
# there's an issue with percy APIs, it returns forbidden for this query
# for now, just wait a few seconds
sleep 30
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN_MOBILE }}
mobile-check-result-pixel-eagle:
runs-on: ubuntu-latest
timeout-minutes: 30
needs: [take-screenshots, create-pixel-eagle-run]
if: always()
steps:
- name: Trigger screenshots comparison
run: |
curl https://pixel-eagle.com/${{ inputs.pixeleagle_project }}/runs/${{ needs.create-pixel-eagle-run.outputs.pixeleagle_run }}/compare/auto -H 'Content-Type: application/json' -d '{"os":"<equal>", "branch": "main"}' --oauth2-bearer ${{ secrets.PIXELEAGLE }} | jq '{project_id: .project_id, from: .from, to: .to}' > pixeleagle-mobile.json
cat pixeleagle-mobile.json
- name: Upload Pixel Eagle status
uses: actions/upload-artifact@v4
with:
name: pixeleagle-mobile
path: pixeleagle-mobile.json
- name: Wait a bit
run: |
sleep 30