fix(ci): upgrade macOS runners to v15 #60
Workflow file for this run
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: Build and Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| strategy: | |
| matrix: | |
| include: | |
| # macOS: Use Intel runner for x64, Apple Silicon runner for arm64 | |
| # CRITICAL: macos-15-intel is x86_64, macos-15 is Apple Silicon (arm64) | |
| # better-sqlite3 native module must be built on matching architecture | |
| - os: macos-15-intel # Intel (x86_64) runner for x64 builds | |
| platform: mac | |
| arch: x64 | |
| - os: macos-15 # Apple Silicon (arm64) runner for arm64 builds | |
| platform: mac | |
| arch: arm64 | |
| - os: windows-latest | |
| platform: win | |
| arch: x64 | |
| - os: windows-latest | |
| platform: win | |
| arch: arm64 | |
| - os: ubuntu-latest | |
| platform: linux | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| # 显式使用与 package.json 中一致的 pnpm 版本 | |
| version: 9.15.0 | |
| run_install: false | |
| - name: Get pnpm store directory | |
| id: pnpm-cache | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT | |
| - name: Setup pnpm cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} | |
| key: ${{ runner.os }}-${{ matrix.arch || 'default' }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-${{ matrix.arch || 'default' }}-pnpm-store- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Rebuild native modules for Electron | |
| shell: bash | |
| run: | | |
| # Rebuild native modules for the target architecture | |
| # 为目标架构重建原生模块 | |
| # First, remove any prebuilt binaries to force rebuild from source | |
| # 首先删除预编译二进制,强制从源码重新编译 | |
| rm -rf node_modules/better-sqlite3/build || true | |
| rm -rf node_modules/better-sqlite3/prebuilds || true | |
| if [ "${{ matrix.platform }}" = "mac" ]; then | |
| echo "Rebuilding better-sqlite3 for macOS ${{ matrix.arch }}" | |
| # Force rebuild with explicit architecture | |
| npx electron-rebuild -f -w better-sqlite3 --arch ${{ matrix.arch }} | |
| elif [ "${{ matrix.platform }}" = "win" ]; then | |
| echo "Rebuilding better-sqlite3 for Windows ${{ matrix.arch }}" | |
| npx electron-rebuild -f -w better-sqlite3 --arch ${{ matrix.arch }} | |
| else | |
| pnpm run rebuild | |
| fi | |
| - name: Verify native module architecture (macOS) | |
| if: matrix.platform == 'mac' | |
| shell: bash | |
| run: | | |
| # Verify the better-sqlite3 native module is built for correct architecture | |
| # 验证 better-sqlite3 原生模块是否为正确架构编译 | |
| NATIVE_MODULE="node_modules/better-sqlite3/build/Release/better_sqlite3.node" | |
| if [ -f "$NATIVE_MODULE" ]; then | |
| echo "Checking architecture of $NATIVE_MODULE" | |
| file "$NATIVE_MODULE" | |
| ARCH=$(file "$NATIVE_MODULE" | grep -o 'arm64\|x86_64') | |
| echo "Detected architecture: $ARCH" | |
| if [ "${{ matrix.arch }}" = "arm64" ] && [ "$ARCH" != "arm64" ]; then | |
| echo "ERROR: Expected arm64 but got $ARCH" | |
| exit 1 | |
| elif [ "${{ matrix.arch }}" = "x64" ] && [ "$ARCH" != "x86_64" ]; then | |
| echo "ERROR: Expected x86_64 but got $ARCH" | |
| exit 1 | |
| fi | |
| echo "Architecture verification passed!" | |
| else | |
| echo "WARNING: Native module not found at $NATIVE_MODULE" | |
| fi | |
| - name: Clean previous build artifacts | |
| shell: bash | |
| run: | | |
| rm -rf dist || true | |
| - name: Build for ${{ matrix.platform }} ${{ matrix.arch }} | |
| shell: bash | |
| run: | | |
| if [ -n "${{ matrix.arch }}" ]; then | |
| # Build specific architecture (Windows or macOS with arch specified) | |
| # 构建特定架构(Windows 或指定了 arch 的 macOS) | |
| if [ "${{ matrix.platform }}" = "win" ]; then | |
| pnpm vite build && pnpm electron-builder --win --${{ matrix.arch }} --publish never | |
| elif [ "${{ matrix.platform }}" = "mac" ]; then | |
| pnpm vite build && pnpm electron-builder --mac --${{ matrix.arch }} --publish never | |
| fi | |
| else | |
| pnpm electron:build:${{ matrix.platform }} | |
| fi | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Normalize Windows update metadata | |
| if: matrix.platform == 'win' && matrix.arch != '' | |
| shell: bash | |
| run: | | |
| # Generate appropriate yml files for each architecture | |
| # 为每个架构生成适当的 yml 文件 | |
| if [ "${{ matrix.arch }}" = "arm64" ]; then | |
| if [ -f "dist/latest.yml" ]; then | |
| node scripts/fix-latest-yml.js --file dist/latest.yml --arch arm64 | |
| # Rename to latest-arm64.yml for arm64 builds | |
| mv dist/latest.yml dist/latest-arm64.yml | |
| echo "Renamed latest.yml to latest-arm64.yml for ARM64" | |
| fi | |
| else | |
| # x64: Generate latest-x64.yml for backward compatibility with older versions | |
| # x64: 生成 latest-x64.yml 以兼容旧版本 | |
| # electron-builder already generates correct filenames via artifactName | |
| # electron-builder 已通过 artifactName 配置生成正确的文件名 | |
| if [ -f "dist/latest.yml" ]; then | |
| node scripts/fix-latest-yml.js --file dist/latest.yml --arch x64 | |
| # Create latest-x64.yml as a copy for backward compatibility with old versions | |
| # 创建 latest-x64.yml 副本以兼容旧版本 | |
| cp dist/latest.yml dist/latest-x64.yml | |
| echo "Created latest-x64.yml for backward compatibility" | |
| fi | |
| fi | |
| # Remove duplicate NSIS blockmap without arch (prevents release upload errors) | |
| shopt -s nullglob | |
| for file in dist/*.exe.blockmap; do | |
| case "$file" in | |
| *-x64.exe.blockmap|*-arm64.exe.blockmap) ;; | |
| *) rm -f "$file" ;; | |
| esac | |
| done | |
| - name: Normalize macOS update metadata | |
| if: matrix.platform == 'mac' && matrix.arch != '' | |
| shell: bash | |
| run: | | |
| # macOS: Rename latest-mac.yml to arch-specific versions | |
| # macOS: 将 latest-mac.yml 重命名为架构特定版本 | |
| if [ -f "dist/latest-mac.yml" ]; then | |
| if [ "${{ matrix.arch }}" = "arm64" ]; then | |
| mv dist/latest-mac.yml dist/latest-mac-arm64.yml | |
| echo "Renamed latest-mac.yml to latest-mac-arm64.yml" | |
| else | |
| # x64: Keep as latest-mac.yml (default for updater) and also create latest-mac-x64.yml | |
| cp dist/latest-mac.yml dist/latest-mac-x64.yml | |
| echo "Created latest-mac-x64.yml for x64" | |
| fi | |
| fi | |
| - name: Remove debug files | |
| shell: bash | |
| run: | | |
| # 删除 builder-debug.yml | |
| find dist -name "builder-debug.yml" -delete || true | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.platform }}-${{ matrix.arch || 'default' }}-build | |
| path: | | |
| dist/*.dmg | |
| dist/*.zip | |
| dist/*-x64.exe | |
| dist/*-arm64.exe | |
| dist/*.AppImage | |
| dist/*.deb | |
| dist/*.blockmap | |
| dist/latest*.yml | |
| if-no-files-found: ignore | |
| release: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| if: startsWith(github.ref, 'refs/tags/') | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Set release version | |
| shell: bash | |
| run: echo "VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_ENV" | |
| - name: List artifacts for debugging | |
| shell: bash | |
| run: | | |
| echo "=== Artifact structure ===" | |
| find artifacts -type f -name "*.yml" -o -name "*.exe" -o -name "*.dmg" | head -50 | |
| - name: Create Release with gh CLI | |
| shell: bash | |
| run: | | |
| # 1. Prepare Release Notes | |
| cat > release_notes.md <<EOF | |
| ## 📦 下载安装 | |
| | 平台 | 下载 | | |
| |------|------| | |
| | Windows | [](https://github.com/legeling/PromptHub/releases/latest/download/PromptHub-Setup-${VERSION}-x64.exe) [](https://github.com/legeling/PromptHub/releases/latest/download/PromptHub-Setup-${VERSION}-arm64.exe) | | |
| | macOS | [](https://github.com/legeling/PromptHub/releases/latest/download/PromptHub-${VERSION}-arm64.dmg) [](https://github.com/legeling/PromptHub/releases/latest/download/PromptHub-${VERSION}-x64.dmg) | | |
| | Linux | [](https://github.com/legeling/PromptHub/releases/latest/download/PromptHub-${VERSION}-x64.AppImage) [](https://github.com/legeling/PromptHub/releases/latest/download/prompthub_${VERSION}_amd64.deb) | | |
| ### ⚠️ macOS 首次启动 | |
| 如果提示"无法打开"或"已损坏",请在终端执行: | |
| \`\`\`bash | |
| sudo xattr -rd com.apple.quarantine /Applications/PromptHub.app | |
| \`\`\` | |
| --- | |
| ## 🔄 本次更新 | |
| 详细更新日志请查看 [更新日志](https://github.com/legeling/PromptHub#-更新日志) | |
| EOF | |
| # 2. Collect and Deduplicate Assets | |
| echo "Collecting and deduplicating assets..." | |
| mkdir -p release_assets | |
| # Find all matching files and copy them to a single directory | |
| # This handles duplicates by overwriting (latest version wins) | |
| find artifacts -type f \( \ | |
| -name "PromptHub-*-x64.dmg" -o \ | |
| -name "PromptHub-*-arm64.dmg" -o \ | |
| -name "PromptHub-Setup-*-x64.exe" -o \ | |
| -name "PromptHub-Setup-*-arm64.exe" -o \ | |
| -name "PromptHub-*-x64.AppImage" -o \ | |
| -name "prompthub_*_amd64.deb" -o \ | |
| -name "PromptHub-*.zip" -o \ | |
| -name "latest*.yml" -o \ | |
| -name "*.blockmap" \ | |
| \) -exec cp -f {} release_assets/ \; | |
| echo "Files to upload (deduplicated):" | |
| ls -1 release_assets/ | |
| # 3. Clean up existing release | |
| echo "Checking for existing release..." | |
| gh release delete "${GITHUB_REF_NAME}" --yes --cleanup-tag || true | |
| # IMPORTANT: Add delay to allow GitHub API to propagate the deletion | |
| echo "Waiting for GitHub API consistency..." | |
| sleep 10 | |
| # 4. Re-create Tag (Ensure it exists for the release) | |
| git tag -f "${GITHUB_REF_NAME}" | |
| git push origin "${GITHUB_REF_NAME}" --force | |
| # 5. Create Release and Upload | |
| echo "Creating release..." | |
| gh release create "${GITHUB_REF_NAME}" \ | |
| release_assets/* \ | |
| --title "PromptHub ${VERSION}" \ | |
| --notes-file release_notes.md \ | |
| --draft=false \ | |
| --prerelease=${{ contains(github.ref, 'beta') || contains(github.ref, 'alpha') }} \ | |
| --generate-notes | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |