Skip to content

Promote#25

Merged
marcelrgberger merged 2 commits intobetafrom
test
Mar 26, 2026
Merged

Promote#25
marcelrgberger merged 2 commits intobetafrom
test

Conversation

@marcelrgberger
Copy link
Copy Markdown
Owner

.

- EdDSA public key set in Info.plist
- Sparkle auto-check enabled at startup
- Build workflow signs ZIP and updates appcast.xml on release
- SPARKLE_PRIVATE_KEY stored as GitHub Secret
- Version 1.0.2 (build 3)
Sparkle auto-updates + signed appcast v1.0.2
Copilot AI review requested due to automatic review settings March 26, 2026 16:03
@marcelrgberger marcelrgberger merged commit b7198d7 into beta Mar 26, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates AutoBrew’s release configuration to enable Sparkle-based in-app updates for production builds by adding signing metadata, enabling the updater, and generating a signed appcast during CI releases.

Changes:

  • Bump MARKETING_VERSION / CURRENT_PROJECT_VERSION for the next release.
  • Enable Sparkle updater startup and add SUPublicEDKey to support signed appcasts.
  • Extend the GitHub Actions release workflow to sign the update ZIP and generate/push an appcast.xml entry.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
project.yml Version/build bump for the release.
Sources/Services/UpdaterService.swift Starts Sparkle updater automatically.
AutoBrew/Info.plist Adds Sparkle public key for EdDSA verification.
.github/workflows/build-and-release.yml Signs Sparkle update and generates/pushes appcast.xml during main releases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

SPARKLE_BIN=$(find "$HOME/Library/Developer/Xcode/DerivedData" -name "sign_update" -path "*/Sparkle/bin/*" 2>/dev/null | head -1)
if [ -z "$SPARKLE_BIN" ]; then
echo "sign_update not found, downloading Sparkle tools..."
curl -sL "https://github.com/sparkle-project/Sparkle/releases/latest/download/Sparkle-2.9.0.tar.xz" | tar xJ -C /tmp
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Sparkle tools download URL mixes releases/latest with a hard-coded asset name (Sparkle-2.9.0.tar.xz). When Sparkle releases a newer version, latest will no longer have a Sparkle-2.9.0.tar.xz asset and this step will start failing. Use a tag-pinned URL (e.g., /releases/download/<tag>/Sparkle-<tag>.tar.xz) or fetch the actual latest asset name dynamically.

Suggested change
curl -sL "https://github.com/sparkle-project/Sparkle/releases/latest/download/Sparkle-2.9.0.tar.xz" | tar xJ -C /tmp
curl -sL "https://github.com/sparkle-project/Sparkle/releases/download/2.9.0/Sparkle-2.9.0.tar.xz" | tar xJ -C /tmp

Copilot uses AI. Check for mistakes.
Comment on lines +204 to +211
# Sign the ZIP
echo "$SPARKLE_KEY" > /tmp/sparkle_key
SIGNATURE=$("$SPARKLE_BIN" "build/$APP_NAME.zip" --ed-key-file /tmp/sparkle_key 2>&1 | grep "sparkle:edSignature" | sed 's/.*"\(.*\)".*/\1/')
LENGTH=$(stat -f%z "build/$APP_NAME.zip")
rm -f /tmp/sparkle_key

echo "SPARKLE_SIGNATURE=$SIGNATURE" >> "$GITHUB_ENV"
echo "ZIP_LENGTH=$LENGTH" >> "$GITHUB_ENV"
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SIGNATURE=$( ... | grep ... | sed ...) pipeline can silently produce an empty signature if sign_update fails or grep finds no match, because set -e doesn’t fail on errors inside pipelines unless pipefail is enabled. Add set -o pipefail (or set -euo pipefail) and explicitly validate SIGNATURE is non-empty before writing it to $GITHUB_ENV.

