This document outlines the process for releasing new versions of Blankie.
Blankie is a universal app. A release covers the Mac build (App Store, GitHub, and Homebrew) and the iOS/iPadOS build for iPhone and iPad (App Store and TestFlight, including CarPlay).
Blankie follows Semantic Versioning:
- MAJOR version for incompatible API changes
- MINOR version for new functionality in a backwards compatible manner
- PATCH version for backwards compatible bug fixes
Before creating a release, ensure:
- All tests pass
- Version numbers are updated:
MARKETING_VERSIONinBlankie.xcodeproj/project.pbxproj(the target editor updates every target and configuration at once)CURRENT_PROJECT_VERSION(the build number) inConfiguration.xcconfig— bump it for every uploaded build
-
CHANGELOG.mdfollows Keep a Changelog format, with items moved from Unreleased into the new version section - All new features are documented
- Credits are updated for any new contributors
Pick the scheme by what you're archiving:
- Mac (App Store/TestFlight, GitHub, Homebrew): archive from
Blankie (Universal)with the Any Mac destination. This uses the standard entitlements (no CarPlay). - iOS (App Store/TestFlight): archive from
Blankie (Universal with CarPlay)with the Any iOS Device destination, so the CarPlay entitlement is included. This requires thecom.apple.developer.carplay-audioentitlement on the release bundle ID (see CARPLAY.md).
On iOS the app ships animated artwork as Apple-hosted Background Assets asset packs (one pack per variant, downloaded on demand). The videos are not bundled in the build and not stored in git. They are packaged into .aar archives and uploaded to App Store Connect separately from the app, so plan for an extra upload and review step. The architecture and one-time project setup (downloader extension, App Group, plist keys) are in DEVELOPMENT.md.
Each clip ships two variants because iPhone and iPad lock screens advertise different artwork keys: a 3:4 portrait master (<Name>, for iPhone's 3x4 key) and a 1:1 square crop (<Name>Square, for iPad's 1x1 key). Both .mov live in ArtworkSources/<Name>/, a directory kept outside the app's synced folder so the videos can never be bundled (their previews and metadata stay tracked under Blankie/Resources/AnimatedArtwork/<Name>/). Every source .mov (both variants, all listed in scripts/animated-artwork.manifest) lives together on a single GitHub Release: artwork-assets-v1.
Each release, build and upload the asset packs:
scripts/package_animated_artwork.sh # → build/AssetPacks/<Name>.aar (42 packs: 21 portrait + 21 square)Then upload the .aar files to App Store Connect (Transporter app, xcrun altool, or the App Store Connect API) and submit them for review alongside the build. Apple hosts up to 200 GB of asset packs; ours are well under that.
How
artwork-assets-vNreleases work: the source.movlive as GitHub Release assets, addressed by filename and pinned by checksum inscripts/animated-artwork.manifest. A tag is one immutable version of that set (published bytes are never overwritten) and its number tracks the asset-pack version on App Store Connect (tagvN↔ pack versionN), keeping the source release and the Apple-hosted packs in lockstep. Everything currently lives onartwork-assets-v1.
- Adding a clip or variant is a new filename, so it just appends to the current release.
- Changing an existing video's content needs the next tag: a published asset can't be overwritten, so the new bytes go on a fresh release (anchored to an empty orphan commit, keeping binaries out of code history) while the old ones stay put. Splitting the set across tags is optional — name-addressing lets a renamed file sit alongside the rest on one release — and the packaging script pulls every entry from a single default
TAG, so you only add a per-entry tag column to the manifest if entries truly span releases.
-
Tag the Release
git tag -a v2.0.0 -m "chore: bump marketing version to v2.0.0" git push origin v2.0.0 -
Archive the builds
- In Xcode, select the scheme and destination from Scheme Selection above
- Archive the app (Product → Archive). Archive the Mac and iOS builds separately
- The Organizer window opens when each archive completes
-
App Store Release
- From the Organizer, select an archive and click "Distribute App"
- Choose "App Store Connect" → "Upload"
- Follow the prompts to upload to App Store Connect
- Repeat for the other platform's archive (both platforms live under the same App Store app record)
- In App Store Connect:
- Add the new builds to the Mac and iOS versions
- Update the "What's New" section with release notes from
CHANGELOG.md - Submit for review
- Once approved, release immediately or schedule the release
-
GitHub Release
- From the Mac archive in the Organizer, click "Distribute App" again
- Choose "Direct Distribution"
- After a brief notarization check, the app can be exported
- Export to a folder, then create a ZIP file named
Blankie.zipcontaining only the exportedBlankie.appat the root level
-
Create the GitHub Release
- Go to the GitHub releases page
- Create a new release from the tag
- Copy the relevant section from
CHANGELOG.mdas the release notes - Upload
Blankie.zipas the release asset
After the GitHub release is published:
-
Wait for the release ZIP to be available on GitHub
-
Run the following command to update the Homebrew cask:
brew bump-cask-pr --version [version] blankie
Replace
[version]with the new version number (e.g.,2.0.0) -
The command will automatically:
- Download the new release
- Calculate the SHA256 checksum
- Update the cask formula
- Create a pull request to the Homebrew cask repository
-
Monitor the pull request for any feedback from Homebrew maintainers
Note: You need to have Homebrew and the homebrew/cask tap installed to run this command.
If the brew bump-cask-pr command fails:
- Ensure you have the latest Homebrew:
brew update - Check that you have push access to your Homebrew fork
- Manually create a PR if needed, updating the version and sha256 in the cask file