@@ -10,15 +10,20 @@ jobs:
1010 name : Integration Test
1111 runs-on : ubuntu-latest
1212
13+ env :
14+ SAUCE_USERNAME : ${{ secrets.SAUCE_USERNAME }}
15+ SAUCE_ACCESS_KEY : ${{ secrets.SAUCE_ACCESS_KEY }}
16+ GITHUB_TOKEN : ${{ github.token }}
17+ SAUCE_REGION : eu-central-1
18+
1319 steps :
1420 - uses : actions/checkout@v4
15- with :
16- submodules : recursive
1721
18- - name : Download sample build
19- uses : actions/ download-artifact@v4
22+ - name : Download artifact from workflow run
23+ uses : dawidd6/action- download-artifact@v6
2024 with :
21- name : UE ${{ inputs.unreal-version }} sample build (Android)
25+ run_id : 19533023161
26+ name : " UE ${{ inputs.unreal-version }} sample build (Android)"
2227 path : sample-build
2328
2429 - name : List downloaded files
2732 ls -lah sample-build/
2833 echo "Using x64 APK for emulator testing"
2934
30- - name : Enable KVM group perms
31- run : |
32- echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
33- sudo udevadm control --reload-rules
34- sudo udevadm trigger --name-match=kvm
35-
36- - name : Setup Android directories
37- run : |
38- mkdir -p $HOME/.android/avd
39- touch $HOME/.android/repositories.cfg
40-
4135 - name : Install Pester
4236 shell : pwsh
4337 run : Install-Module -Name Pester -Force -SkipPublisherCheck
@@ -49,32 +43,99 @@ jobs:
4943 mkdir build
5044 cmake -B build -S .
5145
52- - name : Run Android Integration Tests
53- uses : reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b
54- id : integration-test
55- timeout-minutes : 45
56- with :
57- api-level : 34
58- target : ' google_apis'
59- arch : x86_64
60- force-avd-creation : true
61- disable-animations : true
62- disable-spellchecker : true
63- emulator-options : >
64- -no-window
65- -no-snapshot-save
66- -gpu swiftshader_indirect
67- -noaudio
68- -no-boot-anim
69- -camera-back none
70- -camera-front none
71- script : |
72- adb wait-for-device
73- cd integration-test && pwsh -Command "Invoke-Pester Integration.Tests.Android.ps1 -CI"
74- env :
75- SENTRY_UNREAL_TEST_DSN : ${{ secrets.SENTRY_UNREAL_TEST_DSN }}
76- SENTRY_AUTH_TOKEN : ${{ secrets.SENTRY_API_TOKEN }}
77- SENTRY_UNREAL_TEST_APP_PATH : ${{ github.workspace }}/sample-build/SentryPlayground-x64.apk
46+ - name : Upload APK to SauceLabs Storage
47+ id : upload_apk
48+ run : |
49+ sudo apt-get install -y jq
50+
51+ APK=$(ls sample-build/*.apk | head -n1)
52+ echo "Uploading: $APK"
53+
54+ RESPONSE=$(curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
55+ -X POST "https://api.${SAUCE_REGION}.saucelabs.com/v1/storage/upload" \
56+ -F "payload=@${APK}" \
57+ -F "name=$(basename "$APK")")
58+
59+ echo "Upload Response: $RESPONSE"
60+ STORAGE_ID=$(echo "$RESPONSE" | jq -r '.item.id')
61+
62+ echo "storage_id=$STORAGE_ID" >> $GITHUB_OUTPUT
63+
64+ - name : Check available devices
65+ run : |
66+ echo "Querying available Android devices in EU-Central..."
67+ curl -sS -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
68+ "https://api.eu-central-1.saucelabs.com/v1/rdc/devices?type=real_device&os=Android" \
69+ | jq '.'
70+
71+ - name : Start UE5 test on real device
72+ id : start_job
73+ run : |
74+ REQUEST=$(cat <<EOF
75+ {
76+ "capabilities": {
77+ "alwaysMatch": {
78+ "platformName": "Android",
79+ "appium:app": "storage:${{ steps.upload_apk.outputs.storage_id }}",
80+ "appium:deviceName": "Samsung_Galaxy_S23_FE_free",
81+ "appium:automationName": "UiAutomator2",
82+ "appium:appPackage": "io.sentry.unreal.sample",
83+ "appium:appActivity": "com.epicgames.unreal.GameActivity",
84+ "appium:optionalIntentArguments": "-e cmdline '-message-capture'",
85+ "sauce:options": {
86+ "name": "UE5 Integration Test",
87+ "appiumVersion": "latest"
88+ }
89+ }
90+ }
91+ }
92+ EOF
93+ )
94+
95+ echo "Sending Appium session request..."
96+ echo "$REQUEST"
97+
98+ RESPONSE=$(curl -sS -w "\nHTTP_CODE:%{http_code}" \
99+ -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
100+ -X POST "https://ondemand.eu-central-1.saucelabs.com/wd/hub/session" \
101+ -H "Content-Type: application/json" \
102+ -d "$REQUEST")
103+
104+ echo "Session Response: $RESPONSE"
105+
106+ SESSION_ID=$(echo "$RESPONSE" | grep -v "HTTP_CODE" | jq -r '.value.sessionId // .sessionId')
107+ echo "Extracted session_id: $SESSION_ID"
108+ echo "session_id=$SESSION_ID" >> $GITHUB_OUTPUT
109+
110+ - name : Poll job status
111+ run : |
112+ JOB_ID=${{ steps.start_job.outputs.job_id }}
113+
114+ for i in {1..60}; do
115+ STATUS=$(curl -su "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
116+ "https://api.${SAUCE_REGION}.saucelabs.com/v1/rdc/jobs/$JOB_ID" \
117+ | jq -r '.status')
118+
119+ echo "Status: $STATUS"
120+
121+ if [[ "$STATUS" == "complete" ]] || [[ "$STATUS" == "error" ]]; then
122+ break
123+ fi
124+
125+ sleep 10
126+ done
127+
128+ - name : Download logcat output
129+ run : |
130+ mkdir -p integration-test/output
131+ JOB_ID=${{ steps.start_job.outputs.job_id }}
132+
133+ curl -su "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
134+ "https://api.${SAUCE_REGION}.saucelabs.com/v1/rdc/jobs/$JOB_ID/logs/logcat" \
135+ -o integration-test/output/logcat.txt
136+
137+ echo "Last 50 log lines:"
138+ tail -50 integration-test/output/logcat.txt
78139
79140 - name : Upload integration test output
80141 if : ${{ always() && steps.integration-test.outcome == 'failure' }}
0 commit comments