From 504d12634a5403fecd7c7d27ea154f01997c3a49 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 19 Jun 2025 04:26:41 +0200 Subject: [PATCH] Fix Sparkle signing issues and improve release verification - Add --timestamp flag to all code signing operations - Fix Sparkle XPC services signing to match VibeMeter approach - Add comprehensive Sparkle component verification after signing - Add post-DMG creation verification to ensure app is properly notarized - Increment build number to 105 for clean beta 2 release --- VibeTunnel/version.xcconfig | 2 +- appcast-prerelease.xml | 33 -------------- scripts/codesign-app.sh | 8 ++-- scripts/notarize-app.sh | 11 +++-- scripts/release.sh | 91 +++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 43 deletions(-) diff --git a/VibeTunnel/version.xcconfig b/VibeTunnel/version.xcconfig index 5a15e8c1..52bf9fb8 100644 --- a/VibeTunnel/version.xcconfig +++ b/VibeTunnel/version.xcconfig @@ -2,7 +2,7 @@ // This file contains the version and build number for the app MARKETING_VERSION = 1.0.0-beta.2 -CURRENT_PROJECT_VERSION = 104 +CURRENT_PROJECT_VERSION = 105 // Domain and GitHub configuration APP_DOMAIN = vibetunnel.sh diff --git a/appcast-prerelease.xml b/appcast-prerelease.xml index 91fc1876..8d95428a 100644 --- a/appcast-prerelease.xml +++ b/appcast-prerelease.xml @@ -5,39 +5,6 @@ https://github.com/amantus-ai/vibetunnel VibeTunnel pre-release and beta updates feed en - - VibeTunnel 1.0.0-beta.2 - https://github.com/amantus-ai/vibetunnel/releases/download/v1.0.0-beta.2/VibeTunnel-1.0.0-beta.2.dmg - 104 - 1.0.0-beta.2 - VibeTunnel 1.0.0-beta.2

Pre-release version

🎨 Improvements

-
    -
  • Redesigned slick new web frontend
  • -
  • Faster terminal rendering in the web frontend
  • -
  • New Sessions spawn new Terminal windows. (This needs Applescript and Accessibility permissions)
  • -
  • Enhanced font handling with system font priority
  • -
  • Better async operations in PTY service for improved performance
  • -
  • Improved window activation when showing the welcome and settings windows
  • -
  • Preparations for Linux support
  • -
-

🐛 Bug Fixes

-
    -
  • Fixed window front order when dock icon is hidden
  • -
  • Fixed PTY service enhancements with proper async operations
  • -
  • Fixed race condition in session creation that caused frontend to open previous session
  • -
-

View full changelog

