release: prep v2.7.0 — consolidated notes + in-app Sparkle release notes

Rolls up everything since v2.6.5 (36 commits across remote-perf,
project wizard, dashboard widgets, OAuth resilience, ScarfMon
instrumentation, and the v2.7 skeleton-then-hydrate redesign) into
a single 2.7.0 release.

* releases/v2.7.0/RELEASE_NOTES.md — full consolidated notes,
  reorganized around the throughline (slow-remote performance) with
  five thematic sections: skeleton-then-hydrate loaders, SSH
  cancellation, project wizard + Keychain cron secrets, dashboard
  widgets, OAuth resilience, and ScarfMon. Replaces the previously-
  drafted dashboard-only v2.7.0 stub and the separate v2.8 wizard
  stub (both unreleased).
* releases/v2.8/ — deleted; folded into v2.7.
* README.md — "What's New in 2.6" → "What's New in 2.7" with the
  five-section summary linking out to the full notes.

* tools/render-release-notes.py — stdlib-only Markdown → HTML
  renderer covering the subset of GitHub-flavored markdown that
  release notes use (## / ### headings, paragraphs, ul lists,
  fenced code, inline code/bold/italic/links, hr). Output includes
  a small <style> block tuned for Sparkle's update alert WebKit
  view (light + dark variants via prefers-color-scheme).
* scripts/release.sh — render the active RELEASE_NOTES.md and
  inject the result as <description><![CDATA[...]]></description>
  on the appcast item. Sparkle's standard updater renders this in
  the in-app update sheet so users see release-specific "what's
  new" alongside the version number, not just the bare version.
  Falls back to a "see GitHub release page" placeholder when the
  notes file is missing.

User runs ./scripts/release.sh 2.7.0 to ship.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-05-05 20:31:27 +02:00
parent 5e23b59697
commit cd5bb32a21
5 changed files with 420 additions and 149 deletions
+20
View File
@@ -221,6 +221,23 @@ FILE_LENGTH="$(echo "$SIG_OUTPUT" | sed -nE 's/.*length="([^"]+)".*/\1/p')"
DOWNLOAD_URL="$DOWNLOAD_URL_BASE/v${VERSION}/Scarf-v${VERSION}-Universal.zip"
PUB_DATE="$(LC_TIME=en_US.UTF-8 date -u +"%a, %d %b %Y %H:%M:%S +0000")"
# Render RELEASE_NOTES.md to a Sparkle-friendly inline HTML fragment
# and embed it as <description><![CDATA[…]]></description> on the
# appcast item. Sparkle's standard update alert renders this in a
# WebKit view so users see the release-specific "what's new" inside
# the in-app update sheet, not just the version number. Falls back to
# a placeholder line when the notes file is missing (matches the
# `--notes-file` fallback behavior of `gh release create` below).
RELEASE_NOTES_HTML=""
if [[ -f "$NOTES_FILE" ]]; then
log "Render in-app release notes from $NOTES_FILE"
RELEASE_NOTES_HTML="$(python3 "$REPO_ROOT/tools/render-release-notes.py" "$NOTES_FILE")"
fi
if [[ -z "$RELEASE_NOTES_HTML" ]]; then
RELEASE_NOTES_HTML="<p>Release v${VERSION}. See the <a href=\"https://github.com/awizemann/scarf/releases/tag/v${VERSION}\">GitHub release page</a> for details.</p>"
fi
APPCAST_ITEM=$(cat <<EOF
<item>
<title>Version ${VERSION}</title>
@@ -228,6 +245,9 @@ APPCAST_ITEM=$(cat <<EOF
<sparkle:shortVersionString>${VERSION}</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>14.6</sparkle:minimumSystemVersion>
<pubDate>${PUB_DATE}</pubDate>
<description><![CDATA[
${RELEASE_NOTES_HTML}
]]></description>
<enclosure url="${DOWNLOAD_URL}"
sparkle:edSignature="${ED_SIGNATURE}"
length="${FILE_LENGTH}"