Skip to content

v1.0.2#26

Merged
marcelrgberger merged 3 commits intomainfrom
beta
Mar 26, 2026
Merged

v1.0.2#26
marcelrgberger merged 3 commits intomainfrom
beta

Conversation

@marcelrgberger
Copy link
Copy Markdown
Owner

Sparkle auto-updates

- 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 175a864 into main Mar 26, 2026
1 check passed
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

Enables Sparkle-based auto-updates for AutoBrew and bumps the release version to v1.0.2, including CI automation to generate/sign the appcast used by Sparkle.

Changes:

  • Bump MARKETING_VERSION / CURRENT_PROJECT_VERSION to 1.0.2 / 3.
  • Enable Sparkle updater startup by default and configure the app’s Sparkle public key.
  • Add GitHub Actions steps to sign the update ZIP and generate/push appcast.xml on main.

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 v1.0.2 release.
Sources/Services/UpdaterService.swift Starts Sparkle updater immediately (startingUpdater: true).
AutoBrew/Info.plist Sets SUPublicEDKey for Sparkle EdDSA signature verification.
.github/workflows/build-and-release.yml Adds Sparkle signing + appcast generation/publish during release workflow.

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

git config user.email "hello@marcelrgberger.com"
git add appcast.xml
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.

git commit/git push are both silenced with || true. If the push fails (e.g., branch protections, token permissions, transient errors), the workflow will still proceed to create a GitHub Release but the feed at SUFeedURL won’t be updated, breaking auto-update discovery. It would be safer to fail the job when updating/pushing the appcast fails (or otherwise make the release conditional on a successful appcast update).

Suggested change
git push origin HEAD:main || true
git push origin HEAD:main

Copilot uses AI. Check for mistakes.
<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"
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 workflow updates and pushes appcast.xml before the GitHub Release (and its AutoBrew.zip asset) is created. During that window, the appcast enclosure url points to a release asset that doesn’t exist yet, which can produce transient 404s for clients checking updates. Consider creating/uploading the release assets first, then publishing the appcast update afterward (or otherwise ensuring the enclosure URL is valid when the appcast is pushed).

Suggested change
url="https://github.com/marcelrgberger/auto-brew/releases/download/v$VERSION/AutoBrew.zip"
url="https://github.com/marcelrgberger/auto-brew/releases/latest/download/AutoBrew.zip"

Copilot uses AI. Check for mistakes.
Comment on lines +200 to +201
curl -sL "https://github.com/sparkle-project/Sparkle/releases/latest/download/Sparkle-2.9.0.tar.xz" | tar xJ -C /tmp
SPARKLE_BIN="/tmp/bin/sign_update"
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.

After downloading and extracting the Sparkle tools, SPARKLE_BIN is hard-coded to /tmp/bin/sign_update. The Sparkle release archive layout isn’t guaranteed to create /tmp/bin/…, so this path is likely incorrect and will cause the signing step to fail. Instead, locate sign_update inside the extracted archive (or extract into a known directory) and set SPARKLE_BIN to that actual path, and also ensure it’s executable before running it.

Suggested change
curl -sL "https://github.com/sparkle-project/Sparkle/releases/latest/download/Sparkle-2.9.0.tar.xz" | tar xJ -C /tmp
SPARKLE_BIN="/tmp/bin/sign_update"
TMP_SPARKLE_DIR="$(mktemp -d)"
curl -sL "https://github.com/sparkle-project/Sparkle/releases/latest/download/Sparkle-2.9.0.tar.xz" | tar xJ -C "$TMP_SPARKLE_DIR"
SPARKLE_BIN=$(find "$TMP_SPARKLE_DIR" -name "sign_update" -type f 2>/dev/null | head -1)
if [ -z "$SPARKLE_BIN" ]; then
echo "Error: sign_update not found in downloaded Sparkle archive."
exit 1
fi
chmod +x "$SPARKLE_BIN"

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +211
set -e
# Get Sparkle tools from SPM cache
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
SPARKLE_BIN="/tmp/bin/sign_update"
fi

# 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 step uses set -e, but the signature extraction is done through a pipeline inside command substitution. Without set -o pipefail (and ideally -u), failures in sign_update/grep can be masked and result in an empty/invalid SPARKLE_SIGNATURE being exported. Consider using set -euo pipefail here and explicitly validating that SIGNATURE is non-empty before writing it to $GITHUB_ENV.

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 without restricting file permissions. Since this is a signing key, it’s safer to create the file with a restrictive umask / chmod (and preferably use a unique temp path) to avoid accidental exposure to other processes on the runner.

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=$(mktemp)
chmod 600 "$SPARKLE_KEY_FILE"
printf '%s\n' "$SPARKLE_KEY" > "$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")
rm -f "$SPARKLE_KEY_FILE"

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