11# Android APK build (debug + optional release).
22#
3- # The Vite frontend and offline Reticulum manual are produced by the reusable
4- # Frontend build workflow and downloaded into meshchatx/public/. This avoids
5- # re-running the full pnpm install + build pipeline alongside the much heavier
6- # Android NDK/wheel build steps.
7- #
83# Pinned first-party actions (bump tag and SHA together when upgrading):
94# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8
105# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
2116 push :
2217 branches :
2318 - dev
19+ tags :
20+ - " *"
2421 workflow_dispatch :
2522 inputs :
2623 build_release :
7067 needs : frontend
7168 timeout-minutes : 90
7269 permissions :
73- contents : read
70+ contents : write
7471 actions : write
7572 defaults :
7673 run :
8077 steps :
8178 - name : Checkout
8279 uses : actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
80+ with :
81+ fetch-depth : 0
82+
83+ - name : Resolve tag release track
84+ id : track
85+ if : github.ref_type == 'tag'
86+ run : |
87+ set -euo pipefail
88+ git fetch --no-tags origin dev master
89+ sha="$(git rev-parse HEAD)"
90+ on_m=false
91+ on_d=false
92+ while IFS= read -r line; do
93+ ref="$(printf '%s' "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
94+ case "$ref" in
95+ origin/master) on_m=true ;;
96+ origin/dev) on_d=true ;;
97+ esac
98+ done < <(git branch -r --contains "${sha}")
99+ if [[ "${on_m}" == true ]]; then
100+ track=master
101+ elif [[ "${on_d}" == true ]]; then
102+ track=dev
103+ else
104+ track=none
105+ fi
106+ echo "track=${track}" >> "${GITHUB_OUTPUT}"
107+ echo "Resolved tag ${GITHUB_REF_NAME} -> track=${track}"
108+
109+ - name : Detect Android release signing secrets
110+ id : android_signing
111+ env :
112+ KS_B64 : ${{ secrets.ANDROID_SIGNING_KEYSTORE_BASE64 }}
113+ KS_PASS : ${{ secrets.ANDROID_SIGNING_KEYSTORE_PASSWORD }}
114+ KS_ALIAS : ${{ secrets.ANDROID_SIGNING_KEY_ALIAS }}
115+ run : |
116+ set -euo pipefail
117+ if [[ -n "${KS_B64}" && -n "${KS_PASS}" && -n "${KS_ALIAS}" ]]; then
118+ echo "ready=true" >> "${GITHUB_OUTPUT}"
119+ else
120+ echo "ready=false" >> "${GITHUB_OUTPUT}"
121+ fi
122+
123+ - name : Require signing secrets for master release tags
124+ if : ${{ github.ref_type == 'tag' && steps.track.outputs.track == 'master' && steps.android_signing.outputs.ready != 'true' }}
125+ run : |
126+ echo "::error::Tagged master build needs release signing. Set secrets ANDROID_SIGNING_KEYSTORE_BASE64, ANDROID_SIGNING_KEYSTORE_PASSWORD, and ANDROID_SIGNING_KEY_ALIAS (see workflow header)."
127+ exit 1
83128
84129 - name : Set up Java
85130 uses : actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00
@@ -186,18 +231,34 @@ jobs:
186231 ./gradlew --no-daemon :app:testDebugUnitTest
187232
188233 - name : Build debug APK
234+ if : ${{ github.ref_type != 'tag' || steps.track.outputs.track != 'master' }}
189235 working-directory : android
190236 run : |
191237 chmod +x gradlew
192238 ./gradlew --no-daemon :app:assembleDebug
193239
194240 - name : Build release APK
195- if : ${{ github.event_name != 'workflow_dispatch' || inputs.build_release }}
241+ if : ${{ ( github.ref_type == 'tag' && steps.track.outputs.track == 'master') || (github.ref_type != 'tag' && (github. event_name != 'workflow_dispatch' || inputs.build_release)) }}
196242 working-directory : android
197243 run : |
198244 chmod +x gradlew
199245 ./gradlew --no-daemon :app:assembleRelease
200246
247+ - name : Sign release APKs
248+ if : ${{ github.ref_type == 'tag' && steps.track.outputs.track == 'master' && steps.android_signing.outputs.ready == 'true' }}
249+ env :
250+ KS_B64 : ${{ secrets.ANDROID_SIGNING_KEYSTORE_BASE64 }}
251+ SIGNING_KEYSTORE_PATH : ${{ runner.temp }}/meshchatx-release.jks
252+ SIGNING_KEY_ALIAS : ${{ secrets.ANDROID_SIGNING_KEY_ALIAS }}
253+ SIGNING_KEYSTORE_PASSWORD : ${{ secrets.ANDROID_SIGNING_KEYSTORE_PASSWORD }}
254+ SIGNING_KEY_PASSWORD : ${{ secrets.ANDROID_SIGNING_KEY_PASSWORD }}
255+ run : |
256+ set -euo pipefail
257+ printf '%s' "${KS_B64}" | base64 -d > "${SIGNING_KEYSTORE_PATH}"
258+ export SIGNING_KEYSTORE_PATH SIGNING_KEY_ALIAS SIGNING_KEYSTORE_PASSWORD
259+ export SIGNING_KEY_PASSWORD="${SIGNING_KEY_PASSWORD:-${SIGNING_KEYSTORE_PASSWORD}}"
260+ bash scripts/sign-android-apks.sh
261+
201262 - name : Upload wheels
202263 uses : actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
203264 with :
@@ -206,6 +267,7 @@ jobs:
206267 if-no-files-found : error
207268
208269 - name : Upload debug APK
270+ if : ${{ github.ref_type != 'tag' || steps.track.outputs.track != 'master' }}
209271 uses : actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
210272 with :
211273 name : meshchatx-android-debug-${{ github.ref_name }}-${{ github.run_id }}
@@ -223,9 +285,32 @@ jobs:
223285 if-no-files-found : warn
224286
225287 - name : Upload release APK
226- if : ${{ github.event_name != 'workflow_dispatch' || inputs.build_release }}
288+ if : ${{ ( github.ref_type == 'tag' && steps.track.outputs.track == 'master') || (github.ref_type != 'tag' && (github. event_name != 'workflow_dispatch' || inputs.build_release)) }}
227289 uses : actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
228290 with :
229291 name : meshchatx-android-release-${{ github.ref_name }}-${{ github.run_id }}
230292 path : android/app/build/outputs/apk/release/*.apk
231293 if-no-files-found : error
294+
295+ - name : Upload APKs to GitHub release
296+ if : ${{ github.ref_type == 'tag' && (steps.track.outputs.track == 'dev' || steps.track.outputs.track == 'master') }}
297+ env :
298+ GH_TOKEN : ${{ github.token }}
299+ run : |
300+ set -euo pipefail
301+ dir="${RUNNER_TEMP}/android-gh-release"
302+ rm -rf "${dir}"
303+ mkdir -p "${dir}"
304+ if [[ "${{ steps.track.outputs.track }}" == "dev" ]]; then
305+ cp -v android/app/build/outputs/apk/debug/*.apk "${dir}/"
306+ else
307+ shopt -s nullglob
308+ signed=(android/app/build/outputs/apk/release/*-signed.apk)
309+ shopt -u nullglob
310+ if [[ ${#signed[@]} -eq 0 ]]; then
311+ echo "::error::Expected *-signed.apk under android/app/build/outputs/apk/release/" >&2
312+ exit 1
313+ fi
314+ cp -v "${signed[@]}" "${dir}/"
315+ fi
316+ bash scripts/ci/github-draft-release-upload-assets.sh "${dir}"
0 commit comments