From b5ced3a7faf48db9fa0b9c6322868fef0acef958 Mon Sep 17 00:00:00 2001 From: delibae Date: Tue, 17 Mar 2026 03:19:05 +0900 Subject: [PATCH] feat: add Intel Mac build workflow, bump version to 1.0.8 Add build-macos-intel job using macos-15-intel runner with x86_64-apple-darwin target. Includes code signing, notarization, and updater support (darwin-x86_64 platform key in latest.json). Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build-desktop.yml | 153 +++++++++++++++++++++++-- apps/desktop/package.json | 2 +- apps/desktop/src-tauri/tauri.conf.json | 2 +- package.json | 2 +- 4 files changed, 148 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index c9e4b03..07ae277 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -242,6 +242,133 @@ jobs: sig: ${{ steps.collect.outputs.sig }} url: ${{ steps.collect.outputs.url }} + # ────────────────────────────────────────────── + # macOS (Intel x86_64) + # Ref: https://github.com/actions/runner-images/issues/13045 + # macos-13 retired 2025-12-04, macos-15-intel is the replacement + # Intel runners available until Fall 2027 + # Ref: https://v2.tauri.app/distribute/pipelines/github/ + # Ref: https://v2.tauri.app/plugin/updater/ (platform key: darwin-x86_64) + # ────────────────────────────────────────────── + build-macos-intel: + runs-on: macos-15-intel + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install macOS dependencies + run: | + brew install icu4c harfbuzz pkg-config graphite2 freetype fontconfig + INCLUDES="-I$(brew --prefix harfbuzz)/include -I$(brew --prefix freetype)/include -I$(brew --prefix graphite2)/include -I$(brew --prefix icu4c)/include" + { + echo "PKG_CONFIG_PATH=$(brew --prefix icu4c)/lib/pkgconfig:$(brew --prefix harfbuzz)/lib/pkgconfig:$(brew --prefix graphite2)/lib/pkgconfig:$(brew --prefix freetype)/lib/pkgconfig:$(brew --prefix libpng)/lib/pkgconfig:$(brew --prefix fontconfig)/lib/pkgconfig" + echo "CXXFLAGS=-std=c++17 $INCLUDES" + echo "CFLAGS=$INCLUDES" + echo "LDFLAGS=-L$(brew --prefix harfbuzz)/lib -L$(brew --prefix freetype)/lib -L$(brew --prefix graphite2)/lib -L$(brew --prefix icu4c)/lib" + } >> $GITHUB_ENV + + - name: Import Apple certificate + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + run: | + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + KEYCHAIN_PASSWORD=$(openssl rand -base64 32) + + # Create temporary keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" + security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + + # Import certificate + echo "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12 + security import $RUNNER_TEMP/certificate.p12 \ + -k "$KEYCHAIN_PATH" \ + -P "$APPLE_CERTIFICATE_PASSWORD" \ + -T /usr/bin/codesign \ + -T /usr/bin/security + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + security list-keychains -d user -s "$KEYCHAIN_PATH" login.keychain-db + + - uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-apple-darwin + + - uses: swatinem/rust-cache@v2 + with: + workspaces: apps/desktop/src-tauri -> target + + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - run: pnpm install + + - name: Build Tauri app + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ZOTERO_CONSUMER_KEY: ${{ secrets.ZOTERO_CONSUMER_KEY }} + ZOTERO_CONSUMER_SECRET: ${{ secrets.ZOTERO_CONSUMER_SECRET }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + TECTONIC_DEP_BACKEND: pkg-config + run: pnpm --filter @claude-prism/desktop tauri build --target x86_64-apple-darwin + + - name: Notarize DMG + env: + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + run: | + TARGET="x86_64-apple-darwin" + BUNDLE="apps/desktop/src-tauri/target/$TARGET/release/bundle" + DMG_PATH=$(find "$BUNDLE/dmg" -name '*.dmg' | head -1) + APP_PATH="$BUNDLE/macos/ClaudePrism.app" + + if [ -z "$DMG_PATH" ]; then + echo "Error: DMG not found" + exit 1 + fi + + echo "==> Notarizing $DMG_PATH ..." + xcrun notarytool submit "$DMG_PATH" \ + --apple-id "$APPLE_ID" \ + --team-id "$APPLE_TEAM_ID" \ + --password "$APPLE_PASSWORD" \ + --wait --timeout 30m + + echo "==> Stapling..." + xcrun stapler staple "$DMG_PATH" + xcrun stapler staple "$APP_PATH" + + - name: Collect updater artifacts + id: collect + run: | + BUNDLE="apps/desktop/src-tauri/target/x86_64-apple-darwin/release/bundle" + TAR_SIG=$(find "$BUNDLE/macos" -name '*.app.tar.gz.sig' 2>/dev/null | head -1) + TAR_GZ=$(find "$BUNDLE/macos" -name '*.app.tar.gz' ! -name '*.sig' 2>/dev/null | head -1) + + if [ -n "$TAR_SIG" ] && [ -n "$TAR_GZ" ]; then + echo "sig=$(cat "$TAR_SIG")" >> $GITHUB_OUTPUT + echo "url=$(basename "$TAR_GZ")" >> $GITHUB_OUTPUT + fi + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: desktop-macos-intel + path: | + apps/desktop/src-tauri/target/x86_64-apple-darwin/release/bundle/**/*.dmg + apps/desktop/src-tauri/target/x86_64-apple-darwin/release/bundle/**/*.app.tar.gz + apps/desktop/src-tauri/target/x86_64-apple-darwin/release/bundle/**/*.sig + if-no-files-found: warn + + outputs: + sig: ${{ steps.collect.outputs.sig }} + url: ${{ steps.collect.outputs.url }} + # ────────────────────────────────────────────── # Linux # ────────────────────────────────────────────── @@ -316,7 +443,7 @@ jobs: # Publish: generate latest.json & upload to release # ────────────────────────────────────────────── publish: - needs: [build-windows, build-macos, build-linux] + needs: [build-windows, build-macos, build-macos-intel, build-linux] runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/v') || inputs.release_tag != '' @@ -344,6 +471,8 @@ jobs: WIN_URL: ${{ needs.build-windows.outputs.url }} MAC_SIG: ${{ needs.build-macos.outputs.sig }} MAC_URL: ${{ needs.build-macos.outputs.url }} + MAC_INTEL_SIG: ${{ needs.build-macos-intel.outputs.sig }} + MAC_INTEL_URL: ${{ needs.build-macos-intel.outputs.url }} LIN_SIG: ${{ needs.build-linux.outputs.sig }} LIN_URL: ${{ needs.build-linux.outputs.url }} run: | @@ -356,6 +485,8 @@ jobs: const platforms = {}; if (process.env.MAC_SIG) platforms['darwin-aarch64'] = { signature: process.env.MAC_SIG, url: BASE + '/ClaudePrism-macOS.app.tar.gz' }; + if (process.env.MAC_INTEL_SIG) + platforms['darwin-x86_64'] = { signature: process.env.MAC_INTEL_SIG, url: BASE + '/ClaudePrism-macOS-Intel.app.tar.gz' }; if (process.env.LIN_SIG) platforms['linux-x86_64'] = { signature: process.env.LIN_SIG, url: BASE + '/ClaudePrism-Linux.AppImage' }; if (process.env.WIN_SIG) @@ -387,13 +518,19 @@ jobs: mkdir -p upload # Rename platform artifacts to version-free names - find artifacts -name "*.dmg" | head -1 | xargs -I{} cp {} upload/ClaudePrism-macOS.dmg - find artifacts -name "*.app.tar.gz" | head -1 | xargs -I{} cp {} upload/ClaudePrism-macOS.app.tar.gz - find artifacts -name "*-setup.exe" | head -1 | xargs -I{} cp {} upload/ClaudePrism-Windows-setup.exe - find artifacts -name "*.msi" | head -1 | xargs -I{} cp {} upload/ClaudePrism-Windows.msi - find artifacts -name "*.deb" | head -1 | xargs -I{} cp {} upload/ClaudePrism-Linux.deb - find artifacts -name "*.rpm" | head -1 | xargs -I{} cp {} upload/ClaudePrism-Linux.rpm - find artifacts -name "*.AppImage" | head -1 | xargs -I{} cp {} upload/ClaudePrism-Linux.AppImage + # macOS Apple Silicon (from desktop-macos artifact) + find artifacts/desktop-macos -name "*.dmg" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-macOS.dmg + find artifacts/desktop-macos -name "*.app.tar.gz" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-macOS.app.tar.gz + # macOS Intel (from desktop-macos-intel artifact) + find artifacts/desktop-macos-intel -name "*.dmg" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-macOS-Intel.dmg + find artifacts/desktop-macos-intel -name "*.app.tar.gz" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-macOS-Intel.app.tar.gz + # Windows + find artifacts/desktop-windows -name "*-setup.exe" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-Windows-setup.exe + find artifacts/desktop-windows -name "*.msi" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-Windows.msi + # Linux + find artifacts/desktop-linux -name "*.deb" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-Linux.deb + find artifacts/desktop-linux -name "*.rpm" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-Linux.rpm + find artifacts/desktop-linux -name "*.AppImage" 2>/dev/null | head -1 | xargs -I{} cp {} upload/ClaudePrism-Linux.AppImage cp latest.json upload/ diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a55f8c1..6ebd651 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@claude-prism/desktop", - "version": "1.0.7", + "version": "1.0.8", "private": true, "type": "module", "scripts": { diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index e4606f4..0cd66fb 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/nicegui-unofficial/nicegui-tauri-template/main/src-tauri/tauri.conf-v2-schema.json", "identifier": "com.claude-prism.desktop", "productName": "ClaudePrism", - "version": "1.0.7", + "version": "1.0.8", "build": { "beforeDevCommand": "pnpm dev", "beforeBuildCommand": "pnpm build", diff --git a/package.json b/package.json index f89902e..7250dec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@claude-prism/root", "description": "Open-Source AI LaTeX writing workspace", - "version": "1.0.7", + "version": "1.0.8", "repository": { "type": "git", "url": "https://github.com/delibae/claude-prism"