1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
name: Android CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x android-app/gradlew
- name: Build with Gradle
run: ./gradlew assembleDebug assembleDebugAndroidTest
working-directory: android-app
- name: Upload test APKs (shared with smoke-test job)
uses: actions/upload-artifact@v4
with:
name: test-apks
path: |
android-app/app/build/outputs/apk/debug/app-debug.apk
android-app/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
- name: upload artifact to Firebase App Distribution
if: github.ref == 'refs/heads/main'
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{secrets.FIREBASE_APP_ID}}
serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }}
groups: testers
file: android-app/app/build/outputs/apk/debug/app-debug.apk
- name: Notify claudomator
if: always()
env:
CLAUDOMATOR_WEBHOOK_URL: ${{ secrets.CLAUDOMATOR_WEBHOOK_URL }}
CLAUDOMATOR_WEBHOOK_SECRET: ${{ secrets.CLAUDOMATOR_WEBHOOK_SECRET }}
run: |
PAYLOAD=$(jq -n \
--arg action "completed" \
--arg conclusion "${{ job.status }}" \
--arg name "${{ github.workflow }}" \
--arg repo "${{ github.repository }}" \
--arg sha "${{ github.sha }}" \
--arg run_id "${{ github.run_id }}" \
'{action: $action, workflow_run: {conclusion: $conclusion, name: $name, head_sha: $sha, id: ($run_id | tonumber)}, repository: {full_name: $repo}}')
SIG=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$CLAUDOMATOR_WEBHOOK_SECRET" | awk '{print $2}')
curl -sf -X POST \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: workflow_run" \
-H "X-Hub-Signature-256: sha256=${SIG}" \
"${CLAUDOMATOR_WEBHOOK_URL}/api/webhooks/github" \
-d "$PAYLOAD"
smoke-test:
runs-on: ubuntu-latest
# Run after build succeeds — no point spinning up an emulator for a broken build
needs: build
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x android-app/gradlew
# Restore pre-built APKs so the emulator job skips the compile step
- name: Download test APKs
uses: actions/download-artifact@v4
with:
name: test-apks
path: . # preserves android-app/app/build/outputs/… directory structure
- name: Enable KVM (faster emulator)
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
# -x assembleDebug -x assembleDebugAndroidTest: skip recompile, use downloaded APKs
- name: Run smoke tests on emulator
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 30
arch: x86_64
profile: pixel_3a
script: ./gradlew connectedDebugAndroidTest -x assembleDebug -x assembleDebugAndroidTest
working-directory: android-app
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: smoke-test-results
path: android-app/app/build/outputs/androidTest-results/
- name: Notify claudomator
if: always()
env:
CLAUDOMATOR_WEBHOOK_URL: ${{ secrets.CLAUDOMATOR_WEBHOOK_URL }}
CLAUDOMATOR_WEBHOOK_SECRET: ${{ secrets.CLAUDOMATOR_WEBHOOK_SECRET }}
run: |
PAYLOAD=$(jq -n \
--arg action "completed" \
--arg conclusion "${{ job.status }}" \
--arg name "${{ github.workflow }} / smoke-test" \
--arg repo "${{ github.repository }}" \
--arg sha "${{ github.sha }}" \
--arg run_id "${{ github.run_id }}" \
'{action: $action, workflow_run: {conclusion: $conclusion, name: $name, head_sha: $sha, id: ($run_id | tonumber)}, repository: {full_name: $repo}}')
SIG=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$CLAUDOMATOR_WEBHOOK_SECRET" | awk '{print $2}')
curl -sf -X POST \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: workflow_run" \
-H "X-Hub-Signature-256: sha256=${SIG}" \
"${CLAUDOMATOR_WEBHOOK_URL}/api/webhooks/github" \
-d "$PAYLOAD"
|