Copilot uses AI. Check for mistakes.
Comment on lines +249 to +251
git commit -m "Update appcast for v$VERSION" || true
git push origin HEAD:main || true

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The appcast is committed/pushed with || true, which can hide real failures (e.g., branch protections, auth issues) and result in releasing a build without updating the feed. Consider letting these commands fail the job (remove || true) or at least detect failure and exit 1 so releases don’t proceed with a stale appcast.

Suggested change
git commit -m "Update appcast for v$VERSION" || true
git push origin HEAD:main || true
if git diff --cached --quiet; then
echo "No changes to appcast.xml; skipping commit and push."
else
git commit -m "Update appcast for v$VERSION"
git push origin HEAD:main
fi

Copilot uses AI. Check for mistakes.
Comment on lines +213 to +244
- name: Update appcast.xml
if: github.ref == 'refs/heads/main'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
BUILD: ${{ steps.version.outputs.build }}
run: |
set -e
cat > appcast.xml << EOF
<?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>AutoBrew</title>
<link>https://github.com/marcelrgberger/auto-brew</link>
<description>AutoBrew update feed</description>
<language>en</language>
<item>
<title>Version $VERSION</title>
<pubDate>$(date -R)</pubDate>
<sparkle:version>$BUILD</sparkle:version>
<sparkle:shortVersionString>$VERSION</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>26.0</sparkle:minimumSystemVersion>
<enclosure
url="https://github.com/marcelrgberger/auto-brew/releases/download/v$VERSION/AutoBrew.zip"
length="$ZIP_LENGTH"
type="application/octet-stream"
sparkle:edSignature="$SPARKLE_SIGNATURE"
/>
</item>
</channel>
</rss>
EOF
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update appcast.xml runs before the GitHub Release is created/uploaded. If the release step fails, the workflow will still have pushed an appcast entry pointing at a (potentially) non-existent v$VERSION/AutoBrew.zip, breaking update checks. Reorder so the release is successfully created (and assets uploaded) before updating/pushing appcast.xml, or gate the appcast update on release success.

Copilot uses AI. Check for mistakes.
Comment on lines +205 to +208
echo "$SPARKLE_KEY" > /tmp/sparkle_key
SIGNATURE=$("$SPARKLE_BIN" "build/$APP_NAME.zip" --ed-key-file /tmp/sparkle_key 2>&1 | grep "sparkle:edSignature" | sed 's/.*"\(.*\)".*/\1/')
LENGTH=$(stat -f%z "build/$APP_NAME.zip")
rm -f /tmp/sparkle_key
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Sparkle private key is written to /tmp/sparkle_key and only removed after signing. If the step exits early (e.g., sign_update fails once pipefail is enabled), the key file may remain on disk for the rest of the job. Use a trap to delete it on exit and consider storing it under $RUNNER_TEMP with restrictive permissions (e.g., chmod 600).

Suggested change
echo "$SPARKLE_KEY" > /tmp/sparkle_key
SIGNATURE=$("$SPARKLE_BIN" "build/$APP_NAME.zip" --ed-key-file /tmp/sparkle_key 2>&1 | grep "sparkle:edSignature" | sed 's/.*"\(.*\)".*/\1/')
LENGTH=$(stat -f%z "build/$APP_NAME.zip")
rm -f /tmp/sparkle_key
SPARKLE_KEY_FILE="${RUNNER_TEMP:-/tmp}/sparkle_key"
trap 'rm -f "$SPARKLE_KEY_FILE"' EXIT
printf '%s\n' "$SPARKLE_KEY" > "$SPARKLE_KEY_FILE"
chmod 600 "$SPARKLE_KEY_FILE"
SIGNATURE=$("$SPARKLE_BIN" "build/$APP_NAME.zip" --ed-key-file "$SPARKLE_KEY_FILE" 2>&1 | grep "sparkle:edSignature" | sed 's/.*"\(.*\)".*/\1/')
LENGTH=$(stat -f%z "build/$APP_NAME.zip")

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants