Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 72 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ name: Release
# NOTARY_ISSUER_ID App Store Connect issuer id
#
# Repository secrets:
# SPARKLE_PRIVATE_KEY Sparkle EdDSA private key (optional until Sparkle ships)
# SPARKLE_PRIVATE_KEY Sparkle EdDSA private key
# HOMEBREW_TAP_TOKEN token that can push to TerrifiedBug/homebrew-tap

on:
Expand Down Expand Up @@ -112,6 +112,63 @@ jobs:
ZIP: ${{ steps.v.outputs.zip }}
run: |
echo "sha256=$(shasum -a 256 "$ZIP" | awk '{print $1}')" >> "$GITHUB_OUTPUT"
echo "size=$(stat -f%z "$ZIP")" >> "$GITHUB_OUTPUT"
echo "bundleVersion=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' dist/Browseroute.app/Contents/Info.plist)" >> "$GITHUB_OUTPUT"
echo "shortVersion=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' dist/Browseroute.app/Contents/Info.plist)" >> "$GITHUB_OUTPUT"

- name: Sign update with Sparkle
id: sparkle
env:
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
ZIP: ${{ steps.v.outputs.zip }}
run: |
if [ -z "$SPARKLE_PRIVATE_KEY" ]; then
echo "::error::SPARKLE_PRIVATE_KEY is not set. GitHub zip installs cannot self-update without it."
exit 1
fi
SIGN_UPDATE="$(find .build/artifacts -name sign_update -type f | head -1)"
if [ ! -x "$SIGN_UPDATE" ]; then
echo "::error::sign_update not found under .build/artifacts"
exit 1
fi
SIGNATURE=$("$SIGN_UPDATE" "$ZIP" \
--ed-key-file <(echo "$SPARKLE_PRIVATE_KEY") \
| sed -n 's/.*sparkle:edSignature="\([^"]*\)".*/\1/p')
if [ -z "$SIGNATURE" ]; then
echo "::error::sign_update produced no signature"
exit 1
fi
echo "signature=$SIGNATURE" >> "$GITHUB_OUTPUT"

- name: Generate appcast.xml
env:
VERSION: ${{ steps.v.outputs.version }}
TAG: ${{ steps.v.outputs.tag }}
SIGNATURE: ${{ steps.sparkle.outputs.signature }}
SIZE: ${{ steps.pkg.outputs.size }}
BUNDLE_VERSION: ${{ steps.pkg.outputs.bundleVersion }}
SHORT_VERSION: ${{ steps.pkg.outputs.shortVersion }}
run: |
cat > appcast.xml <<XMLEOF
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Browseroute Updates</title>
<item>
<title>Version $SHORT_VERSION</title>
<sparkle:version>$BUNDLE_VERSION</sparkle:version>
<sparkle:shortVersionString>$SHORT_VERSION</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>14.0</sparkle:minimumSystemVersion>
<pubDate>$(date -R)</pubDate>
<enclosure
url="https://github.com/TerrifiedBug/browseroute/releases/download/$TAG/Browseroute-$VERSION.zip"
sparkle:edSignature="$SIGNATURE"
length="$SIZE"
type="application/octet-stream" />
</item>
</channel>
</rss>
XMLEOF

- name: Create GitHub release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
Expand All @@ -121,6 +178,20 @@ jobs:
generate_release_notes: true
fail_on_unmatched_files: true

- name: Commit appcast.xml
env:
TAG: ${{ steps.v.outputs.tag }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
cp appcast.xml "$RUNNER_TEMP/appcast.xml"
git fetch origin main
git checkout -f main
cp "$RUNNER_TEMP/appcast.xml" appcast.xml
git add appcast.xml
git commit -m "Update appcast.xml for $TAG" || echo "No changes to commit"
git push origin main

- name: Update Homebrew cask
env:
VERSION: ${{ steps.v.outputs.version }}
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ All notable changes to Browseroute are documented here (Keep a Changelog style).
- App icon: charcoal squircle with a routing Y (About, Finder, README).

- Developer ID-signed, notarized GitHub releases (same methodology as yap and TickerBar) and a Homebrew cask.
- Sparkle is an SPM dependency on the app target so Check for Updates can run once `SUPublicEDKey` is a real EdDSA key.
- Sparkle EdDSA key baked in; Check for Updates is live on signed GitHub builds (Homebrew still manages its own updates).
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ open /Applications/Browseroute.app

Or download `Browseroute-<version>.zip` from the
[latest release](https://github.com/TerrifiedBug/browseroute/releases/latest),
unzip, and move `Browseroute.app` into Applications.
unzip, and move `Browseroute.app` into Applications. GitHub zip installs
check for updates from Settings. Homebrew cask installs are updated by
Homebrew.

To build from source (Swift 6.2 toolchain):

Expand Down
2 changes: 1 addition & 1 deletion Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<key>SUFeedURL</key>
<string>https://raw.githubusercontent.com/terrifiedbug/browseroute/main/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>REPLACE_WITH_YOUR_SPARKLE_ED_PUBLIC_KEY</string>
<string>wRn6yH/DH5PndDPMrDfOEiJhZ6nUIiUEibd7PObXOwo=</string>
<key>SUEnableAutomaticChecks</key>
<true/>
<key>CFBundleURLTypes</key>
Expand Down
Loading