mirror of
https://github.com/delibae/claude-prism.git
synced 2026-10-07 02:58:00 +00:00
Three related environment issues are addressed:
1. Linux ICU version mismatch (#91):
The Linux build used pkg-config to dynamically link against the host's
ICU (libicuuc.so.70 on Ubuntu 22.04). Users on newer distros (e.g.
Ubuntu 25.10 with ICU 76) get "cannot open shared object" errors.
Switch to vcpkg static linking, mirroring the macOS fix (commit 9566956).
2. MCP servers fail on macOS GUI app (#87):
macOS GUI apps inherit a minimal PATH (/usr/bin:/bin) that lacks
/opt/homebrew/bin, so MCP server commands like `uv` silently fail.
Prepend common tool directories (~/.local/bin, ~/.cargo/bin,
/opt/homebrew/bin, NVM paths, etc.) to the child process PATH in
create_command().
3. Existing NVM-installed Claude Code ignored (#90):
find_claude_binary() relied on `which` which fails in GUI apps without
NVM in PATH. Add NVM_BIN env var check and login shell fallback
(`$SHELL -l -c "which claude"`) to discover claude through the user's
actual shell configuration.
Closes #87, closes #90, closes #91
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
642 lines
25 KiB
YAML
642 lines
25 KiB
YAML
name: Build Desktop
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
release_tag:
|
|
description: "Upload to this release tag (e.g. v1.0.0). Leave empty for artifact-only build."
|
|
required: false
|
|
default: ""
|
|
push:
|
|
tags:
|
|
- "v*"
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
env:
|
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
|
|
|
jobs:
|
|
# ──────────────────────────────────────────────
|
|
# Windows
|
|
# ──────────────────────────────────────────────
|
|
build-windows:
|
|
runs-on: windows-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Set vcpkg path
|
|
shell: bash
|
|
run: echo "VCPKG_INSTALLED=$VCPKG_INSTALLATION_ROOT/installed" >> $GITHUB_ENV
|
|
|
|
- name: Restore vcpkg cache
|
|
id: vcpkg-cache
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ${{ env.VCPKG_INSTALLED }}
|
|
key: vcpkg-win-v2
|
|
|
|
- name: Install Windows dependencies (vcpkg)
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
shell: bash
|
|
env:
|
|
VCPKG_BINARY_SOURCES: "clear"
|
|
run: |
|
|
vcpkg install "harfbuzz[graphite2]:x64-windows-static-release" \
|
|
fontconfig:x64-windows-static-release \
|
|
freetype:x64-windows-static-release \
|
|
icu:x64-windows-static-release
|
|
|
|
- name: Save vcpkg cache
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@v4
|
|
with:
|
|
path: ${{ env.VCPKG_INSTALLED }}
|
|
key: vcpkg-win-v2
|
|
|
|
- name: Set Windows build environment
|
|
shell: bash
|
|
run: |
|
|
echo "TECTONIC_DEP_BACKEND=vcpkg" >> $GITHUB_ENV
|
|
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> $GITHUB_ENV
|
|
echo "VCPKGRS_TRIPLET=x64-windows-static-release" >> $GITHUB_ENV
|
|
echo "VCPKG_DEFAULT_HOST_TRIPLET=x64-windows-static-release" >> $GITHUB_ENV
|
|
echo "RUSTFLAGS=-Ctarget-feature=+crt-static" >> $GITHUB_ENV
|
|
echo "CXXFLAGS=/std:c++17" >> $GITHUB_ENV
|
|
echo "CFLAGS=" >> $GITHUB_ENV
|
|
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: x86_64-pc-windows-msvc
|
|
|
|
- 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
|
|
shell: bash
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
ZOTERO_CONSUMER_KEY: ${{ secrets.ZOTERO_CONSUMER_KEY }}
|
|
ZOTERO_CONSUMER_SECRET: ${{ secrets.ZOTERO_CONSUMER_SECRET }}
|
|
run: pnpm --filter @claude-prism/desktop tauri build --target x86_64-pc-windows-msvc
|
|
|
|
- name: Collect updater artifacts
|
|
id: collect
|
|
shell: bash
|
|
run: |
|
|
BUNDLE="apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle"
|
|
NSIS_SIG=$(find "$BUNDLE/nsis" -name '*-setup.exe.sig' 2>/dev/null | head -1)
|
|
NSIS_EXE=$(find "$BUNDLE/nsis" -name '*-setup.exe' ! -name '*.sig' 2>/dev/null | head -1)
|
|
|
|
if [ -n "$NSIS_SIG" ] && [ -n "$NSIS_EXE" ]; then
|
|
echo "sig=$(cat "$NSIS_SIG")" >> $GITHUB_OUTPUT
|
|
echo "url=$(basename "$NSIS_EXE")" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Upload build artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: desktop-windows
|
|
path: |
|
|
apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/**/*.exe
|
|
apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/**/*.msi
|
|
apps/desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/**/*.sig
|
|
if-no-files-found: warn
|
|
|
|
outputs:
|
|
sig: ${{ steps.collect.outputs.sig }}
|
|
url: ${{ steps.collect.outputs.url }}
|
|
|
|
# ──────────────────────────────────────────────
|
|
# macOS (Apple Silicon)
|
|
# ──────────────────────────────────────────────
|
|
build-macos:
|
|
runs-on: macos-14
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
# Build tools required by vcpkg ports (autotools for gperf, fontconfig, etc.)
|
|
# These are compile-time only — they do NOT create runtime dylib dependencies.
|
|
- name: Install build tools
|
|
run: brew install autoconf autoconf-archive automake libtool pkg-config
|
|
|
|
# Static linking via vcpkg — avoids runtime dependency on Homebrew dylibs.
|
|
# Ref: https://tectonic-typesetting.github.io/book/latest/howto/build-tectonic/
|
|
# Ref: https://learn.microsoft.com/en-us/vcpkg/users/triplets (arm64-osx defaults to static)
|
|
- name: Setup vcpkg
|
|
run: |
|
|
git clone --depth 1 https://github.com/microsoft/vcpkg $HOME/vcpkg
|
|
$HOME/vcpkg/bootstrap-vcpkg.sh
|
|
echo "VCPKG_ROOT=$HOME/vcpkg" >> $GITHUB_ENV
|
|
|
|
- name: Restore vcpkg cache
|
|
id: vcpkg-cache
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/vcpkg/installed
|
|
key: vcpkg-macos-arm64-v1
|
|
|
|
- name: Install macOS dependencies (vcpkg)
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
env:
|
|
VCPKG_BINARY_SOURCES: "clear"
|
|
run: |
|
|
$HOME/vcpkg/vcpkg install \
|
|
"harfbuzz[graphite2]:arm64-osx" \
|
|
fontconfig:arm64-osx \
|
|
freetype:arm64-osx \
|
|
icu:arm64-osx
|
|
|
|
- name: Save vcpkg cache
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@v4
|
|
with:
|
|
path: ~/vcpkg/installed
|
|
key: vcpkg-macos-arm64-v1
|
|
|
|
- name: Set macOS build environment
|
|
run: |
|
|
echo "TECTONIC_DEP_BACKEND=vcpkg" >> $GITHUB_ENV
|
|
echo "CXXFLAGS=-std=c++17" >> $GITHUB_ENV
|
|
echo "CFLAGS=" >> $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: aarch64-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 }}
|
|
run: pnpm --filter @claude-prism/desktop tauri build --target aarch64-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="aarch64-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/aarch64-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
|
|
path: |
|
|
apps/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/**/*.dmg
|
|
apps/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/**/*.app.tar.gz
|
|
apps/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/**/*.sig
|
|
if-no-files-found: warn
|
|
|
|
outputs:
|
|
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
|
|
|
|
# Build tools required by vcpkg ports (autotools for gperf, fontconfig, etc.)
|
|
- name: Install build tools
|
|
run: brew install autoconf autoconf-archive automake libtool pkg-config
|
|
|
|
# Static linking via vcpkg — same approach as Apple Silicon and Windows.
|
|
- name: Setup vcpkg
|
|
run: |
|
|
git clone --depth 1 https://github.com/microsoft/vcpkg $HOME/vcpkg
|
|
$HOME/vcpkg/bootstrap-vcpkg.sh
|
|
echo "VCPKG_ROOT=$HOME/vcpkg" >> $GITHUB_ENV
|
|
|
|
- name: Restore vcpkg cache
|
|
id: vcpkg-cache
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/vcpkg/installed
|
|
key: vcpkg-macos-x64-v1
|
|
|
|
- name: Install macOS dependencies (vcpkg)
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
env:
|
|
VCPKG_BINARY_SOURCES: "clear"
|
|
run: |
|
|
$HOME/vcpkg/vcpkg install \
|
|
"harfbuzz[graphite2]:x64-osx" \
|
|
fontconfig:x64-osx \
|
|
freetype:x64-osx \
|
|
icu:x64-osx
|
|
|
|
- name: Save vcpkg cache
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@v4
|
|
with:
|
|
path: ~/vcpkg/installed
|
|
key: vcpkg-macos-x64-v1
|
|
|
|
- name: Set macOS build environment
|
|
run: |
|
|
echo "TECTONIC_DEP_BACKEND=vcpkg" >> $GITHUB_ENV
|
|
echo "CXXFLAGS=-std=c++17" >> $GITHUB_ENV
|
|
echo "CFLAGS=" >> $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 }}
|
|
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
|
|
# ──────────────────────────────────────────────
|
|
build-linux:
|
|
runs-on: ubuntu-22.04
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Install Linux dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf \
|
|
autoconf autoconf-archive automake libtool pkg-config
|
|
|
|
# Static linking via vcpkg — avoids runtime dependency on system ICU/harfbuzz.
|
|
# Without this, the binary links against the build host's libicuuc.so.70
|
|
# (Ubuntu 22.04) and fails on distros shipping newer ICU (e.g. Ubuntu 25.10
|
|
# with libicuuc.so.76). Mirrors the macOS approach (commit 9566956).
|
|
- name: Setup vcpkg
|
|
run: |
|
|
git clone --depth 1 https://github.com/microsoft/vcpkg $HOME/vcpkg
|
|
$HOME/vcpkg/bootstrap-vcpkg.sh
|
|
echo "VCPKG_ROOT=$HOME/vcpkg" >> $GITHUB_ENV
|
|
|
|
- name: Restore vcpkg cache
|
|
id: vcpkg-cache
|
|
uses: actions/cache/restore@v4
|
|
with:
|
|
path: ~/vcpkg/installed
|
|
key: vcpkg-linux-x64-v1
|
|
|
|
- name: Install Linux dependencies (vcpkg)
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
env:
|
|
VCPKG_BINARY_SOURCES: "clear"
|
|
run: |
|
|
$HOME/vcpkg/vcpkg install \
|
|
"harfbuzz[graphite2]:x64-linux" \
|
|
fontconfig:x64-linux \
|
|
freetype:x64-linux \
|
|
icu:x64-linux
|
|
|
|
- name: Save vcpkg cache
|
|
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@v4
|
|
with:
|
|
path: ~/vcpkg/installed
|
|
key: vcpkg-linux-x64-v1
|
|
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: x86_64-unknown-linux-gnu
|
|
|
|
- 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 }}
|
|
TECTONIC_DEP_BACKEND: vcpkg
|
|
CXXFLAGS: "-std=c++17"
|
|
CFLAGS: ""
|
|
run: pnpm --filter @claude-prism/desktop tauri build --target x86_64-unknown-linux-gnu
|
|
|
|
- name: Collect updater artifacts
|
|
id: collect
|
|
run: |
|
|
BUNDLE="apps/desktop/src-tauri/target/x86_64-unknown-linux-gnu/release/bundle"
|
|
APPIMAGE_SIG=$(find "$BUNDLE/appimage" -name '*.AppImage.sig' 2>/dev/null | head -1)
|
|
APPIMAGE=$(find "$BUNDLE/appimage" -name '*.AppImage' ! -name '*.sig' 2>/dev/null | head -1)
|
|
|
|
if [ -n "$APPIMAGE_SIG" ] && [ -n "$APPIMAGE" ]; then
|
|
echo "sig=$(cat "$APPIMAGE_SIG")" >> $GITHUB_OUTPUT
|
|
echo "url=$(basename "$APPIMAGE")" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Upload build artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: desktop-linux
|
|
path: |
|
|
apps/desktop/src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/**/*.deb
|
|
apps/desktop/src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/**/*.rpm
|
|
apps/desktop/src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/**/*.AppImage
|
|
apps/desktop/src-tauri/target/x86_64-unknown-linux-gnu/release/bundle/**/*.sig
|
|
if-no-files-found: warn
|
|
|
|
outputs:
|
|
sig: ${{ steps.collect.outputs.sig }}
|
|
url: ${{ steps.collect.outputs.url }}
|
|
|
|
# ──────────────────────────────────────────────
|
|
# Publish: generate latest.json & upload to release
|
|
# ──────────────────────────────────────────────
|
|
publish:
|
|
needs: [build-windows, build-macos, build-macos-intel, build-linux]
|
|
runs-on: ubuntu-latest
|
|
if: startsWith(github.ref, 'refs/tags/v') || inputs.release_tag != ''
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Determine tag
|
|
id: tag
|
|
run: |
|
|
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
|
|
echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "tag=${{ inputs.release_tag }}" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: artifacts
|
|
|
|
- name: Generate latest.json
|
|
env:
|
|
TAG: ${{ steps.tag.outputs.tag }}
|
|
WIN_SIG: ${{ needs.build-windows.outputs.sig }}
|
|
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: |
|
|
VERSION="${TAG#v}"
|
|
PUB_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
export BASE_URL="https://github.com/delibae/claude-prism/releases/download/$TAG"
|
|
|
|
node -e "
|
|
const BASE = process.env.BASE_URL;
|
|
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)
|
|
platforms['windows-x86_64'] = { signature: process.env.WIN_SIG, url: BASE + '/ClaudePrism-Windows-setup.exe' };
|
|
|
|
const data = {
|
|
version: '$VERSION',
|
|
notes: 'ClaudePrism $TAG',
|
|
pub_date: '$PUB_DATE',
|
|
platforms
|
|
};
|
|
require('fs').writeFileSync('latest.json', JSON.stringify(data, null, 2));
|
|
console.log(JSON.stringify(data, null, 2));
|
|
"
|
|
|
|
- name: Create draft release
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
TAG="${{ steps.tag.outputs.tag }}"
|
|
gh release view "$TAG" > /dev/null 2>&1 || \
|
|
gh release create "$TAG" --title "ClaudePrism $TAG" --generate-notes --draft
|
|
|
|
- name: Rename and upload assets
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
TAG="${{ steps.tag.outputs.tag }}"
|
|
mkdir -p upload
|
|
|
|
# Rename platform artifacts to version-free names
|
|
# 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/
|
|
|
|
echo "==> Uploading:"
|
|
ls -la upload/
|
|
|
|
for file in upload/*; do
|
|
gh release upload "$TAG" "$file" --clobber
|
|
done
|
|
|
|
# Release stays as draft — publish manually from GitHub Releases UI
|