diff --git a/Meetingnotes.xcodeproj/project.pbxproj b/Meetingnotes.xcodeproj/project.pbxproj index 4741355..a173e3f 100644 --- a/Meetingnotes.xcodeproj/project.pbxproj +++ b/Meetingnotes.xcodeproj/project.pbxproj @@ -280,7 +280,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 8; + CURRENT_PROJECT_VERSION = 9; DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\""; DEVELOPMENT_TEAM = ML6HYR5LUR; ENABLE_HARDENED_RUNTIME = YES; @@ -294,7 +294,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0.3; + MARKETING_VERSION = 1.0.4; ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = owen.meetingnotes; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -315,7 +315,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 8; + CURRENT_PROJECT_VERSION = 9; DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\""; DEVELOPMENT_TEAM = ML6HYR5LUR; ENABLE_HARDENED_RUNTIME = YES; @@ -329,7 +329,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0.3; + MARKETING_VERSION = 1.0.4; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = owen.meetingnotes; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/appcast.xml b/appcast.xml index 4f2cfc0..9f452c1 100644 --- a/appcast.xml +++ b/appcast.xml @@ -2,16 +2,29 @@ Meetingnotes + + 1.0.4 + Wed, 16 Jul 2025 09:02:52 -0400 + 9 + 1.0.4 + 14.0 + + + + + + + 1.0.3 Tue, 15 Jul 2025 13:35:21 -0400 8 1.0.3 14.0 - + - - + + @@ -20,26 +33,10 @@ 7 1.0.2 14.0 - + - + - - 1.0.1 - Mon, 14 Jul 2025 18:59:45 -0400 - 6 - 1.0.1 - 14.0 - - - - 1.0.0 - Mon, 14 Jul 2025 16:22:59 -0400 - 5 - 1.0.0 - 14.0 - - \ No newline at end of file diff --git a/scripts/build_release.sh b/scripts/build_release.sh index 0d027cc..d9781db 100755 --- a/scripts/build_release.sh +++ b/scripts/build_release.sh @@ -275,13 +275,16 @@ rm -rf "$APPCAST_WORK" mkdir -p "$APPCAST_WORK" echo "🔗 Staging ZIP archives for appcast generation..." -echo "[DEBUG] Staging ZIP and delta archives with directory structure..." -rsync -avm --include='*/' --include='*.zip' --include='*.delta' --exclude='*' "$RELEASES_DIR/" "$APPCAST_WORK/" +echo "[DEBUG] Staging all ZIP archives from all versions..." +find "$RELEASES_DIR" -maxdepth 2 -type f -name "*.zip" -exec cp {} "$APPCAST_WORK"/ \; + +echo "[DEBUG] Staging all existing delta files to preserve them..." +find "$RELEASES_DIR" -maxdepth 2 -type f -name "*.delta" -exec cp {} "$APPCAST_WORK"/ \; + echo "[DEBUG] Appcast workdir contents:" ls -la "$APPCAST_WORK" echo "[DEBUG] Running generate_appcast..." /opt/homebrew/Caskroom/sparkle/2.7.1/bin/generate_appcast "$APPCAST_WORK" \ - --download-url-prefix "https://github.com/owengretzinger/meetingnotes/releases/download/" \ -o "appcast.xml" 2>&1 | tee "$BUILD_DIR/generate_appcast.log" if grep -q "Could not unarchive" "$BUILD_DIR/generate_appcast.log"; then @@ -290,9 +293,60 @@ if grep -q "Could not unarchive" "$BUILD_DIR/generate_appcast.log"; then exit 3 fi -echo "🚚 Moving generated delta files into version folder..." -if compgen -G "$APPCAST_WORK/*.delta" > /dev/null; then - mv "$APPCAST_WORK"/*.delta "$VERSION_DIR/" +echo "🔧 Fixing download URLs in appcast.xml..." +# Fix ZIP/DMG URLs to include version folder +# Transform "https://github.com/.../download/Meetingnotes-1.0.3.zip" to "https://github.com/.../download/v1.0.3/Meetingnotes-1.0.3.zip" +sed -i '' -E 's|url="([^"]*/download/)(Meetingnotes-([0-9]+\.[0-9]+\.[0-9]+)\.(zip\|dmg))"|url="\1v\3/\2"|g' appcast.xml + +# Fix delta URLs - they need to be in the version folder of the release they belong to +# We'll need to parse the appcast to figure out which version each delta belongs to +python3 << 'EOF' +import xml.etree.ElementTree as ET +import re + +# Parse the appcast +tree = ET.parse('appcast.xml') +root = tree.getroot() + +# Register namespace to preserve it in output +ET.register_namespace('sparkle', 'http://www.andymatuschak.org/xml-namespaces/sparkle') + +# Process each item +for item in root.findall('.//item'): + # Get the version for this item + version_elem = item.find('.//{http://www.andymatuschak.org/xml-namespaces/sparkle}shortVersionString') + if version_elem is not None: + version = version_elem.text + + # Fix all delta URLs within this item's sparkle:deltas section + deltas_elem = item.find('.//{http://www.andymatuschak.org/xml-namespaces/sparkle}deltas') + if deltas_elem is not None: + for enclosure in deltas_elem.findall('.//enclosure[@url]'): + url = enclosure.get('url') + if url and '.delta' in url: + # Extract just the filename + filename = url.split('/')[-1] + # Set the correct URL with version folder + new_url = f'https://github.com/owengretzinger/meetingnotes/releases/download/v{version}/{filename}' + enclosure.set('url', new_url) + +# Write the fixed appcast +tree.write('appcast.xml', encoding='UTF-8', xml_declaration=True) + +# Add back the standalone attribute +with open('appcast.xml', 'r') as f: + content = f.read() +content = content.replace('', '') +with open('appcast.xml', 'w') as f: + f.write(content) +EOF + +echo "🚚 Moving only NEW delta files into version folder..." +# Get the build number from the project +BUILD_NUMBER=$(grep -m1 "CURRENT_PROJECT_VERSION" Meetingnotes.xcodeproj/project.pbxproj | sed 's/.*= \(.*\);/\1/') +if compgen -G "$APPCAST_WORK/${APP_NAME}${BUILD_NUMBER}-"*.delta > /dev/null 2>&1; then + echo "[DEBUG] Moving new delta files for build $BUILD_NUMBER..." + mv "$APPCAST_WORK/${APP_NAME}${BUILD_NUMBER}-"*.delta "$VERSION_DIR/" 2>/dev/null || true fi rm -rf "$APPCAST_WORK"