@@ -180,7 +180,6 @@ jobs:
180180 fi
181181
182182 mkdir -p "$OUT_DIR"
183-
184183 DMG_PATH="${OUT_DIR}/GenyConnect-${VERSION}-macos-${{ matrix.target_arch }}.dmg"
185184
186185 xattr -cr "$APP" || true
@@ -210,7 +209,6 @@ jobs:
210209 codesign --verify --deep --strict --verbose=4 "$APP"
211210
212211 STAGING="$(mktemp -d)"
213-
214212 cp -R "$APP" "$STAGING/GenyConnect.app"
215213 ln -s /Applications "$STAGING/Applications"
216214
@@ -222,7 +220,6 @@ jobs:
222220 "$DMG_PATH"
223221
224222 rm -rf "$STAGING"
225-
226223 hdiutil verify "$DMG_PATH"
227224
228225 - name : Verify macOS package
@@ -233,6 +230,11 @@ jobs:
233230
234231 DMG="$(find build/final -type f -name "*.dmg" | head -n 1)"
235232
233+ if [[ -z "$DMG" ]]; then
234+ echo "No DMG found."
235+ exit 1
236+ fi
237+
236238 hdiutil verify "$DMG"
237239
238240 - name : Package Windows
@@ -268,16 +270,6 @@ jobs:
268270 name : ${{ matrix.artifact_name }}
269271 path : artifacts/*
270272
271- - name : Release desktop
272- if : startsWith(github.ref, 'refs/tags/')
273- uses : softprops/action-gh-release@v2
274- env :
275- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
276- with :
277- files : artifacts/*
278- fail_on_unmatched_files : true
279- generate_release_notes : true
280-
281273 android :
282274 name : Build GenyConnect-android-arm64-v8a
283275 if : github.event_name != 'pull_request'
@@ -318,7 +310,10 @@ jobs:
318310 "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
319311 "ndk;${ANDROID_NDK_VERSION}"
320312
313+ echo "ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}" >> "${GITHUB_ENV}"
314+ echo "ANDROID_HOME=${ANDROID_SDK_ROOT}" >> "${GITHUB_ENV}"
321315 echo "ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk/${ANDROID_NDK_VERSION}" >> "${GITHUB_ENV}"
316+ echo "ANDROID_NDK_HOME=${ANDROID_SDK_ROOT}/ndk/${ANDROID_NDK_VERSION}" >> "${GITHUB_ENV}"
322317
323318 - name : Install Qt Android
324319 uses : jurplel/install-qt-action@v4
@@ -328,7 +323,7 @@ jobs:
328323 arch : ${{ env.QT_ARCH }}
329324 cache : true
330325
331- - name : Save Qt paths
326+ - name : Save Qt Android and host paths
332327 shell : bash
333328 run : |
334329 set -euo pipefail
@@ -344,6 +339,7 @@ jobs:
344339 - name : Install Linux dependencies
345340 shell : bash
346341 run : |
342+ set -euo pipefail
347343 sudo apt-get update
348344 sudo apt-get install -y ninja-build unzip zip p7zip-full curl file
349345
@@ -357,62 +353,120 @@ jobs:
357353 run : |
358354 set -euo pipefail
359355
360- mkdir -p "${RUNNER_TEMP}/android-signing"
356+ if [[ -z "${ANDROID_KEYSTORE_BASE64}" || -z "${ANDROID_KEYSTORE_PASSWORD}" || -z "${ANDROID_KEY_ALIAS}" || -z "${ANDROID_KEY_PASSWORD}" ]]; then
357+ echo "Android signing secrets are incomplete."
358+ exit 1
359+ fi
361360
361+ mkdir -p "${RUNNER_TEMP}/android-signing"
362362 echo "${ANDROID_KEYSTORE_BASE64}" | base64 --decode > "${RUNNER_TEMP}/android-signing/release.keystore"
363+ test -s "${RUNNER_TEMP}/android-signing/release.keystore"
363364
364365 echo "QT_ANDROID_KEYSTORE_PATH=${RUNNER_TEMP}/android-signing/release.keystore" >> "${GITHUB_ENV}"
365366 echo "QT_ANDROID_KEYSTORE_ALIAS=${ANDROID_KEY_ALIAS}" >> "${GITHUB_ENV}"
366367 echo "QT_ANDROID_KEYSTORE_STORE_PASS=${ANDROID_KEYSTORE_PASSWORD}" >> "${GITHUB_ENV}"
367368 echo "QT_ANDROID_KEYSTORE_KEY_PASS=${ANDROID_KEY_PASSWORD}" >> "${GITHUB_ENV}"
368369
369- - name : Configure Android
370+ - name : Configure Android module scanner
370371 shell : bash
371372 run : |
372373 set -euo pipefail
373374
374375 SCAN_DEPS="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-scan-deps"
375376
377+ if [[ ! -x "${SCAN_DEPS}" ]]; then
378+ echo "clang-scan-deps not found: ${SCAN_DEPS}"
379+ find "${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin" -maxdepth 1 -type f | sort
380+ exit 1
381+ fi
382+
383+ echo "CLANG_SCAN_DEPS=${SCAN_DEPS}" >> "${GITHUB_ENV}"
384+
385+ - name : Configure Android Release
386+ shell : bash
387+ run : |
388+ set -euo pipefail
389+
376390 cmake -S . -B build -G Ninja \
377391 -DCMAKE_BUILD_TYPE=Release \
378392 -DCMAKE_PREFIX_PATH="${ANDROID_QT_ROOT}" \
379393 -DQt6_DIR="${ANDROID_QT_ROOT}/lib/cmake/Qt6" \
380394 -DQT_HOST_PATH="${QT_HOST_ROOT}" \
395+ -DQT_HOST_PATH_CMAKE_DIR="${QT_HOST_ROOT}/lib/cmake" \
381396 -DQT_ANDROID_BUILD_TYPE=Release \
382397 -DQT_ANDROID_DEPLOY_RELEASE=ON \
383398 -DQT_ANDROID_SIGN_APK=ON \
384399 -DQT_ANDROID_SIGN_AAB=ON \
400+ -DQT_ANDROID_KEYSTORE_PATH="${QT_ANDROID_KEYSTORE_PATH}" \
401+ -DQT_ANDROID_KEYSTORE_ALIAS="${QT_ANDROID_KEYSTORE_ALIAS}" \
402+ -DQT_ANDROID_KEYSTORE_STORE_PASS="${QT_ANDROID_KEYSTORE_STORE_PASS}" \
403+ -DQT_ANDROID_KEYSTORE_KEY_PASS="${QT_ANDROID_KEYSTORE_KEY_PASS}" \
385404 -DCMAKE_TOOLCHAIN_FILE="${ANDROID_QT_ROOT}/lib/cmake/Qt6/qt.toolchain.cmake" \
386405 -DCMAKE_CXX_SCAN_FOR_MODULES=ON \
387- -DCMAKE_CXX_COMPILER_CLANG_SCAN_DEPS="${SCAN_DEPS }" \
406+ -DCMAKE_CXX_COMPILER_CLANG_SCAN_DEPS="${CLANG_SCAN_DEPS }" \
388407 -DANDROID_ABI="${ANDROID_ABI}" \
389408 -DANDROID_PLATFORM="android-${ANDROID_API}" \
390409 -DANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" \
391410 -DANDROID_NDK_ROOT="${ANDROID_NDK_ROOT}" \
392411 -DQT_ANDROID_ABIS="${ANDROID_ABI}" \
412+ -DGENYCONNECT_BUILD_DESKTOP=OFF \
393413 -DGENYCONNECT_BUILD_ANDROID=ON \
394414 -DGENYCONNECT_ENABLE_MOBILE_VPN=ON \
395- -DGENYCONNECT_USE_MODULES=ON
415+ -DGENYCONNECT_AUTO_DOWNLOAD_XRAY=ON \
416+ -DGENYCONNECT_USE_MODULES=ON \
417+ -DGENYCONNECT_TARGET_OS=android \
418+ -DGENYCONNECT_TARGET_ARCH="${TARGET_ARCH}" \
419+ -DGENYCONNECT_TARGET_BUILD_ARCH="${TARGET_ARCH}"
396420
397421 - name : Build Android APK
398422 shell : bash
399423 run : |
424+ set -euo pipefail
400425 cmake --build build --config Release --target apk --parallel
401426
402427 - name : Build Android AAB
403428 shell : bash
404429 run : |
430+ set -euo pipefail
405431 cmake --build build --config Release --target aab --parallel
406432
433+ - name : Normalize Android artifact names
434+ shell : bash
435+ run : |
436+ set -euo pipefail
437+
438+ OUT_DIR="build/final/android-${ANDROID_OUTPUT_ARCH}"
439+ mkdir -p "${OUT_DIR}"
440+
441+ if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
442+ VERSION="${GITHUB_REF_NAME#v}"
443+ else
444+ VERSION="$(grep -E 'project\(\$\{PROJECT_NAME\} VERSION ' CMakeLists.txt | sed -E 's/.*VERSION ([0-9]+\.[0-9]+\.[0-9]+).*/\1/')"
445+ fi
446+
447+ APK="$(find build -type f \( -name "*release*.apk" -o -name "*.apk" \) | grep -vi debug | sort | head -n 1)"
448+ AAB="$(find build -type f \( -name "*release*.aab" -o -name "*.aab" \) | grep -vi debug | sort | head -n 1)"
449+
450+ cp "${APK}" "${OUT_DIR}/GenyConnect-${VERSION}-android-${ANDROID_OUTPUT_ARCH}.apk"
451+ cp "${AAB}" "${OUT_DIR}/GenyConnect-${VERSION}-android-${ANDROID_OUTPUT_ARCH}.aab"
452+
453+ ls -lah "${OUT_DIR}"
454+
407455 - name : Collect Android packages
408456 shell : bash
409457 run : |
410458 set -euo pipefail
411459
412460 mkdir -p artifacts
413461
414- find build -type f -name "*.apk" -exec cp {} artifacts/ \;
415- find build -type f -name "*.aab" -exec cp {} artifacts/ \;
462+ find build/final -type f -name "*.apk" -exec cp {} artifacts/ \;
463+ find build/final -type f -name "*.aab" -exec cp {} artifacts/ \;
464+
465+ if [ -z "$(find artifacts -type f -print -quit)" ]; then
466+ echo "No Android artifacts found."
467+ find build -maxdepth 8 -type f | sort | tail -300
468+ exit 1
469+ fi
416470
417471 ls -lah artifacts
418472
@@ -422,12 +476,35 @@ jobs:
422476 name : GenyConnect-android-arm64-v8a
423477 path : artifacts/*
424478
425- - name : Release Android
426- if : startsWith(github.ref, 'refs/tags/')
479+ release :
480+ name : Publish GitHub Release
481+ if : startsWith(github.ref, 'refs/tags/')
482+ needs :
483+ - desktop
484+ - android
485+ runs-on : ubuntu-latest
486+
487+ permissions :
488+ contents : write
489+
490+ steps :
491+ - name : Download all artifacts
492+ uses : actions/download-artifact@v4
493+ with :
494+ path : release-artifacts
495+ merge-multiple : true
496+
497+ - name : List release files
498+ shell : bash
499+ run : |
500+ set -euo pipefail
501+ find release-artifacts -type f | sort
502+
503+ - name : Publish release
427504 uses : softprops/action-gh-release@v2
428505 env :
429- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
506+ GITHUB_TOKEN : ${{ github.token }}
430507 with :
431- files : artifacts/*
508+ files : release- artifacts/*
432509 fail_on_unmatched_files : true
433510 generate_release_notes : true
0 commit comments