Files
Gaze/ARCHIVE_POST_ACTION_SETUP.md
2026-01-13 12:59:36 -05:00

202 lines
6.6 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```bash
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
1. **Switch to App Store mode:**
```bash
./switch_to appstore
```
2. **Archive in Xcode:**
- **Product → Archive** (or **⌘⇧B** then Archive)
- Watch the build log - you should see the post-action output
3. **Check the archive contents:**
- **Window → Organizer**
- Select your latest Gaze archive
- Right-click → **Show in Finder**
- Right-click the `.xcarchive` file → **Show Package Contents**
- Navigate to: `Products/Applications/Gaze.app/Contents/Frameworks/`
- **Verify:** Only `Lottie.framework` should be present ✅
4. **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 status` shows "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:
1. Gaze target → Build Phases
2. Find "Remove Sparkle for App Store" or "Run Script"
3. 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!
```bash
./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!