Skip to content

Build macOS

Build macOS #172

Workflow file for this run

name: Build macOS
on:
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-apple-darwin,x86_64-apple-darwin
- name: Build ARM64 (Apple Silicon)
run: cargo build --release --target aarch64-apple-darwin --features icon
- name: Build x64 (Intel)
run: cargo build --release --target x86_64-apple-darwin --features icon
- name: Create macOS Icon
run: |
# Create iconset directory
mkdir -p AppIcon.iconset
# Convert PNG to various sizes required for macOS icon
sips -z 16 16 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_16x16.png"
sips -z 32 32 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_16x16@2x.png"
sips -z 32 32 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_32x32.png"
sips -z 64 64 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_32x32@2x.png"
sips -z 128 128 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_128x128.png"
sips -z 256 256 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_128x128@2x.png"
sips -z 256 256 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_256x256.png"
sips -z 512 512 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_256x256@2x.png"
sips -z 512 512 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_512x512.png"
sips -z 1024 1024 "assets/Icons/icon.png" --out "AppIcon.iconset/icon_512x512@2x.png"
# Convert iconset to icns
iconutil -c icns AppIcon.iconset -o AppIcon.icns
- name: Create launcher script
run: |
cat > launch-installer.command << 'EOF'
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
APP_PATH="$SCRIPT_DIR/SpruceOSInstaller.app"
echo "SpruceOS Installer Launcher"
echo "============================"
echo "Removing quarantine attribute..."
xattr -d com.apple.quarantine "$APP_PATH" 2>/dev/null
echo "Launching SpruceOS Installer..."
open "$APP_PATH"
EOF
chmod +x launch-installer.command
- name: Create Universal App Bundle
run: |
# Create universal binary using lipo
lipo -create -output spruceos-installer-universal \
target/aarch64-apple-darwin/release/spruceos-installer \
target/x86_64-apple-darwin/release/spruceos-installer
# Verify the universal binary contains both architectures
echo "Universal binary architectures:"
lipo -info spruceos-installer-universal
# Create .app bundle structure (no spaces in name)
mkdir -p "SpruceOSInstaller.app/Contents/MacOS"
mkdir -p "SpruceOSInstaller.app/Contents/Resources"
# Copy universal binary
cp spruceos-installer-universal "SpruceOSInstaller.app/Contents/MacOS/spruceos-installer"
chmod +x "SpruceOSInstaller.app/Contents/MacOS/spruceos-installer"
# Copy Info.plist and icon
cp "assets/Mac/Info.plist" "SpruceOSInstaller.app/Contents/"
cp "AppIcon.icns" "SpruceOSInstaller.app/Contents/Resources/"
# Copy 7zz binary to Resources so it inherits app's unquarantine status
cp "assets/Mac/7zz" "SpruceOSInstaller.app/Contents/Resources/7zz"
chmod +x "SpruceOSInstaller.app/Contents/Resources/7zz"
# Remove quarantine attribute to prevent macOS Gatekeeper issues
xattr -cr "SpruceOSInstaller.app"
# Create zip for distribution with both app and launcher
zip -r "SpruceOS-Installer-macOS-Universal.zip" "SpruceOSInstaller.app" "launch-installer.command"
- name: Upload Universal artifact
uses: actions/upload-artifact@v4
with:
name: SpruceOS-Installer-macOS-Universal
path: SpruceOS-Installer-macOS-Universal.zip
- name: Upload to Beta Release
uses: softprops/action-gh-release@v1
with:
tag_name: beta-${{ github.ref_name }}
files: SpruceOS-Installer-macOS-Universal.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}