claude-prism/.github/workflows/build-desktop.yml
delibae 12a79b0981 fix: static-link ICU on Linux and augment PATH for GUI-launched child processes
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>
2026-03-25 22:10:19 +09:00

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