How vorssaint-utils Packages Its macOS DMG Releases: A Complete Technical Breakdown
The vorssaint-utils project automates its macOS DMG packaging through the Tools/make-dmg.sh script, which orchestrates code signing, custom background generation, drag-and-drop installer styling, and compressed disk image creation.
The vorssaint-utils repository provides a fully automated pipeline for distributing macOS applications. Understanding how vorssaint-utils packages its DMG releases reveals a sophisticated build process that combines Swift tooling, AppleScript automation, and robust error handling to produce polished installer images. The entire workflow is driven by shell scripts invoked through GitHub Actions, ensuring reproducible releases from source to distributable artifact.
The DMG Packaging Pipeline Overview
The packaging process consists of nine distinct stages executed sequentially by Tools/make-dmg.sh. The script first verifies the integrity of a pre-built signed application, then constructs a temporary staging environment, applies visual styling through macOS Finder automation, and finally compresses the result into a read-only DMG suitable for distribution.
Building and Signing the Application
Before packaging begins, the build.sh script compiles the Swift sources and produces a signed application bundle at build/stage/Vorssaint.app. The DMG packaging script enforces code signing integrity by removing extended attributes and verifying the signature before proceeding:
xattr -cr "$APP"
codesign --verify --deep --strict "$APP"
These commands ensure that quarantine attributes do not interfere with the signing validation and that the application meets macOS Gatekeeper requirements. The verification step acts as a gate; if the app fails this check, the packaging process halts immediately.
Version Detection and Asset Preparation
The script extracts the marketing version from the application's Info.plist using PlistBuddy to generate the output filename dynamically:
VERSION="$(/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' "$APP/Contents/Info.plist")"
OUT="dist/Vorssaint-$VERSION.dmg"
Concurrently, the script generates a custom background image for the installer window by invoking a Swift helper:
swift Tools/MakeDMGBackground.swift build/dmg-background.png
This Tools/MakeDMGBackground.swift utility renders the background asset that will be displayed behind the application icon and Applications folder shortcut in the final DMG window.
Staging the Installer Contents
The script creates a temporary staging directory using mktemp -d and constructs the standard macOS installer layout. It copies the signed application, creates a symbolic link to /Applications, and places the background image in a hidden .background directory:
STAGING="$(mktemp -d)"
ditto "$APP" "$STAGING/$APP_NAME.app"
ln -s /Applications "$STAGING/Applications"
mkdir "$STAGING/.background"
cp build/dmg-background.png "$STAGING/.background/background.png"
This structure creates the familiar drag-and-drop installation experience where users move the application icon onto the Applications folder alias.
Creating the Disk Image
The script generates a writable disk image (UDRW format) using hdiutil create. To handle transient failures common in CI environments, this command executes within a retry loop that attempts the operation up to three times:
hdiutil create -volname "$VOLUME" -srcfolder "$STAGING" -fs HFS+ -format UDRW -ov "$RW"
After creation, the script mounts this writable image and executes an AppleScript block to configure the Finder window. The script sets icon view, hides the toolbar and status bar, positions the app icon and Applications shortcut at specific coordinates, and applies the custom background image. This styling runs as a background process with a timeout safeguard to prevent CI pipelines from hanging on UI automation.
Compressing the Final Release
Once the visual styling is complete, the script detaches the writable image and converts it to a compressed, read-only format:
hdiutil convert "$RW" -format UDZO -imagekey zlib-level=9 -o "$OUT" -quiet
The UDZO format with zlib-level=9 provides maximum compression, minimizing download sizes for end users. The final artifact is placed in dist/Vorssaint-<version>.dmg, ready for distribution.
CI/CD Integration
The packaging workflow is integrated into the GitHub Actions release pipeline defined in .github/workflows/release.yml. The workflow executes the build and packaging scripts in sequence before uploading the resulting DMG as a release artifact:
steps:
- name: Build app
run: ./build.sh
- name: Create DMG
run: Tools/make-dmg.sh
- name: Upload DMG
uses: actions/upload-artifact@v3
with:
name: vorssaint-dmg
path: dist/*.dmg
This automation ensures that every release tag produces a consistently packaged DMG without manual intervention.
Summary
- Primary automation: The
Tools/make-dmg.shscript orchestrates the entire packaging pipeline from verification to compression. - Code signing verification: The script validates the application signature using
codesign --verify --deep --strictand strips extended attributes withxattr -crbefore packaging. - Dynamic versioning: The DMG filename is constructed using
CFBundleShortVersionStringextracted fromInfo.plistviaPlistBuddy. - Visual customization: A Swift helper (
Tools/MakeDMGBackground.swift) generates custom backgrounds, while AppleScript automates Finder window styling with timeout protection for CI environments. - Robust creation: The
hdiutil createcommand includes retry logic to handle transient build failures, targeting theUDRWformat before final compression. - Maximum compression: The final DMG uses
UDZOformat with zlib level 9 compression to optimize download sizes.
Frequently Asked Questions
How is the version number for the DMG filename determined?
The script extracts the version string from the signed application's metadata using /usr/libexec/PlistBuddy to read the CFBundleShortVersionString key from Vorssaint.app/Contents/Info.plist. This value is then interpolated into the output path as dist/Vorssaint-<version>.dmg, ensuring the filename always reflects the current build version without manual updating.
What prevents the AppleScript styling from hanging in CI environments?
The Finder window styling in Tools/make-dmg.sh executes within a background subshell that includes a timeout mechanism. This prevents the CI pipeline from hanging if the AppleScript encounters issues with the window server or Finder responsiveness during automated builds, as implemented in the script's window configuration section.
Why does the script remove extended attributes before packaging?
The xattr -cr command removes quarantine attributes and other extended metadata from the application bundle before codesign --verify executes. This ensures that macOS security attributes applied during download or previous operations do not interfere with signature validation, guaranteeing that the signature check reflects the actual code signing state rather than environmental metadata.
Can the DMG be created without the custom background?
While the default Tools/make-dmg.sh script invokes MakeDMGBackground.swift to generate visual assets, the core hdiutil operations and staging logic function independently of the background image. Removing or commenting out the background generation and AppleScript styling lines would produce a functional DMG without the custom installer appearance, though this would require modifying the source script.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →