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
31 changes: 24 additions & 7 deletions scripts/build-mas.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,21 @@ if [ ! -f "$MAS_PROFILE" ]; then
exit 1
fi

APP="src-tauri/target/release/bundle/macos/Markup.app"
# Universal (arm64 + x86_64). MAS requires Intel support unless the deployment
# target is macOS 12+ (ours is 10.15), so `tauri --target universal-apple-darwin`
# lipos both arches into one bundle; output lands under target/universal-apple-darwin/.
APP="src-tauri/target/universal-apple-darwin/release/bundle/macos/Markup.app"
ENTITLEMENTS="src-tauri/Entitlements.mas.plist"
PKG="src-tauri/target/release/bundle/macos/Markup.pkg"
PKG="src-tauri/target/universal-apple-darwin/release/bundle/macos/Markup.pkg"

echo "==> 1/5 Building sandboxed app (VITE_MARKUP_MAS=1, MAS entitlements)"
echo "==> 1/5 Building sandboxed universal app (VITE_MARKUP_MAS=1, MAS entitlements)"
# Both arches must be present for the universal build — no-op if already added;
# works locally and on CI (rustup manages the toolchain in both).
rustup target add aarch64-apple-darwin x86_64-apple-darwin >/dev/null 2>&1 || true
# --bundles app: we package the .pkg ourselves after signing.
# --config layers the MAS entitlements over tauri.conf.json.
VITE_MARKUP_MAS=1 pnpm tauri build \
--target universal-apple-darwin \
--bundles app \
--config src-tauri/tauri.mas.conf.json

Expand All @@ -60,12 +67,22 @@ VITE_MARKUP_MAS=1 pnpm tauri build \
echo "==> 2/5 Embedding provisioning profile"
cp "$MAS_PROFILE" "$APP/Contents/embedded.provisionprofile"

# Strip extended attributes before signing: a browser-downloaded provisioning
# profile carries com.apple.quarantine, and the App Store rejects any file with
# it (error 91109). Clearing here keeps the bundle clean for the signature/pkg.
xattr -cr "$APP"

echo "==> 3/5 Signing nested code, then the app (Apple Distribution + sandbox entitlements)"
# Sign inner binaries/frameworks first (inside-out), then the bundle.
find "$APP/Contents/Frameworks" -type f \( -name "*.dylib" -o -perm -111 \) 2>/dev/null | while read -r f; do
codesign --force --timestamp --options runtime \
--sign "$MAS_APP_IDENTITY" "$f" || true
done
# Tauri's bundle has no Contents/Frameworks when tauri.conf.json sets
# "frameworks": [] — guard the find so a missing dir doesn't trip
# `set -o pipefail` (find exits non-zero on a nonexistent path).
if [ -d "$APP/Contents/Frameworks" ]; then
find "$APP/Contents/Frameworks" -type f \( -name "*.dylib" -o -perm -111 \) 2>/dev/null | while read -r f; do
codesign --force --timestamp --options runtime \
--sign "$MAS_APP_IDENTITY" "$f" || true
done
fi
codesign --force --timestamp \
--entitlements "$ENTITLEMENTS" \
--sign "$MAS_APP_IDENTITY" \
Expand Down
6 changes: 6 additions & 0 deletions src-tauri/Entitlements.mas.plist
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
the hardened-runtime set for the direct/notarized DMG). MAS apps run
under App Sandbox instead of the hardened-runtime exceptions.

- application-identifier / team-identifier: required for App Store signing;
the .pkg upload is rejected without them. Must match the bundle id + team.
- app-sandbox: mandatory for MAS.
- files.user-selected.read-write: lets the user grant a vault folder
via the system open panel.
Expand All @@ -22,6 +24,10 @@
-->
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>9LH9NBX7P4.com.appkon.markup</string>
<key>com.apple.developer.team-identifier</key>
<string>9LH9NBX7P4</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
Expand Down
Loading