- ]]>
- Thu, 19 Jun 2025 02:14:36 +0200 - - 15.0 -
VibeTunnel 1.0-beta.1 https://github.com/amantus-ai/vibetunnel/releases/download/v1.0-beta.1/VibeTunnel-1.0-beta.1.dmg diff --git a/scripts/codesign-app.sh b/scripts/codesign-app.sh index cb6f61a7..a89e08a1 100755 --- a/scripts/codesign-app.sh +++ b/scripts/codesign-app.sh @@ -89,26 +89,26 @@ if [ -d "$APP_BUNDLE/Contents/Frameworks" ]; then log "Signing embedded frameworks..." find "$APP_BUNDLE/Contents/Frameworks" \( -type d -name "*.framework" -o -type f -name "*.dylib" \) 2>/dev/null | while read -r framework; do log "Signing framework: $framework" - codesign --force --options runtime --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$framework" || log "Warning: Failed to sign $framework" + codesign --force --options runtime --timestamp --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$framework" || log "Warning: Failed to sign $framework" done fi # Sign embedded binaries (like tty-fwd) if [ -f "$APP_BUNDLE/Contents/Resources/tty-fwd" ]; then log "Signing tty-fwd binary..." - codesign --force --options runtime --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/Resources/tty-fwd" || log "Warning: Failed to sign tty-fwd" + codesign --force --options runtime --timestamp --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/Resources/tty-fwd" || log "Warning: Failed to sign tty-fwd" fi # Sign the main executable log "Signing main executable..." -codesign --force --options runtime --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/MacOS/VibeTunnel" || true +codesign --force --options runtime --timestamp --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/MacOS/VibeTunnel" || true # Sign the app bundle WITHOUT deep signing (per Sparkle documentation) # "Due to different code signing requirements, please do not add --deep to # OTHER_CODE_SIGN_FLAGS or from custom build scripts when signing your application. # This is a common source of Sandboxing errors." log "Signing complete app bundle (without --deep per Sparkle requirements)..." -codesign --force --options runtime --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE" +codesign --force --options runtime --timestamp --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE" # Verify the signature log "Verifying code signature..." diff --git a/scripts/notarize-app.sh b/scripts/notarize-app.sh index 108ed8d2..b8345794 100755 --- a/scripts/notarize-app.sh +++ b/scripts/notarize-app.sh @@ -188,28 +188,29 @@ if [ -n "${KEYCHAIN_NAME:-}" ]; then fi # Sign XPC services (directories, not files) +# IMPORTANT: Do NOT use --deep flag, sign each component individually if [ -d "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" ]; then - codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" + codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" log "Signed Installer.xpc" fi if [ -d "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" ]; then # For Sparkle versions >= 2.6, preserve entitlements - codesign -f -s "$SIGN_IDENTITY" -o runtime --preserve-metadata=entitlements $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" + codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp --preserve-metadata=entitlements $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" log "Signed Downloader.xpc" fi # Sign other Sparkle components if [ -f "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" ]; then - codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" + codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" log "Signed Autoupdate" fi if [ -d "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" ]; then - codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" + codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" log "Signed Updater.app" fi # Finally sign the framework itself -codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework" +codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework" log "Signed Sparkle.framework" # 2. Sparkle framework is already signed above per documentation diff --git a/scripts/release.sh b/scripts/release.sh index 1b66224b..00fc5fe5 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -331,6 +331,56 @@ echo "" echo -e "${BLUE}📋 Step 5/8: Signing and notarizing...${NC}" "$SCRIPT_DIR/sign-and-notarize.sh" --sign-and-notarize +# Verify Sparkle component signing +echo "" +echo -e "${BLUE}🔍 Verifying Sparkle component signatures...${NC}" +SPARKLE_OK=true + +# Check each Sparkle component for proper signing with timestamps +if [ -d "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" ]; then + if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" 2>&1 | grep -q "timestamp"; then + echo -e "${RED}❌ Installer.xpc missing timestamp signature${NC}" + SPARKLE_OK=false + else + echo "✅ Installer.xpc properly signed with timestamp" + fi +fi + +if [ -d "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" ]; then + if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" 2>&1 | grep -q "timestamp"; then + echo -e "${RED}❌ Downloader.xpc missing timestamp signature${NC}" + SPARKLE_OK=false + else + echo "✅ Downloader.xpc properly signed with timestamp" + fi +fi + +if [ -f "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" ]; then + if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" 2>&1 | grep -q "timestamp"; then + echo -e "${RED}❌ Autoupdate missing timestamp signature${NC}" + SPARKLE_OK=false + else + echo "✅ Autoupdate properly signed with timestamp" + fi +fi + +if [ -d "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" ]; then + if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" 2>&1 | grep -q "timestamp"; then + echo -e "${RED}❌ Updater.app missing timestamp signature${NC}" + SPARKLE_OK=false + else + echo "✅ Updater.app properly signed with timestamp" + fi +fi + +if [ "$SPARKLE_OK" = false ]; then + echo -e "${RED}❌ Sparkle component signing verification failed!${NC}" + echo "This will cause 'update isn't properly signed' errors for users." + exit 1 +fi + +echo -e "${GREEN}✅ All Sparkle components properly signed${NC}" + # Step 5: Create DMG echo "" echo -e "${BLUE}📋 Step 6/8: Creating DMG...${NC}" @@ -381,6 +431,47 @@ fi echo -e "${GREEN}✅ DMG notarization complete and verified${NC}" +# Verify app inside DMG is properly signed +echo "" +echo -e "${BLUE}🔍 Verifying app inside DMG...${NC}" + +# Mount the DMG temporarily +DMG_MOUNT=$(mktemp -d) +if hdiutil attach "$DMG_PATH" -mountpoint "$DMG_MOUNT" -nobrowse -quiet; then + DMG_APP="$DMG_MOUNT/VibeTunnel.app" + + # Check if app is notarized + if spctl -a -t exec -vv "$DMG_APP" 2>&1 | grep -q "source=Notarized Developer ID"; then + echo "✅ App in DMG is properly notarized" + else + echo -e "${RED}❌ App in DMG is not properly notarized!${NC}" + hdiutil detach "$DMG_MOUNT" -quiet + exit 1 + fi + + # Check if notarization ticket is stapled + if xcrun stapler validate "$DMG_APP" 2>&1 | grep -q "The validate action worked"; then + echo "✅ App in DMG has stapled notarization ticket" + else + echo -e "${RED}❌ App in DMG missing stapled notarization ticket!${NC}" + hdiutil detach "$DMG_MOUNT" -quiet + exit 1 + fi + + # Check Sparkle components in DMG + if codesign -dv "$DMG_APP/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" 2>&1 | grep -q "timestamp"; then + echo "✅ Sparkle components in DMG properly signed" + else + echo -e "${YELLOW}⚠️ Warning: Sparkle components in DMG may not have timestamp signatures${NC}" + fi + + # Unmount DMG + hdiutil detach "$DMG_MOUNT" -quiet + echo -e "${GREEN}✅ App inside DMG verification complete${NC}" +else + echo -e "${YELLOW}⚠️ Warning: Could not mount DMG for verification${NC}" +fi + # Step 6: Create GitHub release echo "" echo -e "${BLUE}📋 Step 7/9: Creating GitHub release...${NC}"