Add app_version workflow_dispatch input for specifying custom version during manual builds. Implement version application step that validates input format and updates package.json, tauri.conf.json, and Cargo.toml with requested version string. Add artifact name suffix based on provided version to distinguish versioned build outputs. Append version to NexaVPN-windows-installer and NexaVPN-windows
190 lines
6.3 KiB
YAML
190 lines
6.3 KiB
YAML
name: Build Windows Desktop Client
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
app_version:
|
|
description: "Optional app version for this build, e.g. 0.1.3"
|
|
required: false
|
|
default: ""
|
|
|
|
jobs:
|
|
build-windows-client:
|
|
name: Build Windows Client
|
|
runs-on: ubuntu-latest
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
working-directory: desktop-client
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
|
|
- name: Install Rust toolchain
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: x86_64-pc-windows-msvc
|
|
|
|
- name: Install system dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
build-essential \
|
|
clang \
|
|
lld \
|
|
llvm \
|
|
curl \
|
|
wget \
|
|
file \
|
|
nsis \
|
|
osslsigncode \
|
|
pkg-config \
|
|
libssl-dev \
|
|
libayatana-appindicator3-dev \
|
|
librsvg2-dev \
|
|
patchelf
|
|
|
|
- name: Install cargo-xwin
|
|
run: |
|
|
if ! cargo xwin --version >/dev/null 2>&1; then
|
|
cargo install --locked cargo-xwin
|
|
fi
|
|
|
|
- name: Install desktop client dependencies
|
|
run: npm install
|
|
|
|
- name: Apply requested app version
|
|
if: ${{ github.event.inputs.app_version != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
VERSION="${{ github.event.inputs.app_version }}"
|
|
export VERSION
|
|
|
|
case "${VERSION}" in
|
|
*[!0-9A-Za-z.+-]*|'')
|
|
echo "Invalid app_version: ${VERSION}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
node -e '
|
|
const fs = require("fs");
|
|
const version = process.env.VERSION;
|
|
const pkgPath = "package.json";
|
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
pkg.version = version;
|
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
'
|
|
|
|
node -e '
|
|
const fs = require("fs");
|
|
const version = process.env.VERSION;
|
|
const configPath = "src-tauri/tauri.conf.json";
|
|
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
config.version = version;
|
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
'
|
|
|
|
perl -0pi -e 's/^version = ".*?"$/version = "'"${VERSION}"'"/m' src-tauri/Cargo.toml
|
|
|
|
echo "Using app version ${VERSION}"
|
|
|
|
- name: Build bundled Windows tunnel helper
|
|
run: npm run helper:windows-x64
|
|
|
|
- name: Prepare signing certificate
|
|
if: ${{ secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
|
run: |
|
|
printf '%s' "${{ secrets.WINDOWS_SIGN_PFX_B64 }}" | base64 -d > /tmp/nexavpn-signing-cert.pfx
|
|
|
|
- name: Sign bundled Windows tunnel helper
|
|
if: ${{ secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
timestamp_url="${{ secrets.WINDOWS_SIGN_TIMESTAMP_URL }}"
|
|
if [ -z "${timestamp_url}" ]; then
|
|
timestamp_url="http://timestamp.digicert.com"
|
|
fi
|
|
helper_path="src-tauri/bundled/windows-x64/nexavpn-tunnel-helper.exe"
|
|
signed_path="${helper_path}.signed"
|
|
osslsigncode sign \
|
|
-pkcs12 /tmp/nexavpn-signing-cert.pfx \
|
|
-pass "${{ secrets.WINDOWS_SIGN_PFX_PASSWORD }}" \
|
|
-h sha256 \
|
|
-ts "${timestamp_url}" \
|
|
-in "${helper_path}" \
|
|
-out "${signed_path}"
|
|
mv "${signed_path}" "${helper_path}"
|
|
|
|
- name: Build Windows installer
|
|
run: npm run tauri:build:windows-x64:linux
|
|
|
|
- name: Prepare artifact names
|
|
run: |
|
|
set -euo pipefail
|
|
VERSION="${{ github.event.inputs.app_version }}"
|
|
if [ -n "${VERSION}" ]; then
|
|
echo "ARTIFACT_SUFFIX=-${VERSION}" >> "${GITHUB_ENV}"
|
|
else
|
|
echo "ARTIFACT_SUFFIX=" >> "${GITHUB_ENV}"
|
|
fi
|
|
|
|
- name: Sign Windows desktop executable and installer
|
|
if: ${{ secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
|
run: |
|
|
set -euo pipefail
|
|
timestamp_url="${{ secrets.WINDOWS_SIGN_TIMESTAMP_URL }}"
|
|
if [ -z "${timestamp_url}" ]; then
|
|
timestamp_url="http://timestamp.digicert.com"
|
|
fi
|
|
|
|
sign_file() {
|
|
local input_path="$1"
|
|
local output_path="${input_path}.signed"
|
|
osslsigncode sign \
|
|
-pkcs12 /tmp/nexavpn-signing-cert.pfx \
|
|
-pass "${{ secrets.WINDOWS_SIGN_PFX_PASSWORD }}" \
|
|
-h sha256 \
|
|
-ts "${timestamp_url}" \
|
|
-in "${input_path}" \
|
|
-out "${output_path}"
|
|
mv "${output_path}" "${input_path}"
|
|
}
|
|
|
|
sign_file "src-tauri/target/x86_64-pc-windows-msvc/release/nexavpn-desktop.exe"
|
|
|
|
shopt -s nullglob
|
|
for installer in src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe; do
|
|
sign_file "${installer}"
|
|
done
|
|
|
|
- name: Cleanup signing certificate
|
|
if: ${{ always() && secrets.WINDOWS_SIGN_PFX_B64 != '' && secrets.WINDOWS_SIGN_PFX_PASSWORD != '' }}
|
|
run: rm -f /tmp/nexavpn-signing-cert.pfx
|
|
|
|
- name: Upload Windows installer
|
|
uses: christopherhx/gitea-upload-artifact@v4
|
|
with:
|
|
name: NexaVPN-windows-installer${{ env.ARTIFACT_SUFFIX }}
|
|
path: |
|
|
desktop-client/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.exe
|
|
desktop-client/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/*.msi
|
|
if-no-files-found: error
|
|
|
|
- name: Upload raw Windows build outputs
|
|
uses: christopherhx/gitea-upload-artifact@v4
|
|
with:
|
|
name: NexaVPN-windows-raw-build${{ env.ARTIFACT_SUFFIX }}
|
|
path: |
|
|
desktop-client/src-tauri/target/x86_64-pc-windows-msvc/release/nexavpn-desktop.exe
|
|
desktop-client/src-tauri/bundled/windows-x64/nexavpn-tunnel-helper.exe
|
|
desktop-client/src-tauri/bundled/windows-x64/wireguard-installer.msi
|
|
if-no-files-found: error
|