chore: validate Android shell in GitHub CI #31
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |