Skip to content

Release

Release #6

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g. 0.1.0). Leave empty to use version from tauri.conf.json'
required: false
default: ''
permissions:
contents: write
jobs:
# Determine the version and tag name to use for the release
prepare:
runs-on: ubuntu-latest
outputs:
tag_name: ${{ steps.get_version.outputs.tag_name }}
version: ${{ steps.get_version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Get version
id: get_version
run: |
if [ "${{ github.event_name }}" = "push" ]; then
# Triggered by tag push — use the tag directly
TAG="${GITHUB_REF#refs/tags/}"
VERSION="${TAG#v}"
elif [ -n "${{ github.event.inputs.version }}" ]; then
# Manual trigger with version specified
VERSION="${{ github.event.inputs.version }}"
TAG="v${VERSION}"
else
# Manual trigger without version — read from tauri.conf.json
VERSION=$(grep -oP '"version":\s*"\K[^"]+' client/src-tauri/tauri.conf.json)
TAG="v${VERSION}"
fi
echo "tag_name=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Resolved version: ${VERSION}, tag: ${TAG}"
release:
needs: prepare
permissions:
contents: write
strategy:
fail-fast: false
matrix:
platform: [macos-latest, ubuntu-22.04, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- name: setup node
uses: actions/setup-node@v4
with:
node-version: 20
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
- name: install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: install frontend dependencies
run: npm install
working-directory: ./client
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tagName: ${{ needs.prepare.outputs.tag_name }}
releaseName: 'CandyConnect VPN ${{ needs.prepare.outputs.tag_name }}'
releaseBody: 'See the assets to download this version and install.'
releaseDraft: false
prerelease: false
projectPath: ./client
mobile-android:
needs: prepare
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Setup Android NDK
id: setup-ndk
uses: nttld/setup-ndk@v1
with:
ndk-version: r26d
- name: install frontend dependencies
run: npm install
working-directory: ./client
- name: Install Tauri CLI
run: npx @tauri-apps/cli --version
working-directory: ./client
- name: Initialize Android project
run: npx tauri android init
working-directory: ./client
env:
NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
JAVA_HOME: ${{ steps.setup-java.outputs.java-home }}
ANDROID_HOME: ${{ env.ANDROID_HOME }}
- name: Build Android APK
run: npx tauri android build --apk
working-directory: ./client
env:
NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
JAVA_HOME: ${{ steps.setup-java.outputs.java-home }}
ANDROID_HOME: ${{ env.ANDROID_HOME }}
- name: Sign APK with debug key
run: |
# Find the unsigned APK
APK_PATH=$(find client/src-tauri/gen/android -name "*.apk" -type f | head -1)
if [ -z "$APK_PATH" ]; then
echo "No APK found, trying AAB..."
APK_PATH=$(find client/src-tauri/gen/android -name "*.aab" -type f | head -1)
fi
if [ -n "$APK_PATH" ]; then
echo "Found artifact: ${APK_PATH}"
# Use zipalign and apksigner if available
BUILD_TOOLS=$(ls -d ${ANDROID_HOME}/build-tools/*/ 2>/dev/null | tail -1)
if [ -n "$BUILD_TOOLS" ] && [ -f "${BUILD_TOOLS}zipalign" ]; then
ALIGNED_APK="${APK_PATH%.apk}-aligned.apk"
${BUILD_TOOLS}zipalign -v 4 "$APK_PATH" "$ALIGNED_APK" && mv "$ALIGNED_APK" "$APK_PATH"
fi
if [ -n "$BUILD_TOOLS" ] && [ -f "${BUILD_TOOLS}apksigner" ]; then
# Generate a debug keystore if not present
if [ ! -f ~/.android/debug.keystore ]; then
mkdir -p ~/.android
keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Debug,O=Android,C=US"
fi
${BUILD_TOOLS}apksigner sign --ks ~/.android/debug.keystore --ks-pass pass:android --key-pass pass:android "$APK_PATH"
fi
fi
- name: Find APK files
id: find_apk
run: |
APK_PATH=$(find client/src-tauri/gen/android -name "*.apk" -type f | head -1)
if [ -z "$APK_PATH" ]; then
echo "No APK found, looking for AAB..."
APK_PATH=$(find client/src-tauri/gen/android -name "*.aab" -type f | head -1)
fi
echo "artifact_path=${APK_PATH}" >> "$GITHUB_OUTPUT"
echo "artifact_name=$(basename ${APK_PATH})" >> "$GITHUB_OUTPUT"
echo "Found artifact: ${APK_PATH}"
- name: Upload Android artifact to release
if: steps.find_apk.outputs.artifact_path != ''
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.prepare.outputs.tag_name }}
name: 'CandyConnect VPN ${{ needs.prepare.outputs.tag_name }}'
files: ${{ steps.find_apk.outputs.artifact_path }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}