

Automating Sparkle Updates for macOS Apps

Goodbye, App Center. Hello, Automation.
With App Center shutting down its servicesβincluding Sparkle update hostingβmacOS developers need a new way to distribute updates. If you're using Sparkle to manage app updates, the process can be tedious:
- Manually creating a
.dmg
- Notarizing it
- Generating an
update.xml
with correct versions and changelogs - Ensuring the update is correctly signed
- Distributing the appcast and updated build
- Archiving previous builds
- Maintaining a URL to the latest build
To make this process seamless, Iβve created a set of scripts that will automate everything from build selection to signing and publishing updates via S3 and CloudFront.
The Scripts
π Get the scripts here: Cindori/sparkle-publisher
This automation consists of three main scripts:
prepare-dmg.sh
- Finds the latest Xcode build of your app
- Packages it into a signed
.dmg
file - Submits it for notarization
- Staples the notarization ticket
publish-update.sh
- Extracts version and build info from
update.xml
- Reads the Changelog.md file for the latest release notes
- Uploads the
.dmg
andupdate.xml
to Amazon S3 - Invalidates CloudFront caches for instant availability
release.sh
- Calls
prepare-dmg.sh
to generate the.dmg
- Runs
publish-update.sh
to push the update online
The scripts are separated so you can easily debug or use parts of the whole workflow.
Requirements
To use these scripts, you need to set up a few things first:
1. Generate Signing Keys for Sparkle
Before you can sign Sparkle updates, you must generate signing keys. Sparkle provides tools for this, and you should have already created a key in your macOS Keychain labeled Private key for signing Sparkle updates
.
If you haven't done this, follow Sparkle's documentation to generate and store the signing keys.
2. Set Up Amazon S3 + CloudFront
You'll need an S3 bucket to host the update files and CloudFront as a CDN for efficient and secure distribution. Using CloudFront ensures that:
- Updates are delivered faster to global users.
- Downloads are signed and served over HTTPS.
- Updates remain accessible even if S3 rate limits are triggered.
Make sure you:
- Set up an S3 bucket to store updates.
- Configure CloudFront to serve files from S3.
- Get your CloudFront Distribution ID (you'll need it for cache invalidation).
The scripts will create the following hierarchy in your bucket:
YourBucket
βββ apps
β βββ YourAppName (lowercased)
β β βββ YourAppName.dmg
β β βββ updates
β β β βββ update.xml
β β β βββ x.x.x-y
β β β β βββ YourAppName.dmg
Where x.x.x
is the version, and y
is the build number.
The scripts will generate both a publicly facing latest version in the app folder and a versioned archive of update builds. This allows you to maintain a static URL for the latest version (e.g., for your landing page) while preserving older versions for rollbacks, historical reference, or cases where a new minimum OS requirement prevents certain users from updating beyond a specific version.
If you want to customize this structure, you will need to edit the scripts first.
3. Install DropDMG and Create a Template
This script uses DropDMG to generate disk images. You must:
- Install DropDMG.
- Create a custom DropDMG template that defines how your
.dmg
will appear to users. - Place the theme files inside the
DMG
directory (see folder structure below).
4. Required CLI Tools
Ensure the following tools are installed:
- Sparkle Tools (
sign_update
,generate_appcast
) - AWS CLI (configured for S3 and CloudFront)
- DropDMG (and its command-line tool)
- Xcode Command Line Tools (
notarytool
,stapler
) fzf
(optional, for a better build selection UI)
5. Changelog Format
The scripts expect a changelog to exist in the project root folder in Markdown format. Each version section should follow this format:
## x.x.x (yy) (2025-02-06)
- Improvement A
- Improvement B
...
- x.x.x β Version string
- yy β Build number
- 2025-02-06 β Release date
The scripts expect that you've manually updated the changelog before running it.
6. Folder Structure
The scripts assume the following directory layout in your project:
YourProjectFolder
βββ Changelog.md
βββ Scripts
β βββ prepare-dmg.sh
β βββ release.sh
β βββ publish-update.sh
βββ DMG
β βββ <place the contents of your DropDMG template here>
β βββ Info.plist
β βββ Background
β βββ Icons
βββ Utilities
β βββ Sparkle
β β βββ generate_appcast
βββ Build
β βββ <place your exported builds here>
7. Update the script config
Once you're ready, edit the script to replace the configuration values with your own data:
- NAME
- WEBSITE
- S3_BUCKET
- CLOUDFRONT_DISTRIBUTION_ID
- DEVELOPER_ID
Running the Script
Once your setup is complete, it's time to release updates!
- Archive your build in Xcode and export your app, selecting Custom method and then Direct Distribution.

Save it in your projects Build folder.
Using the Terminal, navigate to your Scripts folder in your project and run the release script.
./release.sh
If multiple builds exist, youβll be prompted to choose the latest.

The script extracts the latest changelog entry for the current build. Confirm and approve the update.
Done! The update is published, the current release is updated, and CloudFront caches are refreshed.
Any user around the world can now hit "Check for updates" in your app and update to the latest version.
Making Sparkle Updates Effortless
These scripts streamline your macOS app updates to a single commandβno more manual notarization, signing, or appcast edits. Just focus on building your app, and let the automation handle the rest.
Give it a try, and let me know what you ship! π