Files
amnezia-client/.github/workflows/deploy.yml
Yaroslav Gurov 009ca981d5 feat: initial conan support and build process refactoring (#2260)
* feat: initial conan support

* feat: add awg-go and awg-apple recipes

* feat: macos full feature conan build, except ss and cloak

* feat: conan android initial support

* fix: android libssh fixes

* conan: android additional recipes and fixes

* feat: openvpn add support android

* fix: awg android connection establish

* conan: apple full-featured support

* chore: bump min macos version

* chore: get rid of manual deploy recursive copying

* conan: beautify makefile-based recipes

* conan: add geosite.dat and geoip.dat

* conan: use lib linking instead of QT_EXTRA_LIBS for OVPN

* conan: address lack of SONAME of libck-ovpn-plugin.so correctly

* conan: windows initial support

* conan: make awg-windows and wintun be interpret as exes

* conan: fix version for v2ray-rules-dat

* feat: conan and platform bootstrap rework in cmake

* feat: 16kb support for Android

* chore(conan): recipes cleanup

* feat: support of drivers for windows

* feat: support full-featured cmake install

* chore: exclude qtkeychain from the target build

* fix: install for apple systems

* fix: provide flags for cloak plugin for openvpn-pt-android

* chore: bump android deps for 16kb support

* feat(conan): patch cloak to properly provide env for golang

* chore: remove redundant hint from conan find

* feat: linux <-> conan features

* feat: linux initial packaging support

* feat: linux cpack support

* feat: cpack windows full-featured build

* feat: productbuild cpack support

* feat: rework CI/CD for macos

* feat: rework CI/CD for Linux

* fix: libncap automake args

* fix: CI/CD correct QT paths

* fix: windows rework CI/CD

* fix: windows artifact upload

* chore: remove MacOS-old from build targets

* feat: add conan to all mobile and NE builds

* feat: support default amnezia conan remote

* fix: use Release instead of release on Android

* feat: get rid of 3rd-prebuilt

* feat: conan CI/CD upload

* fix: CI/CD change windows toolset versions

* fix: remove MSVC version from CI/CD

* feat: conan CI/CD add Release and Debug build types

* feat: add multiple xcode versions for conan CI/CD

* fix: correct conan CI/CD clang versions

* feat: separate prebuilt baking, and add some for NE

* feat: rework keychain on ios/macos even more

* fix: add desktop Qt for iOS

* feat: add QT_HOST_PATH to build.sh

* fix: add deploy definition to cmake

* fix: android adjustments for toolchains and CI/CD

* fix: add needs for Android CI/CD

* fix: Android CI/CD use android-28

* fix: modernize translations, and CI/CD fixes

* fix: gradle min sdk compilation error

* fix: CI/CD add installers to all jobs

* fix: parse android platform more precisely

* fix: adjust aab path in CI/CD

* feat: CI/CD do not execute artifact build if there is nothing changed

* fix: CI/CD use common jobs even if previous were failed

* fix: Apple CI/CD use set-key-partition-list for keychains

* fix: Apple CI/CD do not specify any keychain (use default)

* fix: build aab as a different step in build script

* chore: beautify build.sh script

* feat: CI/CD build separate APKs per ABI

* fix: Android CI/CD upload artifact in separate steps

* chore: recipes cleanup

* feat: add hints for conan on MacOS

* fix: add main.cpp and tests back to CMakeLists.txt

* chore: xrayProtocol codestyle changes

* fix: openssl set proper X509 request version

* fix: make openvpn protocol rely only on client while configuring

* chore: get rid of old scripts

* chore: readme update describing build process more precisely

* feat: windows build script add multiprocessing capabilities

* chore: bump Qt version in README

* feat: add generator option and use Ninja by default in CI/CD for linux/macos

---------

Co-authored-by: NickVs2015 <nv@amnezia.org>
2026-05-04 22:59:24 +08:00

897 lines
26 KiB
YAML

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