@@ -18,64 +18,317 @@ concurrency:
1818
1919jobs :
2020 build :
21- runs-on : macos-15-intel
21+ runs-on : ubuntu-latest
2222
2323 steps :
24- - uses : actions/checkout@v3
24+ - uses : actions/checkout@v4
2525 with :
26- fetch-depth : 0
2726 ref : ${{ github.head_ref }}
2827 token : ${{ secrets.GITHUB_TOKEN }}
2928
30- - name : Set Up JDK
31- uses : actions/setup-java@v3
29+ - name : Set up JDK 17
30+ uses : actions/setup-java@v4
3231 with :
33- distribution : ' zulu' # See 'Supported distributions' for available options
3432 java-version : ' 17'
35- cache : ' gradle'
33+ distribution : ' temurin'
34+
35+ - name : Setup Gradle
36+ uses : gradle/actions/setup-gradle@v3
3637
3738 # Allow us to run the command
3839 - name : Change wrapper permissions
3940 run : chmod +x ./gradlew
4041
41- # Run Build & Test the Project
42- - name : Build gradle project
43- run : ./gradlew build
42+ # Assemble (no tests / no lint — those run in dedicated jobs)
43+ - name : Assemble gradle project
44+ run : ./gradlew assemble -x lint -x lintDebug -x lintVitalRelease
45+
46+ - name : Build test project
47+ run : ./gradlew :app:assembleAndroidTest -DtestBuildType=debug -x lint -x lintDebug -x lintVitalRelease
48+
49+ - name : Run tests on Firebase Test Lab
50+ uses : asadmansr/Firebase-Test-Lab-Action@v1.0
51+ with :
52+ arg-spec : ' .github/firebase-tests.yml:android-pixel-7'
53+ env :
54+ SERVICE_ACCOUNT : ${{ secrets.SERVICE_ACCOUNT }}
55+
56+ unit-tests :
57+ runs-on : ubuntu-latest
58+
59+ steps :
60+ - uses : actions/checkout@v4
61+ with :
62+ ref : ${{ github.head_ref }}
63+ token : ${{ secrets.GITHUB_TOKEN }}
64+
65+ - name : Set up JDK 17
66+ uses : actions/setup-java@v4
67+ with :
68+ java-version : ' 17'
69+ distribution : ' temurin'
70+
71+ - name : Setup Gradle
72+ uses : gradle/actions/setup-gradle@v3
73+
74+ - name : Change wrapper permissions
75+ run : chmod +x ./gradlew
76+
77+ - name : Run unit tests with coverage
78+ run : ./gradlew :superwall:testDebugUnitTest -x lint -x lintDebug -x lintVitalRelease
79+
80+ - name : Upload unit test coverage data
81+ uses : actions/upload-artifact@v4
82+ if : always()
83+ with :
84+ name : unit-test-coverage
85+ path : superwall/build/jacoco/
86+
87+ - name : Upload unit test reports
88+ uses : actions/upload-artifact@v4
89+ if : always()
90+ with :
91+ name : unit-test-reports
92+ path : |
93+ superwall/build/reports/tests/
94+ superwall/build/test-results/
95+
96+ # Single-runner pre-job that populates the AVD snapshot cache before the matrix
97+ # fans out, so the 5 shards don't race to create the same snapshot on a cold cache.
98+ # On a warm cache this job is ~30s of overhead (checkout + cache restore + skip).
99+ warm-emulator-cache :
100+ runs-on : ubuntu-latest
101+ steps :
102+ - uses : actions/checkout@v4
103+ with :
104+ ref : ${{ github.head_ref }}
105+ token : ${{ secrets.GITHUB_TOKEN }}
44106
45- - name : Run unit and instrumentation tests with coverage
107+ - name : AVD cache
108+ uses : actions/cache@v4
109+ id : avd-cache
110+ with :
111+ path : |
112+ ~/.android/avd/*
113+ ~/.android/adb*
114+ key : avd-api33-google_apis-x86_64-pixel_7_pro-v1
115+
116+ # Everything below only runs on a cold cache. On a warm cache the job ends here.
117+ - name : Free disk space
118+ if : steps.avd-cache.outputs.cache-hit != 'true'
119+ uses : jlumbroso/free-disk-space@v1.3.1
120+ with :
121+ android : false
122+ tool-cache : true
123+ dotnet : true
124+ haskell : true
125+ swap-storage : true
126+ docker-images : false
127+ large-packages : false
128+
129+ - name : Enable KVM
130+ if : steps.avd-cache.outputs.cache-hit != 'true'
131+ run : |
132+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
133+ sudo udevadm control --reload-rules
134+ sudo udevadm trigger --name-match=kvm
135+
136+ - name : Set up JDK 17
137+ if : steps.avd-cache.outputs.cache-hit != 'true'
138+ uses : actions/setup-java@v4
139+ with :
140+ java-version : ' 17'
141+ distribution : ' temurin'
142+
143+ - name : Setup Gradle
144+ if : steps.avd-cache.outputs.cache-hit != 'true'
145+ uses : gradle/actions/setup-gradle@v3
146+
147+ - name : Create AVD and generate snapshot for caching
148+ if : steps.avd-cache.outputs.cache-hit != 'true'
46149 uses : reactivecircus/android-emulator-runner@v2
47150 with :
48151 api-level : 33
49152 target : google_apis
50153 arch : x86_64
51154 profile : pixel_7_pro
52- force-avd-creation : true
155+ force-avd-creation : false
53156 ram-size : 4096M
54157 emulator-boot-timeout : 1800
55- disable-animations : true
158+ disable-animations : false
159+ emulator-options : >
160+ -no-window
161+ -gpu swiftshader_indirect
162+ -no-boot-anim
163+ -noaudio
164+ -camera-back none
165+ -camera-front none
166+ script : echo "Generated AVD snapshot for caching."
167+
168+ instrumentation-tests :
169+ runs-on : ubuntu-latest
170+ needs : [warm-emulator-cache]
171+ # Run even if warm-emulator-cache failed — the per-shard warm-up step below
172+ # acts as a fallback. Don't run on workflow cancellation.
173+ if : ${{ !cancelled() }}
174+ strategy :
175+ fail-fast : false
176+ matrix :
177+ shard : [0, 1, 2, 3, 4]
178+
179+ steps :
180+ - uses : actions/checkout@v4
181+ with :
182+ ref : ${{ github.head_ref }}
183+ token : ${{ secrets.GITHUB_TOKEN }}
184+
185+ # Reclaim ~10+ GB on the runner before the AVD cache restore + emulator boot.
186+ # Ubuntu runners ship near-full and instrumentation jobs can hit "no space
187+ # left on device" around the emulator boot or coverage write otherwise.
188+ - name : Free disk space
189+ uses : jlumbroso/free-disk-space@v1.3.1
190+ with :
191+ android : false # keep Android SDK / tools
192+ tool-cache : true # rm -rf "$AGENT_TOOLSDIRECTORY"
193+ dotnet : true # rm -rf /usr/share/dotnet
194+ haskell : true # rm -rf /opt/ghc
195+ swap-storage : true # rm -f /mnt/swapfile (4 GiB)
196+ docker-images : false # slow (~16s), skip
197+ large-packages : false # slow (includes google-cloud-sdk), skip
198+
199+ - name : Enable KVM
200+ run : |
201+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
202+ sudo udevadm control --reload-rules
203+ sudo udevadm trigger --name-match=kvm
204+
205+ - name : Set up JDK 17
206+ uses : actions/setup-java@v4
207+ with :
208+ java-version : ' 17'
209+ distribution : ' temurin'
210+
211+ - name : Setup Gradle
212+ uses : gradle/actions/setup-gradle@v3
213+
214+ - name : Change wrapper permissions
215+ run : chmod +x ./gradlew
216+
217+ # Cache the AVD across runs. Key is shared across all 5 shards because they
218+ # all use the same api-level/target/arch/profile, so they all share one snapshot.
219+ - name : AVD cache
220+ uses : actions/cache@v4
221+ id : avd-cache
222+ with :
223+ path : |
224+ ~/.android/avd/*
225+ ~/.android/adb*
226+ key : avd-api33-google_apis-x86_64-pixel_7_pro-v1
227+
228+ # Cold-cache only: create the AVD and let the emulator save a snapshot on shutdown.
229+ # Note the deliberate ABSENCE of -no-snapshot-save in emulator-options here, and
230+ # disable-animations is left false so the snapshot is generic and reusable.
231+ - name : Create AVD and generate snapshot for caching
232+ if : steps.avd-cache.outputs.cache-hit != 'true'
233+ uses : reactivecircus/android-emulator-runner@v2
234+ with :
235+ api-level : 33
236+ target : google_apis
237+ arch : x86_64
238+ profile : pixel_7_pro
239+ force-avd-creation : false
240+ ram-size : 4096M
241+ emulator-boot-timeout : 1800
242+ disable-animations : false
56243 emulator-options : >
57244 -no-window
58245 -gpu swiftshader_indirect
59246 -no-boot-anim
60247 -noaudio
61248 -camera-back none
62249 -camera-front none
250+ script : echo "Generated AVD snapshot for caching."
251+
252+ - name : Run instrumentation tests with coverage (shard ${{ matrix.shard }}/5)
253+ uses : reactivecircus/android-emulator-runner@v2
254+ with :
255+ api-level : 33
256+ target : google_apis
257+ arch : x86_64
258+ profile : pixel_7_pro
259+ force-avd-creation : false
260+ ram-size : 4096M
261+ emulator-boot-timeout : 1800
262+ disable-animations : true
263+ emulator-options : >
63264 -no-snapshot-save
64- script : ./gradlew :superwall:jacocoFullReport
265+ -no-window
266+ -gpu swiftshader_indirect
267+ -no-boot-anim
268+ -noaudio
269+ -camera-back none
270+ -camera-front none
271+ script : >
272+ ./gradlew :superwall:connectedDebugAndroidTest
273+ -Pandroid.testInstrumentationRunnerArguments.numShards=5
274+ -Pandroid.testInstrumentationRunnerArguments.shardIndex=${{ matrix.shard }}
275+ -x lint -x lintDebug -x lintVitalRelease
65276
66- - name : Build test project
67- run : ./gradlew :app:assembleAndroidTest -DtestBuildType=debug
277+ - name : Upload instrumentation test coverage data
278+ uses : actions/upload-artifact@v4
279+ if : always()
280+ with :
281+ name : instrumentation-test-coverage-shard-${{ matrix.shard }}
282+ path : superwall/build/outputs/code_coverage/
68283
69- - name : Upload test reports
284+ - name : Upload instrumentation test reports
70285 uses : actions/upload-artifact@v4
71286 if : always()
72287 with :
73- name : test-reports
288+ name : instrumentation- test-reports-shard-${{ matrix.shard }}
74289 path : |
75- **/build/reports/tests/
76- **/build/test-results/
77- **/build/reports/androidTests/connected/
78- **/build/outputs/code_coverage/
290+ superwall/build/reports/androidTests/connected/
291+ superwall/build/outputs/androidTest-results/
292+
293+ coverage-report :
294+ runs-on : ubuntu-latest
295+ needs : [unit-tests, instrumentation-tests]
296+ # Run as long as unit-tests succeeded, even if some/all instrumentation
297+ # shards failed — a partial report is better than no report or badge update.
298+ if : ${{ !cancelled() && needs.unit-tests.result == 'success' }}
299+
300+ steps :
301+ - uses : actions/checkout@v4
302+ with :
303+ ref : ${{ github.head_ref }}
304+ token : ${{ secrets.GITHUB_TOKEN }}
305+
306+ - name : Set up JDK 17
307+ uses : actions/setup-java@v4
308+ with :
309+ java-version : ' 17'
310+ distribution : ' temurin'
311+
312+ - name : Setup Gradle
313+ uses : gradle/actions/setup-gradle@v3
314+
315+ - name : Change wrapper permissions
316+ run : chmod +x ./gradlew
317+
318+ - name : Download unit test coverage data
319+ uses : actions/download-artifact@v4
320+ with :
321+ name : unit-test-coverage
322+ path : superwall/build/jacoco/
323+
324+ - name : Download instrumentation test coverage data (all shards)
325+ uses : actions/download-artifact@v4
326+ with :
327+ pattern : instrumentation-test-coverage-shard-*
328+ path : superwall/build/outputs/code_coverage/
329+
330+ - name : Generate combined coverage report
331+ run : ./gradlew :superwall:compileDebugSources :superwall:jacocoTestReport -x testDebugUnitTest -x lint -x lintDebug -x lintVitalRelease
79332
80333 - name : Upload coverage report
81334 uses : actions/upload-artifact@v4
@@ -107,10 +360,3 @@ jobs:
107360 git commit -m "Update coverage badge [skip ci]"
108361 git push origin HEAD:${{ github.head_ref }}
109362 fi
110-
111- - name : Run tests on Firebase Test Lab
112- uses : asadmansr/Firebase-Test-Lab-Action@v1.0
113- with :
114- arg-spec : ' .github/firebase-tests.yml:android-pixel-7'
115- env :
116- SERVICE_ACCOUNT : ${{ secrets.SERVICE_ACCOUNT }}
0 commit comments