name: Build Desktop (Dev) # 开发阶段构建 — 不创建 Release,只上传 Artifacts 供下载测试 on: workflow_dispatch: inputs: platforms: description: 'Build platforms' required: true default: 'all' type: choice options: - all - macos-arm64 - macos-x64 - windows-x64 - linux-x64 - linux-arm64 permissions: contents: read concurrency: group: build-desktop-dev-${{ github.ref }} cancel-in-progress: true jobs: # ── 动态生成构建矩阵 ────────────────────────────────────── prepare: runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - id: set-matrix run: | ALL='[{"platform":"macos-latest","rust_target":"aarch64-apple-darwin","tauri_args":"--target aarch64-apple-darwin","bundles":"app,dmg","label":"macOS-ARM64","artifact_name":"macos-arm64","asset_platform":"macos","asset_arch":"arm64"},{"platform":"macos-latest","rust_target":"x86_64-apple-darwin","tauri_args":"--target x86_64-apple-darwin","bundles":"app,dmg","label":"macOS-x64","artifact_name":"macos-x64","asset_platform":"macos","asset_arch":"x64"},{"platform":"windows-latest","rust_target":"x86_64-pc-windows-msvc","tauri_args":"","bundles":"msi","label":"Windows-x64","artifact_name":"windows-x64","asset_platform":"windows","asset_arch":"x64"},{"platform":"ubuntu-22.04","rust_target":"x86_64-unknown-linux-gnu","tauri_args":"","bundles":"deb","label":"Linux-x64","artifact_name":"linux-x64","asset_platform":"linux","asset_arch":"x64"},{"platform":"ubuntu-22.04-arm","rust_target":"aarch64-unknown-linux-gnu","tauri_args":"","bundles":"deb","label":"Linux-ARM64","artifact_name":"linux-arm64","asset_platform":"linux","asset_arch":"arm64"}]' SELECTED="${{ inputs.platforms }}" if [ "$SELECTED" = "all" ]; then MATRIX=$(echo "$ALL" | jq -c '{include: .}') else MATRIX=$(echo "$ALL" | jq -c --arg sel "$SELECTED" '{include: [.[] | select( ($sel == "macos-arm64" and .label == "macOS-ARM64") or ($sel == "macos-x64" and .label == "macOS-x64") or ($sel == "windows-x64" and .label == "Windows-x64") or ($sel == "linux-x64" and .label == "Linux-x64") or ($sel == "linux-arm64" and .label == "Linux-ARM64") )]}') fi echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" # ── 构建 ──────────────────────────────────────────────────── build: needs: prepare strategy: fail-fast: false matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} runs-on: ${{ matrix.platform }} name: Build (${{ matrix.label }}) steps: - name: Checkout uses: actions/checkout@v4 # ── 读取版本号 ─────────────────────────────────────────── - name: Read version id: version shell: bash run: | VERSION=$(jq -r '.version' desktop/src-tauri/tauri.conf.json) echo "version=$VERSION" >> "$GITHUB_OUTPUT" # ── 系统依赖 (Linux) ───────────────────────────────────── # libfuse2 是 AppImage 运行时依赖:linuxdeploy 工具链本身是 AppImage 格式, # 运行时需要 libfuse2,Ubuntu 22.04 默认未安装。 - name: Install Linux dependencies if: contains(matrix.platform, 'ubuntu') run: | sudo apt-get update sudo apt-get install -y \ build-essential curl wget file \ libxdo-dev libssl-dev \ libwebkit2gtk-4.1-dev \ libayatana-appindicator3-dev \ librsvg2-dev patchelf \ libfuse2 # ── Bun ────────────────────────────────────────────────── - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest # ── Node.js ────────────────────────────────────────────── - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 # ── Rust ───────────────────────────────────────────────── - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.rust_target }} - name: Rust cache uses: swatinem/rust-cache@v2 with: workspaces: 'desktop/src-tauri -> target' shared-key: ${{ matrix.rust_target }} # ── 安装依赖 ───────────────────────────────────────────── - name: Install root dependencies run: bun install - name: Install desktop dependencies working-directory: desktop run: bun install - name: Install adapter dependencies working-directory: adapters run: bun install # ── 构建 sidecars ──────────────────────────────────────── - name: Build sidecars working-directory: desktop env: TAURI_ENV_TARGET_TRIPLE: ${{ matrix.rust_target }} run: bun run build:sidecars # ── 构建 Tauri (无签名、无 updater) ────────────────────── - name: Build Tauri app working-directory: desktop env: TAURI_ENV_TARGET_TRIPLE: ${{ matrix.rust_target }} run: | # 开发构建: 禁用 updater artifacts (不需要签名密钥) echo '{"bundle":{"createUpdaterArtifacts":false}}' > /tmp/dev-build.json ARGS=(bunx tauri build --bundles ${{ matrix.bundles }} --ci --config /tmp/dev-build.json) if [ -n "${{ matrix.tauri_args }}" ]; then ARGS+=(${{ matrix.tauri_args }}) fi "${ARGS[@]}" shell: bash # ── 收集产物 ───────────────────────────────────────────── - name: Collect artifacts id: collect shell: bash run: | BUNDLE_DIR="desktop/src-tauri/target/${{ matrix.rust_target }}/release/bundle" FALLBACK_DIR="desktop/src-tauri/target/release/bundle" # 优先使用带 target 的路径 if [ -d "$BUNDLE_DIR" ]; then SEARCH_DIR="$BUNDLE_DIR" else SEARCH_DIR="$FALLBACK_DIR" fi STAGING="desktop/build-artifacts/ci-Claude-Code-Haha-v${{ steps.version.outputs.version }}-${{ matrix.artifact_name }}" mkdir -p "$STAGING" echo "Searching for artifacts in: $SEARCH_DIR" if [ -d "$SEARCH_DIR" ]; then find "$SEARCH_DIR" \ \( -type f \( \ -name "*.dmg" -o -name "*.msi" -o \ -name "*.deb" -o -name "*.AppImage" -o -name "*.zip" \ \) \) -o \ \( -type d -name "*.app" \) | while read -r f; do base="$(basename "$f")" bundle="artifact" ext="" case "$base" in *.app) bundle="app" ext=".app" ;; *.dmg) bundle="dmg" ext=".dmg" ;; *.msi) bundle="msi" ext=".msi" ;; *.deb) bundle="deb" ext=".deb" ;; *.AppImage) bundle="appimage" ext=".AppImage" ;; *.zip) bundle="zip" ext=".zip" ;; *) ext="" ;; esac target="Claude-Code-Haha_${{ steps.version.outputs.version }}_${{ matrix.asset_platform }}_${{ matrix.asset_arch }}_${bundle}${ext}" echo " Copying: ${base} -> ${target}" cp -R "$f" "$STAGING/$target" done fi echo "staging_dir=$STAGING" >> "$GITHUB_OUTPUT" echo "=== Collected artifacts ===" ls -lh "$STAGING/" 2>/dev/null || echo "(empty)" # ── 上传为 GitHub Artifact ─────────────────────────────── - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: Claude-Code-Haha-v${{ steps.version.outputs.version }}-${{ matrix.artifact_name }} path: ${{ steps.collect.outputs.staging_dir }} retention-days: 7 if-no-files-found: warn # ── 构建完成汇总 ──────────────────────────────────────────── summary: needs: build runs-on: ubuntu-latest if: always() steps: - name: Build summary run: | echo "## Desktop Dev Build Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Platform | Status |" >> $GITHUB_STEP_SUMMARY echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY echo "Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY echo "Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "📦 Artifacts are available for download from the **Artifacts** section above." >> $GITHUB_STEP_SUMMARY echo "Artifacts will be retained for **7 days**." >> $GITHUB_STEP_SUMMARY