ci: cut over desktop releases to Electron
Repackages Electron app for legacy Tauri updater migration Stops release and manual DMG workflows from building Tauri Documents transition flow and cleanup timing
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
name: Build macOS DMG (arm64)
|
||||
name: Build Electron macOS DMG (arm64)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -16,114 +16,7 @@ on:
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
RUST_BACKTRACE: short
|
||||
|
||||
jobs:
|
||||
build-macos-dmg-arm64:
|
||||
name: Build DMG (arm64, ${{ inputs.macos_version }})
|
||||
runs-on: ${{ inputs.macos_version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.ref || github.ref }}
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: aarch64-apple-darwin
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: packages/desktop/src-tauri
|
||||
key: aarch64-apple-darwin
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Install 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)
|
||||
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
|
||||
echo "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12
|
||||
security import $RUNNER_TEMP/certificate.p12 \
|
||||
-P "$APPLE_CERTIFICATE_PASSWORD" \
|
||||
-A -t cert -f pkcs12 \
|
||||
-k "$KEYCHAIN_PATH"
|
||||
|
||||
security list-keychain -d user -s "$KEYCHAIN_PATH"
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: \
|
||||
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
|
||||
- name: Set up notarization credentials
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
run: |
|
||||
if [ -z "$APPLE_ID" ] || [ -z "$APPLE_TEAM_ID" ] || [ -z "$APPLE_PASSWORD" ]; then
|
||||
echo "Error: Missing Apple notarization credentials"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
xcrun notarytool store-credentials "openchamber-notarize" \
|
||||
--apple-id "$APPLE_ID" \
|
||||
--team-id "$APPLE_TEAM_ID" \
|
||||
--password "$APPLE_PASSWORD"
|
||||
|
||||
- name: Build UI package
|
||||
run: bun run --cwd packages/ui build
|
||||
|
||||
- name: Build Desktop app (arm64)
|
||||
run: bun run --cwd packages/desktop build && bun run --cwd packages/desktop tauri build --target aarch64-apple-darwin
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
|
||||
- name: Prepare DMG artifact
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p artifacts
|
||||
DMG_PATH="packages/desktop/src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/*.dmg"
|
||||
if ls $DMG_PATH 1> /dev/null 2>&1; then
|
||||
DMG_FILE=$(ls $DMG_PATH | head -n 1)
|
||||
DMG_NAME="OpenChamber_${{ inputs.macos_version }}_arm64.dmg"
|
||||
cp "$DMG_FILE" "artifacts/$DMG_NAME"
|
||||
else
|
||||
echo "Error: DMG file not found at $DMG_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload DMG artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dmg-${{ inputs.macos_version }}-arm64
|
||||
path: artifacts/*.dmg
|
||||
retention-days: 7
|
||||
|
||||
build-macos-dmg-arm64-electron:
|
||||
name: Build Electron DMG (arm64, ${{ inputs.macos_version }})
|
||||
runs-on: ${{ inputs.macos_version }}
|
||||
|
||||
+183
-377
@@ -78,299 +78,6 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
build-desktop-macos:
|
||||
needs: create-release
|
||||
runs-on: macos-26
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [aarch64-apple-darwin, x86_64-apple-darwin]
|
||||
include:
|
||||
- target: aarch64-apple-darwin
|
||||
arch: aarch64
|
||||
platform: darwin-aarch64
|
||||
- target: x86_64-apple-darwin
|
||||
arch: x86_64
|
||||
platform: darwin-x86_64
|
||||
outputs:
|
||||
version: ${{ needs.create-release.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: packages/desktop/src-tauri
|
||||
key: ${{ matrix.target }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Install Apple Certificate
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
run: |
|
||||
# Create temporary keychain
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
|
||||
|
||||
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 \
|
||||
-P "$APPLE_CERTIFICATE_PASSWORD" \
|
||||
-A -t cert -f pkcs12 \
|
||||
-k "$KEYCHAIN_PATH"
|
||||
|
||||
security list-keychain -d user -s "$KEYCHAIN_PATH"
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: \
|
||||
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
|
||||
- name: Set up notarization credentials
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
run: |
|
||||
# Validate secrets are set
|
||||
if [ -z "$APPLE_ID" ] || [ -z "$APPLE_TEAM_ID" ] || [ -z "$APPLE_PASSWORD" ]; then
|
||||
echo "Error: Missing Apple notarization credentials"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
xcrun notarytool store-credentials "openchamber-notarize" \
|
||||
--apple-id "$APPLE_ID" \
|
||||
--team-id "$APPLE_TEAM_ID" \
|
||||
--password "$APPLE_PASSWORD"
|
||||
|
||||
- name: Build UI package
|
||||
run: bun run --cwd packages/ui build
|
||||
|
||||
- name: Build Desktop app
|
||||
# Note: We use inline commands instead of desktop:build to pass architecture-specific --target flag
|
||||
# This enables cross-compilation for both arm64 and x86_64 from the same runner
|
||||
run: |
|
||||
export TAURI_ENV_TARGET_TRIPLE=${{ matrix.target }}
|
||||
bun run --cwd packages/desktop build
|
||||
bun run --cwd packages/desktop tauri build --target ${{ matrix.target }}
|
||||
env:
|
||||
TAURI_ENV_TARGET_TRIPLE: ${{ matrix.target }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
|
||||
- name: Verify binary architectures
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
BUNDLE_DIR="packages/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/macos"
|
||||
|
||||
if [ ! -d "$BUNDLE_DIR" ]; then
|
||||
echo "❌ Error: bundle directory not found: $BUNDLE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APP_PATH=$(find "$BUNDLE_DIR" -maxdepth 2 -name "*.app" -print -quit)
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
echo "❌ Error: .app bundle not found under $BUNDLE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔍 Verifying binary architectures in $APP_PATH"
|
||||
|
||||
# Extract raw architecture names (macOS file command reports ARM as "arm64")
|
||||
MAIN_ARCH_RAW=$(file "$APP_PATH/Contents/MacOS/openchamber-desktop" | grep -oE 'arm64|x86_64|aarch64' | head -1)
|
||||
SIDEARCH_ARCH_RAW=$(file "$APP_PATH/Contents/MacOS/openchamber-server" | grep -oE 'arm64|x86_64|aarch64' | head -1)
|
||||
|
||||
# Normalize architecture names (arm64 -> aarch64 for consistency with Rust/Tauri)
|
||||
normalize_arch() {
|
||||
case "$1" in
|
||||
arm64) echo "aarch64" ;;
|
||||
aarch64|x86_64) echo "$1" ;;
|
||||
*) echo "unknown" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
MAIN_ARCH=$(normalize_arch "$MAIN_ARCH_RAW")
|
||||
SIDEARCH_ARCH=$(normalize_arch "$SIDEARCH_ARCH_RAW")
|
||||
EXPECTED_ARCH=$(echo "${{ matrix.target }}" | grep -oE 'aarch64|x86_64' | head -1)
|
||||
|
||||
echo " Main: $MAIN_ARCH_RAW → $MAIN_ARCH"
|
||||
echo " Sidecar: $SIDEARCH_ARCH_RAW → $SIDEARCH_ARCH"
|
||||
echo " Expected: $EXPECTED_ARCH"
|
||||
|
||||
if [ "$MAIN_ARCH" != "$EXPECTED_ARCH" ]; then
|
||||
echo "❌ ERROR: Main binary architecture mismatch!"
|
||||
echo " Expected: $EXPECTED_ARCH"
|
||||
echo " Got: $MAIN_ARCH (raw: $MAIN_ARCH_RAW)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$SIDEARCH_ARCH" != "$EXPECTED_ARCH" ]; then
|
||||
echo "❌ ERROR: Sidecar binary architecture mismatch!"
|
||||
echo " Expected: $EXPECTED_ARCH"
|
||||
echo " Got: $SIDEARCH_ARCH (raw: $SIDEARCH_ARCH_RAW)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Architecture verification passed: both binaries match $EXPECTED_ARCH"
|
||||
|
||||
- name: Verify macOS entitlements
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
BUNDLE_DIR="packages/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/macos"
|
||||
|
||||
if [ ! -d "$BUNDLE_DIR" ]; then
|
||||
echo "Error: bundle directory not found: $BUNDLE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APP_PATH=$(find "$BUNDLE_DIR" -maxdepth 2 -name "*.app" -print -quit)
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
echo "Error: .app bundle not found under $BUNDLE_DIR"
|
||||
echo "Contents:"; ls -la "$BUNDLE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Verifying app bundle: $APP_PATH"
|
||||
codesign -vv "$APP_PATH"
|
||||
|
||||
ENTITLEMENTS=$(codesign -d --entitlements :- "$APP_PATH" 2>&1 || true)
|
||||
echo "$ENTITLEMENTS"
|
||||
|
||||
if echo "$ENTITLEMENTS" | grep -q "com.apple.security.app-sandbox"; then
|
||||
echo "Error: app sandbox entitlement is present"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for key in \
|
||||
com.apple.security.cs.allow-jit \
|
||||
com.apple.security.cs.allow-unsigned-executable-memory \
|
||||
com.apple.security.cs.disable-executable-page-protection \
|
||||
com.apple.security.cs.disable-library-validation
|
||||
do
|
||||
if ! echo "$ENTITLEMENTS" | grep -q "<key>$key</key>"; then
|
||||
echo "Error: required entitlement missing: $key"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Prepare release artifacts
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
VERSION="${{ needs.create-release.outputs.version }}"
|
||||
|
||||
# Copy DMG (Tauri names it with the target triple in the path)
|
||||
DMG_PATH="packages/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg"
|
||||
if ls $DMG_PATH 1> /dev/null 2>&1; then
|
||||
DMG_FILE=$(ls $DMG_PATH | head -n 1)
|
||||
DMG_NAME="OpenChamber_${VERSION}_${{ matrix.platform }}.dmg"
|
||||
cp "$DMG_FILE" "artifacts/$DMG_NAME"
|
||||
else
|
||||
echo "Error: DMG file not found at $DMG_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy tar.gz and signature for updater
|
||||
TAR_PATH="packages/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/macos/*.tar.gz"
|
||||
SIG_PATH="packages/desktop/src-tauri/target/${{ matrix.target }}/release/bundle/macos/*.tar.gz.sig"
|
||||
|
||||
if ls $TAR_PATH 1> /dev/null 2>&1; then
|
||||
TAR_FILE=$(ls $TAR_PATH | head -n 1)
|
||||
TAR_BASE=$(basename "$TAR_FILE")
|
||||
TAR_NAME="${TAR_BASE%.tar.gz}-${{ matrix.platform }}.tar.gz"
|
||||
cp "$TAR_FILE" "artifacts/$TAR_NAME"
|
||||
else
|
||||
echo "Error: tar.gz file not found at $TAR_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ls $SIG_PATH 1> /dev/null 2>&1; then
|
||||
SIG_FILE=$(ls $SIG_PATH | head -n 1)
|
||||
SIG_BASE=$(basename "$SIG_FILE")
|
||||
SIG_NAME="${SIG_BASE%.tar.gz.sig}-${{ matrix.platform }}.tar.gz.sig"
|
||||
cp "$SIG_FILE" "artifacts/$SIG_NAME"
|
||||
else
|
||||
echo "Error: signature file not found at $SIG_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Successfully prepared artifacts:"
|
||||
ls -lh artifacts/
|
||||
|
||||
- name: Generate update manifest
|
||||
run: |
|
||||
VERSION="${{ needs.create-release.outputs.version }}"
|
||||
|
||||
# Find the signature file for this platform
|
||||
SIG_FILE=$(find artifacts -name "*-${{ matrix.platform }}.tar.gz.sig" | head -1)
|
||||
if [ -f "$SIG_FILE" ]; then
|
||||
SIGNATURE=$(cat "$SIG_FILE")
|
||||
else
|
||||
SIGNATURE=""
|
||||
fi
|
||||
|
||||
# Find the tar.gz file name for this platform
|
||||
TAR_FILE=$(find artifacts -name "*-${{ matrix.platform }}.tar.gz" ! -name "*.sig" | head -1)
|
||||
TAR_NAME=$(basename "$TAR_FILE" 2>/dev/null || echo "OpenChamber-${{ matrix.platform }}.app.tar.gz")
|
||||
|
||||
cat > artifacts/latest-${{ matrix.platform }}.json << EOF
|
||||
{
|
||||
"version": "${VERSION}",
|
||||
"notes": "See release notes at https://github.com/${{ github.repository }}/releases/tag/v${VERSION}",
|
||||
"pub_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
||||
"platforms": {
|
||||
"${{ matrix.platform }}": {
|
||||
"signature": "${SIGNATURE}",
|
||||
"url": "https://github.com/${{ github.repository }}/releases/download/v${VERSION}/${TAR_NAME}"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Generated latest-${{ matrix.platform }}.json:"
|
||||
cat artifacts/latest-${{ matrix.platform }}.json
|
||||
|
||||
- name: Upload release assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ needs.create-release.outputs.version }}
|
||||
files: |
|
||||
artifacts/*.dmg
|
||||
artifacts/*.tar.gz
|
||||
artifacts/*.tar.gz.sig
|
||||
artifacts/latest-${{ matrix.platform }}.json
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload manifest as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: manifest-${{ matrix.platform }}
|
||||
path: artifacts/latest-${{ matrix.platform }}.json
|
||||
retention-days: 1
|
||||
|
||||
publish-npm:
|
||||
needs: create-release
|
||||
runs-on: ubuntu-latest
|
||||
@@ -411,89 +118,6 @@ jobs:
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
combine-manifests:
|
||||
needs: [create-release, build-desktop-macos]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download aarch64 manifest
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: manifest-darwin-aarch64
|
||||
path: artifacts
|
||||
|
||||
- name: Download x86_64 manifest
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: manifest-darwin-x86_64
|
||||
path: artifacts
|
||||
|
||||
- name: Combine manifests
|
||||
run: |
|
||||
VERSION="${{ needs.create-release.outputs.version }}"
|
||||
PUB_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
REPO="${{ github.repository }}"
|
||||
|
||||
# Validate that both manifest files exist and are valid JSON
|
||||
if [ ! -f artifacts/latest-darwin-aarch64.json ]; then
|
||||
echo "Error: aarch64 manifest not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f artifacts/latest-darwin-x86_64.json ]; then
|
||||
echo "Error: x86_64 manifest not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate JSON structure
|
||||
if ! jq empty artifacts/latest-darwin-aarch64.json 2>/dev/null; then
|
||||
echo "Error: aarch64 manifest is not valid JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! jq empty artifacts/latest-darwin-x86_64.json 2>/dev/null; then
|
||||
echo "Error: x86_64 manifest is not valid JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate platform data exists in manifests
|
||||
if ! jq -e '.platforms["darwin-aarch64"]' artifacts/latest-darwin-aarch64.json > /dev/null; then
|
||||
echo "Error: darwin-aarch64 platform data not found in manifest"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! jq -e '.platforms["darwin-x86_64"]' artifacts/latest-darwin-x86_64.json > /dev/null; then
|
||||
echo "Error: darwin-x86_64 platform data not found in manifest"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use jq to properly combine the manifests
|
||||
jq -n \
|
||||
--arg version "$VERSION" \
|
||||
--arg notes "See release notes at https://github.com/${REPO}/releases/tag/v${VERSION}" \
|
||||
--arg pub_date "$PUB_DATE" \
|
||||
--slurpfile aarch64 artifacts/latest-darwin-aarch64.json \
|
||||
--slurpfile x86_64 artifacts/latest-darwin-x86_64.json \
|
||||
'{
|
||||
version: $version,
|
||||
notes: $notes,
|
||||
pub_date: $pub_date,
|
||||
platforms: {
|
||||
"darwin-aarch64": $aarch64[0].platforms["darwin-aarch64"],
|
||||
"darwin-x86_64": $x86_64[0].platforms["darwin-x86_64"]
|
||||
}
|
||||
}' > artifacts/latest.json
|
||||
|
||||
echo "Generated combined latest.json:"
|
||||
cat artifacts/latest.json
|
||||
|
||||
- name: Upload combined manifest
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ needs.create-release.outputs.version }}
|
||||
files: artifacts/latest.json
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
build-desktop-electron-macos:
|
||||
needs: create-release
|
||||
runs-on: macos-26
|
||||
@@ -617,6 +241,31 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Stage signed Electron app for Tauri updater repackage
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
APP_DIR="packages/electron/dist/mac"
|
||||
[ -d "packages/electron/dist/mac-arm64" ] && APP_DIR="packages/electron/dist/mac-arm64"
|
||||
|
||||
APP_PATH=$(find "$APP_DIR" -maxdepth 2 -name "*.app" -print -quit)
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
echo "Error: .app not found under packages/electron/dist/mac*"
|
||||
ls -la packages/electron/dist/
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf electron-app-artifact
|
||||
mkdir -p electron-app-artifact
|
||||
cp -R "$APP_PATH" electron-app-artifact/OpenChamber.app
|
||||
|
||||
- name: Upload signed Electron app for Tauri updater repackage
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: electron-app-${{ matrix.arch }}
|
||||
path: electron-app-artifact/OpenChamber.app
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload per-arch latest-mac.yml for merge
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -624,6 +273,163 @@ jobs:
|
||||
path: packages/electron/dist/latest-mac.yml
|
||||
retention-days: 1
|
||||
|
||||
repackage-electron-as-tauri-update:
|
||||
needs: [create-release, build-desktop-electron-macos]
|
||||
runs-on: macos-26
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: arm64
|
||||
platform: darwin-aarch64
|
||||
- arch: x64
|
||||
platform: darwin-x86_64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download signed Electron app
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: electron-app-${{ matrix.arch }}
|
||||
path: staged
|
||||
|
||||
- name: Install minisign
|
||||
run: brew install minisign
|
||||
|
||||
- name: Tar and sign Electron app as Tauri update payload
|
||||
env:
|
||||
TAURI_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
VERSION: ${{ needs.create-release.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ ! -d staged/OpenChamber.app ]; then
|
||||
echo "Error: staged/OpenChamber.app not found"
|
||||
ls -la staged
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd staged
|
||||
TARBALL="OpenChamber.app.tar.gz"
|
||||
tar -czf "$TARBALL" OpenChamber.app
|
||||
|
||||
printf '%s\n' "$TAURI_KEY" > ../tauri-signing.key
|
||||
printf '%s\n' "$TAURI_KEY_PASSWORD" | minisign -S -s ../tauri-signing.key -m "$TARBALL" -W
|
||||
|
||||
mv "$TARBALL" "OpenChamber-${VERSION}-${{ matrix.platform }}.app.tar.gz"
|
||||
mv "${TARBALL}.minisig" "OpenChamber-${VERSION}-${{ matrix.platform }}.app.tar.gz.sig"
|
||||
|
||||
- name: Generate Tauri latest platform manifest
|
||||
env:
|
||||
VERSION: ${{ needs.create-release.outputs.version }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
SIG=$(cat staged/OpenChamber-${VERSION}-${{ matrix.platform }}.app.tar.gz.sig)
|
||||
TAR="OpenChamber-${VERSION}-${{ matrix.platform }}.app.tar.gz"
|
||||
jq -n \
|
||||
--arg version "$VERSION" \
|
||||
--arg notes "OpenChamber has moved to Electron. This update replaces the Tauri shell with the Electron build. Subsequent updates will be delivered via the Electron auto-updater." \
|
||||
--arg pub_date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||
--arg platform "${{ matrix.platform }}" \
|
||||
--arg signature "$SIG" \
|
||||
--arg url "https://github.com/${REPO}/releases/download/v${VERSION}/${TAR}" \
|
||||
'{ version: $version, notes: $notes, pub_date: $pub_date, platforms: { ($platform): { signature: $signature, url: $url } } }' \
|
||||
> staged/latest-${{ matrix.platform }}.json
|
||||
|
||||
- name: Upload tarball and signature to release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ needs.create-release.outputs.version }}
|
||||
files: |
|
||||
staged/*.app.tar.gz
|
||||
staged/*.app.tar.gz.sig
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload per-platform Tauri manifest for merge
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tauri-manifest-${{ matrix.platform }}
|
||||
path: staged/latest-${{ matrix.platform }}.json
|
||||
retention-days: 1
|
||||
|
||||
combine-manifests:
|
||||
needs: [create-release, repackage-electron-as-tauri-update]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download Tauri updater manifests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: tauri-manifest-*
|
||||
path: artifacts
|
||||
merge-multiple: true
|
||||
|
||||
- name: Combine manifests
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
VERSION="${{ needs.create-release.outputs.version }}"
|
||||
PUB_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
|
||||
if [ ! -f artifacts/latest-darwin-aarch64.json ]; then
|
||||
echo "Error: aarch64 manifest not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f artifacts/latest-darwin-x86_64.json ]; then
|
||||
echo "Error: x86_64 manifest not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! jq empty artifacts/latest-darwin-aarch64.json 2>/dev/null; then
|
||||
echo "Error: aarch64 manifest is not valid JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! jq empty artifacts/latest-darwin-x86_64.json 2>/dev/null; then
|
||||
echo "Error: x86_64 manifest is not valid JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! jq -e '.platforms["darwin-aarch64"]' artifacts/latest-darwin-aarch64.json > /dev/null; then
|
||||
echo "Error: darwin-aarch64 platform data not found in manifest"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! jq -e '.platforms["darwin-x86_64"]' artifacts/latest-darwin-x86_64.json > /dev/null; then
|
||||
echo "Error: darwin-x86_64 platform data not found in manifest"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--arg version "$VERSION" \
|
||||
--arg notes "OpenChamber has moved to Electron. This update replaces the Tauri shell with the Electron build. Subsequent updates will be delivered via the Electron auto-updater." \
|
||||
--arg pub_date "$PUB_DATE" \
|
||||
--slurpfile aarch64 artifacts/latest-darwin-aarch64.json \
|
||||
--slurpfile x86_64 artifacts/latest-darwin-x86_64.json \
|
||||
'{
|
||||
version: $version,
|
||||
notes: $notes,
|
||||
pub_date: $pub_date,
|
||||
platforms: {
|
||||
"darwin-aarch64": $aarch64[0].platforms["darwin-aarch64"],
|
||||
"darwin-x86_64": $x86_64[0].platforms["darwin-x86_64"]
|
||||
}
|
||||
}' > artifacts/latest.json
|
||||
|
||||
cat artifacts/latest.json
|
||||
|
||||
- name: Upload combined Tauri updater manifest
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ needs.create-release.outputs.version }}
|
||||
files: artifacts/latest.json
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
combine-electron-manifests:
|
||||
needs: [create-release, build-desktop-electron-macos]
|
||||
runs-on: ubuntu-latest
|
||||
@@ -657,7 +463,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
finalize-release:
|
||||
needs: [create-release, build-desktop-macos, build-desktop-electron-macos, publish-npm, combine-manifests, combine-electron-manifests]
|
||||
needs: [create-release, build-desktop-electron-macos, repackage-electron-as-tauri-update, publish-npm, combine-manifests, combine-electron-manifests]
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
|
||||
Reference in New Issue
Block a user