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
This commit is contained in:
Peter Steinberger 2025-06-19 04:26:41 +02:00
parent 89e2dfe356
commit 504d12634a
5 changed files with 102 additions and 43 deletions

View file

@ -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

View file

@ -5,39 +5,6 @@
<link>https://github.com/amantus-ai/vibetunnel</link>
<description>VibeTunnel pre-release and beta updates feed</description>
<language>en</language>
<item>
<title>VibeTunnel 1.0.0-beta.2</title>
<link>https://github.com/amantus-ai/vibetunnel/releases/download/v1.0.0-beta.2/VibeTunnel-1.0.0-beta.2.dmg</link>
<sparkle:version>104</sparkle:version>
<sparkle:shortVersionString>1.0.0-beta.2</sparkle:shortVersionString>
<description><![CDATA[
<h2>VibeTunnel 1.0.0-beta.2</h2><p><strong>Pre-release version</strong></p><div><h3>🎨 Improvements</h3>
<ul>
<li>Redesigned slick new web frontend</li>
<li>Faster terminal rendering in the web frontend</li>
<li>New Sessions spawn new Terminal windows. (This needs Applescript and Accessibility permissions)</li>
<li>Enhanced font handling with system font priority</li>
<li>Better async operations in PTY service for improved performance</li>
<li>Improved window activation when showing the welcome and settings windows</li>
<li>Preparations for Linux support</li>
</ul>
<h3>🐛 Bug Fixes</h3>
<ul>
<li>Fixed window front order when dock icon is hidden</li>
<li>Fixed PTY service enhancements with proper async operations</li>
<li>Fixed race condition in session creation that caused frontend to open previous session</li>
</ul>
<p><a href="https://github.com/amantus-ai/vibetunnel/blob/main/CHANGELOG.md#100-beta2-20250619">View full changelog</a></p></div>
]]></description>
<pubDate>Thu, 19 Jun 2025 02:14:36 +0200</pubDate>
<enclosure
url="https://github.com/amantus-ai/vibetunnel/releases/download/v1.0.0-beta.2/VibeTunnel-1.0.0-beta.2.dmg"
length="22202042"
type="application/octet-stream"
sparkle:edSignature="r8U74pQQyFwBlYOtO+6yd8vAM+JfFBwYDlkbFPLCyTmc9CANqenfP1SCi3MJROvAV/ajsqCRGDbtR3+3+hAkAg=="
/>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
</item>
<item>
<title>VibeTunnel 1.0-beta.1</title>
<link>https://github.com/amantus-ai/vibetunnel/releases/download/v1.0-beta.1/VibeTunnel-1.0-beta.1.dmg</link>

View file

@ -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..."

View file

@ -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

View file

@ -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}"