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

6.6 KiB
Raw Blame History

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

  1. Switch to App Store mode:

    ./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!

./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!