Skip to content

chore: validate Android shell in GitHub CI #31

chore: validate Android shell in GitHub CI

chore: validate Android shell in GitHub CI #31

Workflow file for this run

name: Release
on:
push:
branches:
- master
tags:
- 'v*'
workflow_dispatch:
jobs:
release:
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: windows-latest
target: x86_64-pc-windows-msvc
artifact: api-switch.exe
asset: api-switch-${{ github.ref_name }}-windows-x64.exe
- platform: macos-latest
target: x86_64-apple-darwin
artifact: api-switch
asset: api-switch-${{ github.ref_name }}-macos-x64
- platform: macos-latest
target: aarch64-apple-darwin
artifact: api-switch
asset: api-switch-${{ github.ref_name }}-macos-arm64
- platform: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact: api-switch
asset: api-switch-${{ github.ref_name }}-linux-x64
- platform: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
artifact: api-switch
asset: api-switch-${{ github.ref_name }}-linux-arm64
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: src-tauri -> target
- name: Linux dependencies
if: startsWith(matrix.platform, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils
- name: Install pnpm and dependencies
run: |
npm install -g pnpm
pnpm install --frozen-lockfile
pnpm remove sharp png-to-ico
- name: Build
run: |
pnpm build:web-admin
pnpm tauri build --target ${{ matrix.target }}
- name: Prepare artifact (rename)
shell: bash
run: |
mkdir -p artifact
binary_dir="src-tauri/target/${{ matrix.target }}/release"
# Copy binary
if [ -f "$binary_dir/api-switch.exe" ]; then
cp "$binary_dir/api-switch.exe" "artifact/${{ matrix.asset }}"
else
cp "$binary_dir/api-switch" "artifact/${{ matrix.asset }}"
fi
# Copy installer bundles if present
if [ -d "$binary_dir/bundle" ]; then
find "$binary_dir/bundle" -type f \( -name '*.msi' -o -name '*.exe' -o -name '*.dmg' -o -name '*.AppImage' -o -name '*.deb' -o -name '*.rpm' \) -exec cp {} artifact/ \; 2>/dev/null || true
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.asset }}
path: artifact/*
release-headless:
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: ubuntu-latest
target: x86_64-unknown-linux-gnu
asset: api-switch-${{ github.ref_name }}-linux-x64-headless
- platform: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
asset: api-switch-${{ github.ref_name }}-linux-arm64-headless
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: src-tauri -> target
key: headless-${{ matrix.target }}
- name: Install pnpm and dependencies
run: |
npm install -g pnpm
pnpm install --frozen-lockfile
pnpm remove sharp png-to-ico
- name: Build web-admin assets
run: pnpm build:web-admin
- name: Build headless binary
working-directory: src-tauri
run: cargo build --release --no-default-features --target ${{ matrix.target }}
- name: Verify no GUI libraries linked
run: |
binary="src-tauri/target/${{ matrix.target }}/release/api-switch"
if readelf -d "$binary" | grep -Ei 'libwebkit2gtk|libgtk-3|libgtk-4|libsoup'; then
echo "::error::Headless binary unexpectedly links GUI libraries"
exit 1
fi
echo "OK: no GTK/WebKit/libsoup NEEDED entries"
- name: Prepare artifact (rename)
run: |
mkdir -p artifact
cp "src-tauri/target/${{ matrix.target }}/release/api-switch" "artifact/${{ matrix.asset }}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.asset }}
path: artifact/*
release-android:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- 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: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: src-tauri -> target
key: android
- name: Setup JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: temurin
- 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: r27d
link-to-sdk: true
- name: Install pnpm and dependencies
run: |
npm install -g pnpm
pnpm install --frozen-lockfile
pnpm remove sharp png-to-ico
- name: Build Android APK
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
run: pnpm android:build
- name: Upload Android artifact
uses: actions/upload-artifact@v4
with:
name: api-switch-${{ github.ref_name }}-android-universal-apk
path: src-tauri/gen/android/app/build/outputs/apk/universal/release/*.apk
publish:
needs: [release, release-headless, release-android]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release notes
run: |
cat > RELEASE_NOTES.md <<'EOF'
## API Switch ${{ github.ref_name }}
### Downloads
**Portable binaries** (no install needed, just run):
- `api-switch-windows-x64.exe` — Windows
- `api-switch-macos-x64` — macOS Intel
- `api-switch-macos-arm64` — macOS Apple Silicon
- `api-switch-linux-x64` — Linux x64
- `api-switch-linux-arm64` — Linux ARM64
- `api-switch-linux-x64-headless` — Linux x64 (无 GUI,体积更小,适合服务器/Termux)
- `api-switch-linux-arm64-headless` — Linux ARM64 (无 GUI,适合服务器/Termux)
- `api-switch-android-universal-apk` — Android universal APK
**Installers** (system integration):
- `*.msi` / `*.exe` — Windows installer
- `*.dmg` — macOS disk image
- `*.AppImage` — Linux AppImage
### Usage
1. Download and run (or install via installer)
2. Database is auto-created in the same directory
3. Point your client to `http://127.0.0.1:9090`
EOF
- name: Create release
id: create_release
continue-on-error: true
uses: softprops/action-gh-release@v2
with:
files: artifacts/**/*
draft: true
name: ${{ github.ref_name }}
body_path: RELEASE_NOTES.md
- name: Create release (retry)
if: steps.create_release.outcome == 'failure'
uses: softprops/action-gh-release@v2
with:
files: artifacts/**/*
draft: true
name: ${{ github.ref_name }}
body_path: RELEASE_NOTES.md