its whats on the tin; culls raw photos
1#!/bin/bash
2# Update the Sparkle appcast.xml with a new release
3# Usage: ./update-appcast.sh VERSION TAG DMG_SIZE SPARKLE_SIGNATURE RELEASE_NOTES REPO
4
5set -e
6
7VERSION="$1"
8TAG="$2"
9DMG_SIZE="$3"
10SPARKLE_SIGNATURE="$4"
11RELEASE_NOTES="$5"
12REPO="$6"
13
14PUBDATE=$(date -R)
15DMG_URL="https://github.com/${REPO}/releases/download/${TAG}/Cull-${VERSION}-macOS.dmg"
16
17# Convert markdown release notes to HTML
18RELEASE_NOTES_HTML=$(echo "$RELEASE_NOTES" | python3 -c "
19import sys, re, html
20md = sys.stdin.read().strip()
21lines = []
22in_list = False
23for line in md.split('\n'):
24 stripped = line.strip()
25 if stripped.startswith('### '):
26 if in_list: lines.append('</ul>'); in_list = False
27 lines.append(f'<h3>{html.escape(stripped[4:])}</h3>')
28 elif stripped.startswith('## '):
29 if in_list: lines.append('</ul>'); in_list = False
30 lines.append(f'<h2>{html.escape(stripped[3:])}</h2>')
31 elif stripped.startswith('- '):
32 if not in_list: lines.append('<ul>'); in_list = True
33 content = stripped[2:]
34 content = re.sub(r'\*\*(.+?)\*\*', r'<b>\1</b>', content)
35 content = re.sub(r'\x60(.+?)\x60', r'<code>\1</code>', content)
36 lines.append(f' <li>{content}</li>')
37 elif stripped == '':
38 if in_list: lines.append('</ul>'); in_list = False
39 else:
40 if in_list: lines.append('</ul>'); in_list = False
41 content = re.sub(r'\*\*(.+?)\*\*', r'<b>\1</b>', stripped)
42 lines.append(f'<p>{content}</p>')
43if in_list: lines.append('</ul>')
44print('\n'.join(lines))
45")
46
47NEW_ITEM=" <item>
48 <title>Version ${VERSION}</title>
49 <pubDate>${PUBDATE}</pubDate>
50 <sparkle:version>${VERSION}</sparkle:version>
51 <sparkle:shortVersionString>${VERSION}</sparkle:shortVersionString>
52 <sparkle:minimumSystemVersion>14.0</sparkle:minimumSystemVersion>
53 <description><![CDATA[${RELEASE_NOTES_HTML}]]></description>
54 <enclosure
55 url=\"${DMG_URL}\"
56 sparkle:edSignature=\"${SPARKLE_SIGNATURE}\"
57 length=\"${DMG_SIZE}\"
58 type=\"application/octet-stream\"
59 sparkle:os=\"macos\"/>
60 </item>"
61
62APPCAST_FILE="docs/appcast.xml"
63
64if [ -f "$APPCAST_FILE" ]; then
65 # Insert the new item after <language>en</language>, before existing items
66 python3 << PYEOF
67appcast = open("$APPCAST_FILE").read()
68marker = "<language>en</language>"
69idx = appcast.find(marker)
70if idx == -1:
71 raise SystemExit("Error: could not find <language> tag in appcast.xml")
72end = idx + len(marker)
73new_item = """
74$NEW_ITEM"""
75result = appcast[:end] + new_item + appcast[end:]
76open("$APPCAST_FILE", "w").write(result)
77PYEOF
78else
79 cat > "$APPCAST_FILE" << APPCAST_EOF
80<?xml version="1.0" encoding="utf-8"?>
81<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
82 <channel>
83 <title>Cull Updates</title>
84 <link>https://taciturnaxolotl.github.io/cull/appcast.xml</link>
85 <description>Most recent updates to Cull</description>
86 <language>en</language>
87${NEW_ITEM}
88 </channel>
89</rss>
90APPCAST_EOF
91fi
92
93echo "Appcast updated for version ${VERSION}"