6.6 KiB
Archive Post-Action Setup (REQUIRED for App Store)
The Problem
App Store validation fails with:
App sandbox not enabled. The following executables must include the
"com.apple.security.app-sandbox" entitlement...
Sparkle.framework/Versions/B/Autoupdate
Sparkle.framework/Versions/B/Updater.app
...
Sparkle.framework must be physically removed from the app bundle for App Store distribution.
Why Build Phase Scripts Don't Work
Build Phase scripts run during compilation when files are code-signed and locked by macOS. Even with chmod and chflags, you get "Operation not permitted" due to System Integrity Protection.
The Solution: Archive Post-Action
Archive Post-Actions run after the archive completes, when files are no longer locked. This is the correct place to remove Sparkle.
Setup Instructions (2 minutes)
1. Open Scheme Editor
In Xcode: Product → Scheme → Edit Scheme... (or press ⌘<)
2. Select Archive
Click Archive in the left sidebar
3. Add Post-Action Script
- At the bottom, under "Post-actions", click the + button
- Select New Run Script Action
4. Configure the Action
Provide build settings from: Select Gaze from the dropdown (IMPORTANT!)
Shell: Leave as /bin/bash
Script: Copy and paste this entire script:
if [[ "${OTHER_SWIFT_FLAGS}" == *"APPSTORE"* ]]; then
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🗑️ Removing Sparkle from archived app..."
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
SPARKLE_PATH="${ARCHIVE_PATH}/Products/Applications/Gaze.app/Contents/Frameworks/Sparkle.framework"
if [ -d "$SPARKLE_PATH" ]; then
echo "📂 Found Sparkle at: $SPARKLE_PATH"
# Make writable and remove
chmod -R u+w "$SPARKLE_PATH" 2>/dev/null || true
chflags -R nouchg "$SPARKLE_PATH" 2>/dev/null || true
rm -rf "$SPARKLE_PATH"
if [ ! -d "$SPARKLE_PATH" ]; then
echo "✅ Sparkle framework removed successfully!"
else
echo "❌ ERROR: Could not remove Sparkle framework"
echo " This will cause App Store validation to fail"
exit 1
fi
else
echo "ℹ️ Sparkle framework not found (already removed)"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Archive ready for App Store distribution"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
else
echo "✓ Self-distribution archive - Sparkle retained"
fi
5. Save
Click Close to save the scheme changes
Verification Steps
Test the Archive
-
Switch to App Store mode:
./switch_to appstore -
Archive in Xcode:
- Product → Archive (or ⌘⇧B then Archive)
- Watch the build log - you should see the post-action output
-
Check the archive contents:
- Window → Organizer
- Select your latest Gaze archive
- Right-click → Show in Finder
- Right-click the
.xcarchivefile → Show Package Contents - Navigate to:
Products/Applications/Gaze.app/Contents/Frameworks/ - Verify: Only
Lottie.frameworkshould be present ✅
-
Distribute to App Store:
- In Organizer, click Distribute App
- Choose App Store Connect
- Complete the distribution wizard
- Validation should now pass! ✅
What You Should See
In the Build Log (after archiving):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🗑️ Removing Sparkle from archived app...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📂 Found Sparkle at: [path]
✅ Sparkle framework removed successfully!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Archive ready for App Store distribution
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
In the Frameworks folder:
Gaze.app/Contents/Frameworks/
└── Lottie.framework/
No Sparkle.framework! ✅
Troubleshooting
"I don't see the post-action output"
- Make sure you selected Gaze in "Provide build settings from"
- Check View → Navigators → Show Report Navigator (⌘9)
- Select the Archive action to see full logs
"Sparkle is still in the archive"
- Verify
./switch_to statusshows "App Store" for all items - Check the script exactly matches (copy/paste the entire script)
- Try cleaning: Product → Clean Build Folder (⌘⇧K)
"Script says 'Sparkle framework not found'"
- This means Sparkle wasn't embedded (good!)
- Continue with distribution - validation should pass
"Archive Post-Action section doesn't exist"
- Make sure you're editing the Archive section, not Run or Test
- Click the triangle next to "Archive" to expand it
Optional: Remove Old Build Phase Script
If you previously added a Build Phase script (which doesn't work due to file locking), you can remove it:
- Gaze target → Build Phases
- Find "Remove Sparkle for App Store" or "Run Script"
- Click the X to delete it
The Archive Post-Action is the correct and only solution needed.
Why This Is Required
Even though:
- ✅ Sparkle code is disabled via
#if !APPSTORE - ✅ Info.plist has no Sparkle keys
- ✅ Entitlements have no Sparkle exceptions
App Store validation still checks for the physical presence of unsandboxed executables in frameworks. Sparkle contains XPC services that aren't App Store compatible, so the entire framework must be removed.
For Self-Distribution
When building for self-distribution (./switch_to self), the script detects the absence of the APPSTORE flag and leaves Sparkle intact. You don't need to change anything!
./switch_to self
./self_distribute # Sparkle is retained and works normally
Summary
✅ One-time setup: Add Archive Post-Action script
✅ Works automatically: Removes Sparkle only for App Store builds
✅ Zero maintenance: Once configured, runs automatically forever
This is the correct and only working solution for removing Sparkle from App Store builds!