name: Release on: push: tags: - "v*" permissions: contents: write jobs: release: runs-on: ${{ matrix.os }} strategy: matrix: include: # 固定 runner 版本,避免 latest 漂移导致 ABI 升级 - os: windows-2022 - os: ubuntu-22.04 - os: macos-14 steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" - name: Setup Rust uses: dtolnay/rust-toolchain@stable - name: Add macOS targets (ARM64 only for universal) if: runner.os == 'macOS' && runner.arch == 'ARM64' run: | rustup target add aarch64-apple-darwin x86_64-apple-darwin - name: Install Linux system deps if: runner.os == 'Linux' shell: bash run: | set -euxo pipefail sudo apt-get update # Core build tools and pkg-config sudo apt-get install -y --no-install-recommends \ build-essential \ pkg-config \ curl \ wget \ file \ patchelf \ libssl-dev # GTK/GLib stack for gdk-3.0, glib-2.0, gio-2.0 sudo apt-get install -y --no-install-recommends \ libgtk-3-dev \ librsvg2-dev \ libayatana-appindicator3-dev # WebKit2GTK (version differs across Ubuntu images; try 4.1 then 4.0) sudo apt-get install -y --no-install-recommends libwebkit2gtk-4.1-dev \ || sudo apt-get install -y --no-install-recommends libwebkit2gtk-4.0-dev # libsoup also changed major version; prefer 3.0 with fallback to 2.4 sudo apt-get install -y --no-install-recommends libsoup-3.0-dev \ || sudo apt-get install -y --no-install-recommends libsoup2.4-dev - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: 10.12.3 run_install: false - name: Get pnpm store directory id: pnpm-store shell: bash run: echo "path=$(pnpm store path --silent)" >> $GITHUB_OUTPUT - name: Setup pnpm cache uses: actions/cache@v4 with: path: ${{ steps.pnpm-store.outputs.path }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: ${{ runner.os }}-pnpm-store- - name: Install frontend deps run: pnpm install --frozen-lockfile - name: Build Tauri App (macOS, universal on ARM64) if: runner.os == 'macOS' && runner.arch == 'ARM64' run: pnpm tauri build --target universal-apple-darwin # macOS 仅保留通用包(在 macOS-14 / ARM64 运行器上构建) - name: Build Tauri App (Windows) if: runner.os == 'Windows' run: pnpm tauri build - name: Build Tauri App (Linux) if: runner.os == 'Linux' run: pnpm tauri build - name: Prepare macOS Assets if: runner.os == 'macOS' shell: bash run: | set -euxo pipefail mkdir -p release-assets echo "Looking for .app bundle..." APP_PATH="" for path in \ "src-tauri/target/release/bundle/macos" \ "src-tauri/target/universal-apple-darwin/release/bundle/macos" \ "src-tauri/target/aarch64-apple-darwin/release/bundle/macos" \ "src-tauri/target/x86_64-apple-darwin/release/bundle/macos"; do if [ -d "$path" ]; then APP_PATH=$(find "$path" -name "*.app" -type d | head -1) [ -n "$APP_PATH" ] && break fi done if [ -z "$APP_PATH" ]; then echo "No .app found" >&2 exit 1 fi APP_DIR=$(dirname "$APP_PATH") APP_NAME=$(basename "$APP_PATH") cd "$APP_DIR" # 使用 ditto 打包更兼容资源分叉 ditto -c -k --sequesterRsrc --keepParent "$APP_NAME" "CC-Switch-macOS.zip" mv "CC-Switch-macOS.zip" "$GITHUB_WORKSPACE/release-assets/" echo "macOS zip ready" - name: Prepare Windows Assets if: runner.os == 'Windows' shell: pwsh run: | $ErrorActionPreference = 'Stop' New-Item -ItemType Directory -Force -Path release-assets | Out-Null # 安装器(优先 NSIS,其次 MSI) $installer = Get-ChildItem -Path 'src-tauri/target/release/bundle' -Recurse -Include *.exe,*.msi -ErrorAction SilentlyContinue | Where-Object { $_.FullName -match '\\bundle\\(nsis|msi)\\' } | Select-Object -First 1 if ($null -ne $installer) { $dest = if ($installer.Extension -ieq '.msi') { 'CC-Switch-Setup.msi' } else { 'CC-Switch-Setup.exe' } Copy-Item $installer.FullName (Join-Path release-assets $dest) Write-Host "Installer copied: $dest" } else { Write-Warning 'No Windows installer found' } # 绿色版(portable):仅可执行文件 $exeCandidates = @( 'src-tauri/target/release/cc-switch.exe', 'src-tauri/target/x86_64-pc-windows-msvc/release/cc-switch.exe' ) $exePath = $exeCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($null -ne $exePath) { $portableDir = 'release-assets/CC-Switch-Portable' New-Item -ItemType Directory -Force -Path $portableDir | Out-Null Copy-Item $exePath $portableDir Compress-Archive -Path "$portableDir/*" -DestinationPath 'release-assets/CC-Switch-Windows-Portable.zip' -Force Remove-Item -Recurse -Force $portableDir Write-Host 'Windows portable zip created' } else { Write-Warning 'Portable exe not found' } - name: Prepare Linux Assets if: runner.os == 'Linux' shell: bash run: | set -euxo pipefail mkdir -p release-assets # 优先 DEB,同时若存在 AppImage 一并上传 DEB=$(find src-tauri/target/release/bundle -name "*.deb" | head -1 || true) if [ -n "$DEB" ]; then cp "$DEB" release-assets/ echo "Deb package copied" else echo "No .deb found" >&2 exit 1 fi APPIMAGE=$(find src-tauri/target/release/bundle -name "*.AppImage" | head -1 || true) if [ -n "$APPIMAGE" ]; then cp "$APPIMAGE" release-assets/ echo "AppImage copied" else echo "No AppImage found (optional)" fi - name: List prepared assets shell: bash run: | ls -la release-assets || true - name: Upload Release Assets uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} name: CC Switch ${{ github.ref_name }} body: | ## CC Switch ${{ github.ref_name }} Claude Code 供应商切换工具 ### 下载 - macOS: `CC-Switch-macOS.zip`(解压即用) - Windows: `CC-Switch-Setup.exe` 或 `CC-Switch-Setup.msi`(安装版);`CC-Switch-Windows-Portable.zip`(绿色版) - Linux: `*.deb`(Debian/Ubuntu 安装包) --- 提示:macOS 如遇“已损坏”提示,可在终端执行:`xattr -cr "/Applications/CC Switch.app"` files: release-assets/* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: List generated bundles (debug) if: always() shell: bash run: | echo "Listing bundles in src-tauri/target..." find src-tauri/target -maxdepth 4 -type f -name "*.*" 2>/dev/null || true