Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 37 additions & 18 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
name: Build macOS Release

on:
push:
tags:
- "v*"
workflow_dispatch:

permissions:
contents: write

Expand All @@ -18,14 +16,11 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust toolchain (both macOS targets)
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-apple-darwin,x86_64-apple-darwin

- name: Install cargo-bundle
run: cargo install cargo-bundle

- name: Cache cargo registry
uses: actions/cache@v4
with:
Expand All @@ -44,24 +39,45 @@ jobs:
path: target
key: ${{ runner.os }}-universal-cargo-build-${{ hashFiles('**/Cargo.lock') }}

- name: Build release bundles (aarch64 + x86_64)
run: |
cargo bundle --release --target aarch64-apple-darwin
cargo bundle --release --target x86_64-apple-darwin
- name: Build macOS app (universal)
run: bash scripts/build-macos.sh

- name: Sign macOS app
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
MACOS_CERTIFICATE_NAME: ${{ secrets.MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.MACOS_CI_KEYCHAIN_PWD }}
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.MACOS_NOTARIZATION_APPLE_ID }}
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}
MACOS_NOTARIZATION_PWD: ${{ secrets.MACOS_NOTARIZATION_PWD }}
run: bash scripts/sign-macos.sh

- name: Package DMG
run: bash scripts/package-macos.sh

# Homebrew-style artifact from the built .app
- name: Create artifacts directory
run: mkdir -p artifacts

- name: Package app bundles
- name: Zip universal .app for Homebrew
# APP_BUNDLE_PATH is set by scripts/build-macos.sh
run: |
cd target/aarch64-apple-darwin/release/bundle/osx
zip -r ../../../../../artifacts/rustcast-aarch64-apple-darwin.app.zip *.app
if [ -z "$APP_BUNDLE_PATH" ]; then
echo "APP_BUNDLE_PATH not set by build-macos.sh" >&2
exit 1
fi
APP_NAME=$(basename "$APP_BUNDLE_PATH")
zip -r "artifacts/${APP_NAME%.app}-universal-macos.app.zip" "$APP_BUNDLE_PATH"

cd - >/dev/null
cd target/x86_64-apple-darwin/release/bundle/osx
zip -r ../../../../../artifacts/rustcast-x86_64-apple-darwin.app.zip *.app
- name: Upload DMG artifact
uses: actions/upload-artifact@v4
with:
name: rustcast-macos-dmg
path: ${{ env.DMG_PATH }}
retention-days: 7

- name: Upload artifacts
- name: Upload .app zip artifact (Homebrew)
uses: actions/upload-artifact@v4
with:
name: macos-bundles
Expand All @@ -81,7 +97,10 @@ jobs:
- name: Create release
uses: softprops/action-gh-release@v1
with:
files: artifacts/**/*.zip
# Include both DMG and .app zip(s)
files: |
artifacts/**/*.dmg
artifacts/**/*.zip
draft: false
prerelease: false
env:
Expand Down
18 changes: 0 additions & 18 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,3 @@ rayon = "1.11.0"
serde = { version = "1.0.228", features = ["derive"] }
tokio = { version = "1.48.0", features = ["full"] }
toml = "0.9.8"

[package.metadata.bundle]
name = "RustCast"
identifier = "com.umangsurana.rustcast"
icon = ["bundling/icon.icns"]
version = "1.0.0"
resources = []
copyright = "Copyright Umang Surana (c) 2025"
category = "Developer Tool"
short_description = "An open source alternative to Raycast, and in rust"
osx_minimum_system_version = "10.15"

[package.metadata.bundle.osx]
info_plist_path = "bundling/Info.plist"

[package.metadata.bundle.osx.info]
LSUIElement = true
NSHighResolutionCapable = true
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,29 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>

<key>CFBundleExecutable</key>
<string>rustcast</string>

<key>CFBundleIdentifier</key>
<string>com.umangsurana.rustcast</string>

<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>

<key>CFBundleName</key>
<string>RustCast</string>

<key>CFBundlePackageType</key>
<string>APPL</string>

<key>CFBundleShortVersionString</key>
<string>1.0</string>

<key>CFBundleVersion</key>
<string>1</string>

<key>LSUIElement</key>
<true/>

<key>NSHighResolutionCapable</key>
<true/>

<key>NSHumanReadableCopyright</key>
<string>Copyright © 2025 Umang Surana. All rights reserved.</string>

<key>NSInputMonitoringUsageDescription</key>
<string>RustCast needs to monitor keyboard input to detect global shortcuts and control casting.</string>
<key>CFBundleIconFile</key>
<string>icon</string>
</dict>
</plist>
File renamed without changes.
14 changes: 0 additions & 14 deletions bundling/entitlements.plist

This file was deleted.

52 changes: 52 additions & 0 deletions scripts/build-macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env -S bash -e

