name: 'Deploy workflow' on: push: branches: - '**' env: QT_MIRROR: https://mirrors.ocf.berkeley.edu/qt/ # https://download.qt.io/static/mirrorlist/ jobs: Detect-Changes: runs-on: ubuntu-latest outputs: recipes_changed: ${{ steps.filter.outputs.recipes }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: base: ${{ github.event.before }} filters: | recipes: - 'recipes/**' - 'conanfile.py' Bake-Prebuilts-Linux: runs-on: ubuntu-latest needs: Detect-Changes if: needs.Detect-Changes.outputs.recipes_changed == 'true' steps: - uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build dependencies' shell: bash run: | for build_type in Release Debug; do cmake -S . -B build -DPREBUILTS_ONLY=1 "-DCMAKE_BUILD_TYPE=$build_type" done - name: 'Authorize in remote' run: conan remote login amnezia "${{ secrets.CONAN_USER }}" -p "${{ secrets.CONAN_PASSWORD }}" - name: 'Upload baked prebuilts' run: conan upload -r amnezia "*" -c # ------------------------------------------------------ Build-Linux-Ubuntu: runs-on: android-runner needs: Bake-Prebuilts-Linux if: ${{ always() }} env: QT_VERSION: 6.10.1 QIF_VERSION: 4.7 PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} FALLBACK_S3_ENDPOINT: ${{ secrets.FALLBACK_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Install Qt' uses: jurplel/install-qt-action@v3 with: version: ${{ env.QT_VERSION }} host: 'linux' target: 'desktop' arch: 'linux_gcc_64' modules: 'qtremoteobjects qt5compat qtshadertools' dir: ${{ runner.temp }} setup-python: 'true' tools: 'tools_ifw' set-env: 'true' aqtversion: '==3.3.0' py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Setup python' uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Install system packages' run: sudo apt-get install libxkbcommon-x11-0 libsecret-1-dev - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - name: 'Build project' shell: bash env: QT_INSTALL_DIR: ${{ runner.temp }} run: deploy/build.sh --generator Ninja --installer all - name: 'Upload installer artifact' uses: actions/upload-artifact@v7 with: path: deploy/build/AmneziaVPN-*-Linux.run archive: false retention-days: 7 - name: 'Upload translations artifact' uses: actions/upload-artifact@v4 with: name: AmneziaVPN_translations path: client/translations retention-days: 7 # ------------------------------------------------------ Bake-Prebuilts-Windows: runs-on: windows-latest needs: Detect-Changes if: needs.Detect-Changes.outputs.recipes_changed == 'true' steps: - uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: actions/setup-python@v6 with: python-version: 3.14 - uses: ilammy/msvc-dev-cmd@v1 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build dependencies' run: cmake -S . -B build -G "Visual Studio 17 2022" -DPREBUILTS_ONLY=1 - name: 'Authorize in remote' run: conan remote login amnezia "${{ secrets.CONAN_USER }}" -p "${{ secrets.CONAN_PASSWORD }}" - name: 'Upload baked prebuilts' run: conan upload -r amnezia "*" -c # ------------------------------------------------------ Build-Windows: runs-on: windows-latest needs: Bake-Prebuilts-Windows if: ${{ always() }} env: QT_VERSION: 6.10.1 QIF_VERSION: 4.7 PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} FALLBACK_S3_ENDPOINT: ${{ secrets.FALLBACK_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - name: 'Install Qt' uses: jurplel/install-qt-action@v3 with: version: ${{ env.QT_VERSION }} host: 'windows' target: 'desktop' arch: 'win64_msvc2022_64' modules: 'qtremoteobjects qt5compat qtshadertools' dir: ${{ runner.temp }} setup-python: 'true' tools: 'tools_ifw' set-env: 'true' aqtversion: '==3.3.0' py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Setup mvsc' uses: ilammy/msvc-dev-cmd@v1 with: arch: 'x64' - name: 'Setup .NET SDK' uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - name: 'Install WiX Toolset' shell: powershell run: | dotnet tool install --global wix --version 4.0.6 wix extension add -g WixToolset.UI.wixext/4.0.6 wix extension add -g WixToolset.Util.wixext/4.0.6 wix extension list -g $wixBinDir = Join-Path $env:USERPROFILE ".dotnet\tools" echo "WIX_BIN_DIR=$wixBinDir" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: 'Setup python' uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build project' shell: cmd env: QT_INSTALL_DIR: ${{ runner.temp }} run: | set WIX_ROOT_PATH="${{ env.USERPROFILE }}\.dotnet\tools" deploy\build.bat --installer all - name: 'Upload WIX installer artifact' uses: actions/upload-artifact@v7 with: path: deploy/build/AmneziaVPN-*-win64.msi archive: false retention-days: 7 - name: 'Upload IFW installer artifact' uses: actions/upload-artifact@v7 with: path: deploy/build/AmneziaVPN-*-win64.exe archive: false retention-days: 7 # ------------------------------------------------------ Bake-Prebuilts-iOS: runs-on: macos-latest needs: Detect-Changes if: needs.Detect-Changes.outputs.recipes_changed == 'true' strategy: matrix: xcode-version: [26.0] steps: - uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: actions/setup-python@v6 with: python-version: 3.14 - uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: ${{ matrix.xcode-version }} - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build dependencies' run: cmake -S . -B build -G Xcode -DPREBUILTS_ONLY=1 -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos - name: 'Authorize in remote' run: conan remote login amnezia "${{ secrets.CONAN_USER }}" -p "${{ secrets.CONAN_PASSWORD }}" - name: 'Upload baked prebuilts' run: conan upload -r amnezia "*" -c # ------------------------------------------------------ Build-iOS: runs-on: macos-latest needs: Bake-Prebuilts-iOS if: ${{ always() }} env: QT_VERSION: 6.10.1 KEYCHAIN_PASSWORD: "" PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} FALLBACK_S3_ENDPOINT: ${{ secrets.FALLBACK_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: ./.github/actions/apple-setup-keychain id: setup-keychain with: keychain-password: ${{ env.KEYCHAIN_PASSWORD }} - name: 'Install signing certificate' uses: ./.github/actions/apple-install-cert with: keychain-path: ${{ steps.setup-keychain.outputs.keychain-path }} keychain-password: ${{ env.KEYCHAIN_PASSWORD }} cert-base64: ${{ secrets.IOS_SIGNING_CERT_BASE64 }} cert-password: ${{ secrets.IOS_SIGNING_CERT_PASSWORD }} - name: 'Install app provisioning profile' uses: ./.github/actions/apple-setup-provisioning-profile with: provisioning_profile_base64: ${{ secrets.IOS_APP_PROVISIONING_PROFILE }} - name: 'Install NE provisioning profile' uses: ./.github/actions/apple-setup-provisioning-profile with: provisioning_profile_base64: ${{ secrets.IOS_NE_PROVISIONING_PROFILE }} - name: 'Setup xcode' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '26.1' - name: 'Install desktop Qt' uses: jurplel/install-qt-action@v3 with: version: ${{ env.QT_VERSION }} host: 'mac' target: 'desktop' modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia' arch: 'clang_64' dir: ${{ runner.temp }} set-env: 'true' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Install iOS Qt' uses: jurplel/install-qt-action@v3 with: version: ${{ env.QT_VERSION }} host: 'mac' target: 'ios' modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia' dir: ${{ runner.temp }} setup-python: 'true' set-env: 'true' extra: '--external 7z --base ${{ env.QT_MIRROR }}' - name: 'Setup python' uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install deps' run: pip install "conan==2.26.2" jsonschema jinja2 - name: 'Build project' env: QT_INSTALL_DIR: ${{ runner.temp }} APPSTORE_CONNECT_KEY_ID: ${{ secrets.APPSTORE_CONNECT_KEY_ID }} APPSTORE_CONNECT_ISSUER_ID: ${{ secrets.APPSTORE_CONNECT_ISSUER_ID }} APPSTORE_CONNECT_PRIVATE_KEY: ${{ secrets.APPSTORE_CONNECT_PRIVATE_KEY }} run: | sh deploy/build.sh -t ios | \ sed -e '/-Xcc -DPROD_AGW_PUBLIC_KEY/,/-Xcc/ { /-Xcc/!d; }' -e '/-Xcc -DPROD_AGW_PUBLIC_KEY/d' | \ sed -e '/-Xcc -DDEV_AGW_PUBLIC_KEY/,/-Xcc/ { /-Xcc/!d; }' -e '/-Xcc -DDEV_AGW_PUBLIC_KEY/d' | \ sed -e '/-DPROD_AGW_PUBLIC_KEY/,/-D/ { /-D/!d; }' -e '/-DPROD_AGW_PUBLIC_KEY/d' | \ sed -e '/-DDEV_AGW_PUBLIC_KEY/,/-D/ { /-D/!d; }' -e '/-DDEV_AGW_PUBLIC_KEY/d' # ------------------------------------------------------ Bake-Prebuilts-MacOS: runs-on: macos-latest needs: Detect-Changes if: needs.Detect-Changes.outputs.recipes_changed == 'true' strategy: matrix: xcode-version: [16.2, 16.4] steps: - uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: actions/setup-python@v6 with: python-version: 3.14 - uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: ${{ matrix.xcode-version }} - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build dependencies' run: cmake -S . -B build -G Xcode -DPREBUILTS_ONLY=1 - name: 'Authorize in remote' run: conan remote login amnezia "${{ secrets.CONAN_USER }}" -p "${{ secrets.CONAN_PASSWORD }}" - name: 'Upload baked prebuilts' run: conan upload -r amnezia "*" -c # ------------------------------------------------------ Build-MacOS: runs-on: macos-latest needs: Bake-Prebuilts-MacOS if: ${{ always() }} env: QT_VERSION: 6.10.1 KEYCHAIN_PASSWORD: "" PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} FALLBACK_S3_ENDPOINT: ${{ secrets.FALLBACK_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: ./.github/actions/apple-setup-keychain id: setup-keychain with: keychain-password: ${{ env.KEYCHAIN_PASSWORD }} - uses: ./.github/actions/apple-install-cert with: keychain-path: ${{ steps.setup-keychain.outputs.keychain-path }} keychain-password: ${{ env.KEYCHAIN_PASSWORD }} cert-base64: ${{ secrets.MAC_APP_CERT_CERT }} cert-password: ${{ secrets.MAC_APP_CERT_PW }} - uses: ./.github/actions/apple-install-cert with: keychain-path: ${{ steps.setup-keychain.outputs.keychain-path }} keychain-password: ${{ env.KEYCHAIN_PASSWORD }} cert-base64: ${{ secrets.MAC_INSTALLER_SIGNER_CERT }} cert-password: ${{ secrets.MAC_INSTALL_CERT_PW }} - name: 'Setup xcode' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '16.2.0' - name: 'Install Qt' uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} host: 'mac' target: 'desktop' arch: 'clang_64' modules: 'qtremoteobjects qt5compat qtshadertools' dir: ${{ runner.temp }} setup-python: 'true' set-env: 'true' aqtversion: '==3.3.0' py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Setup python' uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build project' env: QT_INSTALL_DIR: ${{ runner.temp }} CODESIGN_SIGNATURE: ${{ secrets.MAC_SIGNER_ID }} CODESIGN_INSTALLER_SIGNATURE: ${{ secrets.MAC_INSTALLER_SIGNER_ID }} NOTARYTOOL_TEAM_ID: ${{ secrets.MAC_TEAM_ID }} NOTARYTOOL_EMAIL: ${{ secrets.APPLE_DEV_EMAIL }} NOTARYTOOL_PASSWORD: ${{ secrets.APPLE_DEV_PASSWORD }} shell: bash run: deploy/build.sh --generator Ninja --installer all - name: 'Upload installer artifact' uses: actions/upload-artifact@v7 with: path: deploy/build/AmneziaVPN-*-Darwin.pkg archive: false retention-days: 7 # ------------------------------------------------------ Bake-Prebuilts-MacOS-NE: runs-on: macos-latest needs: Detect-Changes if: needs.Detect-Changes.outputs.recipes_changed == 'true' strategy: matrix: xcode-version: [16.2, 16.4] steps: - uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: actions/setup-python@v6 with: python-version: 3.14 - uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: ${{ matrix.xcode-version }} - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build dependencies' run: cmake -S . -B build -G Xcode -DPREBUILTS_ONLY=1 -DMACOS_NE=TRUE - name: 'Authorize in remote' run: conan remote login amnezia "${{ secrets.CONAN_USER }}" -p "${{ secrets.CONAN_PASSWORD }}" - name: 'Upload baked prebuilts' run: conan upload -r amnezia "*" -c # ------------------------------------------------------ Build-MacOS-NE: runs-on: macos-latest needs: Bake-Prebuilts-MacOS-NE if: ${{ always() }} env: QT_VERSION: 6.10.1 MAC_TEAM_ID: ${{ secrets.MAC_TEAM_ID }} MAC_APP_CERT_CERT: ${{ secrets.MAC_APP_CERT_CERT }} MAC_SIGNER_ID: ${{ secrets.MAC_SIGNER_ID }} MAC_APP_CERT_PW: ${{ secrets.MAC_APP_CERT_PW }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} FALLBACK_S3_ENDPOINT: ${{ secrets.FALLBACK_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - uses: ./.github/actions/apple-setup-provisioning-profile with: provisioning_profile_base64: ${{ secrets.MAC_APP_PROVISIONING_PROFILE }} - uses: ./.github/actions/apple-setup-provisioning-profile with: provisioning_profile_base64: ${{ secrets.MAC_NE_PROVISIONING_PROFILE }} - name: 'Setup xcode' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '26.1' - name: 'Install desktop Qt' uses: jurplel/install-qt-action@v3 with: version: ${{ env.QT_VERSION }} host: 'mac' target: 'desktop' modules: 'qtremoteobjects qt5compat qtshadertools qtmultimedia' arch: 'clang_64' dir: ${{ runner.temp }} set-env: 'true' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Install go' uses: actions/setup-go@v5 with: go-version: '1.24' cache: false - name: 'Setup gomobile' run: | export PATH=$PATH:~/go/bin go install golang.org/x/mobile/cmd/gomobile@latest gomobile init - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - name: 'Setup python' uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Build project' run: | export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin" bash deploy/build_macos_ne.sh - name: 'Upload unpacked artifact' uses: actions/upload-artifact@v4 with: name: AmneziaVPN_MacOS_unpacked path: deploy/build/client/AmneziaVPN.app retention-days: 7 # ------------------------------------------------------ Bake-Prebuilts-Android: runs-on: android-runner needs: Detect-Changes if: needs.Detect-Changes.outputs.recipes_changed == 'true' env: ANDROID_PLATFORM: android-28 NDK_VERSION: 27.0.11718014 steps: - uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Setup Android SDK' uses: android-actions/setup-android@v4 with: packages: "platforms;${{ env.ANDROID_PLATFORM }} ndk;${{ env.NDK_VERSION }}" - name: 'Build dependencies' run: | CMAKE_ANDROID_NDK="$ANDROID_HOME/ndk/$NDK_VERSION" args=( -G Ninja -DPREBUILTS_ONLY=1 -DCMAKE_SYSTEM_NAME=Android "-DANDROID_PLATFORM=$ANDROID_PLATFORM" "-DCMAKE_ANDROID_NDK=$CMAKE_ANDROID_NDK" ) for abi in arm64-v8a armeabi-v7a x86 x86_64; do for build_type in Release Debug; do cmake -S . -B build_${abi//-/_} "${args[@]}" "-DCMAKE_ANDROID_ARCH_ABI=$abi" "-DCMAKE_BUILD_TYPE=$build_type" done done - name: 'Authorize in remote' run: conan remote login amnezia "${{ secrets.CONAN_USER }}" -p "${{ secrets.CONAN_PASSWORD }}" - name: 'Upload baked prebuilts' run: conan upload -r amnezia "*" -c # ------------------------------------------------------ Build-Android: runs-on: android-runner needs: Bake-Prebuilts-Android if: ${{ always() }} env: ANDROID_PLATFORM: android-28 NDK_VERSION: 27.0.11718014 QT_VERSION: 6.10.1 QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools' PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} FALLBACK_S3_ENDPOINT: ${{ secrets.FALLBACK_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' - name: 'Install desktop Qt' uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} host: 'linux' target: 'desktop' arch: 'linux_gcc_64' modules: ${{ env.QT_MODULES }} dir: ${{ runner.temp }} py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Install android_x86_64 Qt' uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} host: 'linux' target: 'android' arch: 'android_x86_64' modules: ${{ env.QT_MODULES }} dir: ${{ runner.temp }} py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Install android_x86 Qt' uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} host: 'linux' target: 'android' arch: 'android_x86' modules: ${{ env.QT_MODULES }} dir: ${{ runner.temp }} py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Install android_armv7 Qt' uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} host: 'linux' target: 'android' arch: 'android_armv7' modules: ${{ env.QT_MODULES }} dir: ${{ runner.temp }} py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Install android_arm64_v8a Qt' uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} host: 'linux' target: 'android' arch: 'android_arm64_v8a' modules: ${{ env.QT_MODULES }} dir: ${{ runner.temp }} py7zrversion: '==0.22.*' extra: '--base ${{ env.QT_MIRROR }}' - name: 'Setup Java' uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' - name: 'Setup Android SDK' uses: android-actions/setup-android@v4 with: packages: "platforms;${{ env.ANDROID_PLATFORM }} ndk;${{ env.NDK_VERSION }}" - name: 'Setup python' uses: actions/setup-python@v6 with: python-version: 3.14 - name: 'Install conan' run: pip install "conan==2.26.2" - name: 'Decode keystore secret to file' env: KEYSTORE_BASE64: ${{ secrets.ANDROID_RELEASE_KEYSTORE_BASE64 }} shell: bash run: | echo $KEYSTORE_BASE64 | base64 --decode > android.keystore - name: 'Build project' env: QT_INSTALL_DIR: ${{ runner.temp }} QT_ANDROID_KEYSTORE_PATH: ${{ github.workspace }}/android.keystore QT_ANDROID_KEYSTORE_ALIAS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_ALIAS }} QT_ANDROID_KEYSTORE_STORE_PASS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_PASS }} shell: bash run: | deploy/build.sh -t android --sign --aab VERSION=$(grep CMAKE_PROJECT_VERSION:STATIC deploy/build/CMakeCache.txt | cut -d= -f2) (cd deploy/build/client/android-build && mv AmneziaVPN.apk AmneziaVPN_${VERSION}_android9+_universal.apk) (cd deploy/build/client/android-build/build/outputs/bundle/release && mv android-build-release.aab AmneziaVPN_${VERSION}.aab) for abi in arm64-v8a armeabi-v7a x86 x86_64; do deploy/build.sh -t android --sign --abi ${abi} --build ./deploy/build/${abi} (cd deploy/build/${abi}/client/android-build && mv AmneziaVPN.apk AmneziaVPN_${VERSION}_android9+_${abi}.apk) done - name: 'Upload universal APK' uses: actions/upload-artifact@v7 with: path: deploy/build/client/android-build/*.apk archive: false retention-days: 7 - name: 'Upload AAB' uses: actions/upload-artifact@v7 with: path: deploy/build/client/android-build/build/outputs/bundle/release/*.aab archive: false retention-days: 7 - name: 'Upload arm64-v8a APK' uses: actions/upload-artifact@v7 with: path: deploy/build/arm64-v8a/client/android-build/*.apk archive: false retention-days: 7 - name: 'Upload armeabi-v7a APK' uses: actions/upload-artifact@v7 with: path: deploy/build/armeabi-v7a/client/android-build/*.apk archive: false retention-days: 7 - name: 'Upload x86 APK' uses: actions/upload-artifact@v7 with: path: deploy/build/x86/client/android-build/*.apk archive: false retention-days: 7 - name: 'Upload x86_64 APK' uses: actions/upload-artifact@v7 with: path: deploy/build/x86_64/client/android-build/*.apk archive: false retention-days: 7 Extra: runs-on: ubuntu-latest steps: - name: Search a corresponding PR uses: octokit/request-action@v2.x id: pull_request with: route: GET /repos/${{ github.repository }}/pulls head: ${{ github.repository_owner }}:${{ github.ref_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Add PR link to build summary if: ${{ fromJSON(steps.pull_request.outputs.data)[0].number != '' }} run: | echo "Pull request:" >> $GITHUB_STEP_SUMMARY echo "[[#${{ fromJSON(steps.pull_request.outputs.data)[0].number }}] ${{ fromJSON(steps.pull_request.outputs.data)[0].title }}](${{ fromJSON(steps.pull_request.outputs.data)[0].html_url }})" >> $GITHUB_STEP_SUMMARY # ------------------------------------------------------ Test-Linux: runs-on: ubuntu-latest env: QT_VERSION: 6.10.1 steps: - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - name: 'Install Qt' uses: jurplel/install-qt-action@v3 with: version: ${{ env.QT_VERSION }} host: 'linux' target: 'desktop' arch: 'linux_gcc_64' modules: 'qtremoteobjects qt5compat qtshadertools' dir: ${{ runner.temp }} set-env: 'true' - name: 'Install dependencies' run: | sudo apt-get update sudo apt-get install -y \ cmake \ ninja-build \ libsecret-1-dev \ libxcb-cursor0 \ libxkbcommon-x11-0 \ libxcb-xinerama0 \ libxcb-icccm4 \ libxcb-image0 \ libxcb-keysyms1 \ libxcb-randr0 \ libxcb-render-util0 \ libxcb-xfixes0 \ libxcb-shape0 \ libxcb-sync1 \ libxcb-xkb1 \ libgl1 \ libglib2.0-0 - name: 'Configure' run: | cmake -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=ON - name: 'Build' run: cmake --build build - name: 'Run tests' run: | QT_ROOT=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:\ $QT_ROOT/lib:\ $PWD/client/3rd-prebuilt/deploy-prebuilt/linux/x64 export QT_QPA_PLATFORM=offscreen ctest --test-dir build/client --output-on-failure # ------------------------------------------------------ Test-Windows: runs-on: windows-latest env: QT_VERSION: 6.10.1 steps: - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - name: 'Install Qt' uses: jurplel/install-qt-action@v3 with: version: ${{ env.QT_VERSION }} host: 'windows' target: 'desktop' arch: 'win64_msvc2022_64' modules: 'qtremoteobjects qt5compat qtshadertools' dir: ${{ runner.temp }} set-env: 'true' - name: 'Setup MSVC' uses: ilammy/msvc-dev-cmd@v1 with: arch: 'x64' - name: 'Install dependencies' shell: bash run: | choco install ninja -y - name: 'Configure' shell: cmd run: | cmake -B build -G Ninja ^ -DCMAKE_BUILD_TYPE=Release ^ -DBUILD_TESTING=ON - name: 'Build' shell: cmd run: cmake --build build --config Release - name: 'Deploy Qt dependencies' shell: cmd run: | for %%f in (build\client\test_*.exe) do (windeployqt %%f) - name: 'Run tests' shell: cmd run: | set PATH=%PATH%;%CD%\client\3rd-prebuilt\deploy-prebuilt\windows\x64 set PATH=%PATH%;%Qt6_DIR%\..\..\..\bin ctest --test-dir build\client --output-on-failure # ------------------------------------------------------ Test-MacOS: runs-on: macos-latest env: QT_VERSION: 6.10.1 steps: - name: 'Setup xcode' uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '16.2.0' - name: 'Get sources' uses: actions/checkout@v4 with: submodules: 'true' fetch-depth: 10 - name: 'Install Qt' uses: jurplel/install-qt-action@v4 with: version: ${{ env.QT_VERSION }} host: 'mac' target: 'desktop' arch: 'clang_64' modules: 'qtremoteobjects qt5compat qtshadertools' dir: ${{ runner.temp }} set-env: 'true' - name: 'Install dependencies' run: | brew update brew install cmake ninja - name: 'Configure' run: | cmake -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=ON - name: 'Build' run: cmake --build build - name: 'Run tests' run: | QT_ROOT=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:\ $QT_ROOT/lib:\ $PWD/client/3rd-prebuilt/deploy-prebuilt/macos export QT_QPA_PLATFORM=offscreen ctest --test-dir build/client --output-on-failure