feat(ide): enhance IDE layout with resizable panels and improved user… #136
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
| # 本地安装包(P0-1):dmg / msi / AppImage 构建并上传至 Release | |
| # 与 release.yml 同 tag 触发;Release 由 release.yml 创建后,本 workflow 将桌面端安装包追加到同一 Release | |
| name: Build and Release Desktop (dmg/msi/AppImage) | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| branches: | |
| - main | |
| paths: | |
| - 'crates/skilllite-assistant/**' | |
| - 'crates/skilllite-agent/**' | |
| - 'crates/skilllite-core/**' | |
| - 'skilllite/**' | |
| - 'Cargo.lock' | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-desktop: | |
| name: Build ${{ matrix.platform }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: macos-14 | |
| platform: darwin-arm64 | |
| - os: windows-latest | |
| platform: windows-x64 | |
| - os: ubuntu-22.04 | |
| platform: linux-x64 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: crates/skilllite-assistant/package-lock.json | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo build | |
| uses: actions/cache@v4 | |
| with: | |
| path: target | |
| key: ${{ runner.os }}-desktop-cargo-${{ hashFiles('Cargo.lock', 'crates/skilllite-assistant/src-tauri/Cargo.toml') }} | |
| - name: Install Linux dependencies (Tauri 2) | |
| if: matrix.os == 'ubuntu-22.04' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| build-essential \ | |
| curl \ | |
| wget \ | |
| file \ | |
| libxdo-dev \ | |
| libssl-dev \ | |
| libayatana-appindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf | |
| - name: Install create-dmg (macOS DMG bundling) | |
| if: runner.os == 'macOS' | |
| run: brew install create-dmg | |
| - name: Install npm dependencies | |
| working-directory: crates/skilllite-assistant | |
| run: npm ci | |
| # macOS:导入 Developer ID 证书以便 Tauri 构建时签名(配置 Secrets 后生效,未配置则跳过即不签名) | |
| # 注意:if 条件中不能使用 secrets,故在脚本内判断是否跳过 | |
| - name: Import Apple Developer certificate (macOS) | |
| if: runner.os == 'macOS' | |
| env: | |
| APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | |
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} | |
| run: | | |
| if [ -z "$APPLE_CERTIFICATE" ]; then echo "APPLE_CERTIFICATE not set, skipping signing"; exit 0; fi | |
| echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12 | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain | |
| security default-keychain -s build.keychain | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain | |
| security set-keychain-settings -t 3600 -u build.keychain | |
| security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign >/dev/null 2>&1 | |
| rm -f certificate.p12 | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain | |
| SIGNING_IDENTITY=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application" | head -1 | awk -F'"' '{print $2}') | |
| echo "APPLE_SIGNING_IDENTITY=$SIGNING_IDENTITY" >> $GITHUB_ENV | |
| echo "Signing identity configured (identity not logged)." | |
| # macOS:用 App Store Connect API 密钥做公证时,把 .p8 内容写回为临时文件(不填 APPLE_ID/APPLE_PASSWORD 时用) | |
| # 注意:if 条件中不能使用 secrets,故在脚本内判断是否跳过 | |
| - name: Prepare Apple API key for notarization (macOS) | |
| if: runner.os == 'macOS' | |
| working-directory: crates/skilllite-assistant | |
| env: | |
| APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }} | |
| run: | | |
| if [ -z "$APPLE_API_KEY_P8" ]; then echo "APPLE_API_KEY_P8 not set, skipping"; exit 0; fi | |
| echo "$APPLE_API_KEY_P8" > authkey.p8 | |
| echo "APPLE_API_KEY_PATH=${{ github.workspace }}/crates/skilllite-assistant/authkey.p8" >> $GITHUB_ENV | |
| - name: Build Tauri app (skilllite binary bundled via beforeBuildCommand) | |
| working-directory: crates/skilllite-assistant | |
| shell: bash | |
| run: | | |
| [ -z "$APPLE_ID" ] && unset APPLE_ID | |
| [ -z "$APPLE_PASSWORD" ] && unset APPLE_PASSWORD | |
| [ -z "$APPLE_API_KEY" ] && unset APPLE_API_KEY | |
| [ -z "$APPLE_API_ISSUER" ] && unset APPLE_API_ISSUER | |
| [ -z "$APPLE_API_KEY_PATH" ] && unset APPLE_API_KEY_PATH | |
| if [ "$RUNNER_OS" = "macOS" ]; then | |
| npm run tauri:build -- --bundles app | |
| else | |
| npm run tauri:build | |
| fi | |
| env: | |
| CI: true | |
| APPLE_SIGNING_IDENTITY: ${{ env.APPLE_SIGNING_IDENTITY }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
| APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} | |
| APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} | |
| APPLE_API_KEY_PATH: ${{ env.APPLE_API_KEY_PATH }} | |
| - name: Verify .app bundle exists (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| APP_DIR="crates/skilllite-assistant/src-tauri/target/release/bundle/macos" | |
| echo "--- Contents of bundle/macos/ ---" | |
| ls -la "$APP_DIR" || echo "WARNING: $APP_DIR does not exist" | |
| echo "--- Checking .app structure ---" | |
| ls -la "$APP_DIR/SkillLite Assistant.app/Contents/" 2>/dev/null || echo "WARNING: .app not found at expected path" | |
| - name: Create DMG with create-dmg (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| APP_VERSION=$(python3 -c "import json; print(json.load(open('crates/skilllite-assistant/src-tauri/tauri.conf.json'))['version'])") | |
| APP_PATH="crates/skilllite-assistant/src-tauri/target/release/bundle/macos/SkillLite Assistant.app" | |
| DMG_DIR="crates/skilllite-assistant/src-tauri/target/release/bundle/dmg" | |
| mkdir -p "$DMG_DIR" | |
| set +e | |
| create-dmg \ | |
| --volname "SkillLite Assistant" \ | |
| --window-pos 200 120 \ | |
| --window-size 600 400 \ | |
| --icon-size 100 \ | |
| --icon "SkillLite Assistant.app" 175 190 \ | |
| --app-drop-link 425 190 \ | |
| "$DMG_DIR/SkillLite Assistant_${APP_VERSION}_aarch64.dmg" \ | |
| "$APP_PATH" | |
| EXIT_CODE=$? | |
| set -e | |
| if [ $EXIT_CODE -ne 0 ] && [ $EXIT_CODE -ne 2 ]; then | |
| echo "create-dmg failed with exit code $EXIT_CODE" | |
| exit 1 | |
| fi | |
| - name: Upload macOS artifact (dmg) | |
| if: runner.os == 'macOS' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: skilllite-assistant-darwin-arm64 | |
| path: crates/skilllite-assistant/src-tauri/target/release/bundle/dmg/*.dmg | |
| - name: Remove Apple API key file (macOS, reduce exposure) | |
| if: runner.os == 'macOS' | |
| working-directory: crates/skilllite-assistant | |
| run: rm -f authkey.p8 | |
| - name: Upload Windows artifact (msi) | |
| if: matrix.os == 'windows-latest' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: skilllite-assistant-windows-x64 | |
| path: crates/skilllite-assistant/src-tauri/target/release/bundle/msi/*.msi | |
| - name: Upload Linux artifact (AppImage) | |
| if: matrix.os == 'ubuntu-22.04' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: skilllite-assistant-linux-x64 | |
| path: crates/skilllite-assistant/src-tauri/target/release/bundle/appimage/*.AppImage | |
| upload-to-release: | |
| name: Upload desktop assets to Release | |
| needs: build-desktop | |
| runs-on: ubuntu-latest | |
| # tag 触发或手动触发时上传;允许部分平台成功(fail_on_unmatched_files: false) | |
| if: always() && (startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch') && !cancelled() | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download desktop artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./desktop-artifacts | |
| - name: List artifacts | |
| run: find ./desktop-artifacts -type f | |
| - name: Upload to existing Release (tag push) | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| files: | | |
| desktop-artifacts/skilllite-assistant-darwin-arm64/*.dmg | |
| desktop-artifacts/skilllite-assistant-windows-x64/*.msi | |
| desktop-artifacts/skilllite-assistant-linux-x64/*.AppImage | |
| fail_on_unmatched_files: false | |
| - name: Create draft Release (manual dispatch) | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: desktop-${{ github.sha }} | |
| name: "Desktop Build (manual)" | |
| draft: true | |
| files: | | |
| desktop-artifacts/skilllite-assistant-darwin-arm64/*.dmg | |
| desktop-artifacts/skilllite-assistant-windows-x64/*.msi | |
| desktop-artifacts/skilllite-assistant-linux-x64/*.AppImage | |
| fail_on_unmatched_files: false |