TARGET="rustcast" # your Cargo binary name
ASSETS_DIR="assets"
RELEASE_DIR="target/release"
APP_NAME="Rustcast.app"
APP_TEMPLATE="$ASSETS_DIR/macos/$APP_NAME"
APP_TEMPLATE_PLIST="$APP_TEMPLATE/Contents/Info.plist"
APP_DIR="$RELEASE_DIR/macos"
APP_BINARY="$RELEASE_DIR/$TARGET"
APP_BINARY_DIR="$APP_DIR/$APP_NAME/Contents/MacOS"
APP_EXTRAS_DIR="$APP_DIR/$APP_NAME/Contents/Resources"
DMG_NAME="rustcast.dmg"
DMG_DIR="$RELEASE_DIR/macos"

VERSION="{$APP_VERSION}"
BUILD=$(git describe --always --dirty --exclude='*')

# Update version/build in Info.plist
cp "$APP_TEMPLATE_PLIST" "$APP_TEMPLATE_PLIST.tmp"
sed -i '' -e "s/{{ VERSION }}/$VERSION/g" "$APP_TEMPLATE_PLIST.tmp"
sed -i '' -e "s/{{ BUILD }}/$BUILD/g" "$APP_TEMPLATE_PLIST.tmp"
mv "$APP_TEMPLATE_PLIST.tmp" "$APP_TEMPLATE_PLIST"

export MACOSX_DEPLOYMENT_TARGET="11.0"

# Ensure both targets exist
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin

# Build both archs
cargo build --release --locked --target=x86_64-apple-darwin
cargo build --release --locked --target=aarch64-apple-darwin

# Create universal binary
lipo \
"target/x86_64-apple-darwin/release/$TARGET" \
"target/aarch64-apple-darwin/release/$TARGET" \
-create -output "$APP_BINARY"

# Build app bundle
rm -rf "$APP_DIR/$APP_NAME"
mkdir -p "$APP_BINARY_DIR"
mkdir -p "$APP_EXTRAS_DIR"
cp -fRp "$APP_TEMPLATE" "$APP_DIR"
cp -fp "$APP_BINARY" "$APP_BINARY_DIR"
touch -r "$APP_BINARY" "$APP_DIR/$APP_NAME"

echo "Created '$APP_NAME' in '$APP_DIR'"
echo "APP_BUNDLE_PATH=$APP_DIR/$APP_NAME" >> "$GITHUB_ENV"
echo "DMG_NAME=$DMG_NAME" >> "$GITHUB_ENV"
echo "DMG_DIR=$DMG_DIR" >> "$GITHUB_ENV"
27 changes: 27 additions & 0 deletions scripts/package-macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env -S bash -e

APP_BUNDLE_PATH="${APP_BUNDLE_PATH:?APP_BUNDLE_PATH not set}"
DMG_NAME="${DMG_NAME:?DMG_NAME not set}"
DMG_DIR="${DMG_DIR:?DMG_DIR not set}"

VOLUME_NAME="Rustcast" # visible volume name
STAGING_DIR="$DMG_DIR/dmg-staging"

rm -rf "$STAGING_DIR"
mkdir -p "$STAGING_DIR"

# Copy app and Applications symlink into staging dir
cp -R "$APP_BUNDLE_PATH" "$STAGING_DIR/"
ln -s /Applications "$STAGING_DIR/Applications"

# Remove old DMG
rm -f "$DMG_DIR/$DMG_NAME"

# Create DMG
hdiutil create -volname "$VOLUME_NAME" \
-srcfolder "$STAGING_DIR" \
-ov -format UDZO \
"$DMG_DIR/$DMG_NAME"

echo "Created DMG at $DMG_DIR/$DMG_NAME"
echo "DMG_PATH=$DMG_DIR/$DMG_NAME" >> "$GITHUB_ENV"
37 changes: 37 additions & 0 deletions scripts/sign-macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env -S bash -e

APP_BUNDLE_PATH="${APP_BUNDLE_PATH:?APP_BUNDLE_PATH not set}"

# 1. Create a temporary keychain and import certificate
KEYCHAIN=build.keychain-db

if security list-keychains | grep -q "$KEYCHAIN"; then
echo "Keychain $KEYCHAIN already exists, using existing keychain."
else
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" "$KEYCHAIN"
fi

security default-keychain -s "$KEYCHAIN"
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" "$KEYCHAIN"
security set-keychain-settings "$KEYCHAIN"
security default-keychain -s "$KEYCHAIN"
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" "$KEYCHAIN"
security set-keychain-settings "$KEYCHAIN"

# Import certificate (Base64 encoded .p12 in secret MACOS_CERTIFICATE)
echo "$MACOS_CERTIFICATE" | base64 --decode > certificate.p12
security import certificate.p12 \
-k "$KEYCHAIN" \
-P "$MACOS_CERTIFICATE_PWD" \
-T /usr/bin/codesign

security set-key-partition-list -S apple-tool:,apple:,codesign: \
-s -k "$MACOS_CI_KEYCHAIN_PWD" "$KEYCHAIN"

# 2. Sign app bundle
codesign --deep --force --options runtime --timestamp \
--sign "$MACOS_CERTIFICATE_NAME" \
"$APP_BUNDLE_PATH"

codesign --verify --deep --strict --verbose=2 "$APP_BUNDLE_PATH"
echo "Signed app at $APP_BUNDLE_PATH"