docs/RELEASING.md
SwiftPM-only; package/sign/notarize manually (no Xcode project). Sparkle feed is served from GitHub Releases. Checklist below merges Trimmy’s release flow with CodexBar specifics.
Must read first: open the master macOS release guide at ~/Projects/agent-scripts/docs/RELEASING-MAC.md alongside this file and reconcile any differences in favor of CodexBar specifics before starting a release.
swiftformat, swiftlint, swift, sign_update, generate_appcast, gh, python3, zip, curl, plus APP_STORE_CONNECT_* and SPARKLE_PRIVATE_KEY_FILE./Applications/Xcode.app (for ictool/iconutil and SDKs).Developer ID Application: Peter Steinberger (Y5PE65HELJ).APP_STORE_CONNECT_API_KEY_P8, APP_STORE_CONNECT_KEY_ID, APP_STORE_CONNECT_ISSUER_ID.SPARKLE_PRIVATE_KEY_FILE when generating appcast.source ~/.profile) before running Scripts/release.sh../Scripts/build_icon.sh Icon.icon CodexBar
Uses Xcode’s ictool + transparent padding + iconset → Icon.icns.
./Scripts/sign-and-notarize.sh
What it does:
swift build -c release --arch arm64 and swift build -c release --arch x86_64CodexBar.app with Info.plist and Icon.icnsCodexBar-<version>.zipGotchas fixed:
--timestamp and --deep when signing the app to avoid invalid signature errors.unzip — it can add AppleDouble ._* files that break the sealed signature and trigger “app is damaged”. Use Finder or ditto -x -k CodexBar-<ver>.zip /Applications. If Gatekeeper complains, delete the app bundle, re-extract with ditto, then spctl -a -t exec to verify.find CodexBar.app -name '._*' should return nothing; then spctl --assess --type execute --verbose CodexBar.app and codesign --verify --deep --strict --verbose CodexBar.app should both pass on the packaged bundle.After notarization:
SPARKLE_PRIVATE_KEY_FILE=/path/to/ed25519-priv.key \
./Scripts/make_appcast.sh CodexBar-0.1.0.zip \
https://raw.githubusercontent.com/steipete/CodexBar/main/appcast.xml
Generates HTML release notes from `CHANGELOG.md` (via `Scripts/changelog-to-html.sh`) and embeds them into the appcast entry.
Uploads not handled automatically—commit/publish appcast + zip to the feed location (GitHub Releases/raw URL).
git tag v<version>
./Scripts/make_appcast.sh ...
# upload zip + appcast to Releases
# then create GitHub release (gh release create v<version> ...)
CodexBar ships a Homebrew Cask in ../homebrew-tap. When installed via Homebrew, CodexBar disables Sparkle and the app
must be updated via brew.
After publishing the GitHub release, update the tap cask + CLI formula (see docs/releasing-homebrew.md).
~/Projects/agent-scripts/docs/RELEASING-MAC.md; resolve any conflicts toward CodexBar’s specifics.swiftformat, swiftlint, swift test (zero warnings/errors)./Scripts/build_icon.sh if icon changed./Scripts/sign-and-notarize.sh/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle/sparkle-private-key-KEEP-SECURE.txt (primary) and /Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle-VibeTunnel/sparkle-private-key-KEEP-SECURE.txt (older backup)Scripts/check-release-assets.sh <tag> to confirm both the app zip and dSYM zip are present on GitHub../Scripts/make_appcast.sh CodexBar-<ver>.zip https://raw.githubusercontent.com/steipete/CodexBar/main/appcast.xmlSPARKLE_CHANNEL=beta to tag the entry.SPARKLE_PRIVATE_KEY_FILE=... ./Scripts/verify_appcast.sh <ver>../homebrew-tap/Casks/codexbar.rb (url + sha256) and ../homebrew-tap/Formula/codexbar.rb (CLI tarball urls + sha256), then verify:
brew uninstall --cask codexbar || truebrew untap steipete/tap || true; brew tap steipete/tapbrew install --cask steipete/tap/codexbar && open -a CodexBarCodexBar <version>, notes as Markdown list (no stray blank lines)CodexBar-<ver>.zip, unzip via ditto, run, and verify signature (spctl -a -t exec -vv CodexBar.app + stapler validate)appcast.xml points to the new zip/version and renders the HTML release notes (not escaped tags)sparkle:edSignature is present for the enclosure in appcast (generated by generate_appcast with the ed25519 key)- per line, blank line between sections); visually confirm bullets render correctly after publishing/Applications/CodexBar.app to test Sparkle delta/full update to the new releasefind CodexBar.app -name '._*' is empty, spctl --assess --type execute --verbose CodexBar.app and codesign --verify --deep --strict --verbose CodexBar.app succeed/Applications/CodexBar.app, quit first, replace, relaunch, and test updatebuild_icon.sh (ictool) to ensure transparent padding.Contents/Frameworks and rpath added; codesign deep.ditto -x -k, removing any ._* files, then re-verify with spctl.curl -I <enclosure-url>.