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_keys, generate_appcast, gh, python3, zip, curl, plus APP_STORE_CONNECT_*. SPARKLE_PRIVATE_KEY_FILE is only needed when overriding the default Keychain Sparkle key./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..mac-release.env; CodexBar still uses the older shared AGCY key, so the manifest includes the local Dropbox fallback path. SPARKLE_PRIVATE_KEY_FILE overrides it.source ~/.profile) before running Scripts/release.sh.Scripts/mac-release resolves MAC_RELEASE_TOOL, sibling ../agent-scripts, or ~/Projects/agent-scripts../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-macos-universal-<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, or let Scripts/release.sh do this:
./Scripts/make_appcast.sh CodexBar-macos-universal-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).
./Scripts/release.sh
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, .github/workflows/release-cli.yml builds the macOS, glibc Linux, and static musl Linux CLI tarballs for arm64 and x86_64, uploads them plus checksums, then dispatches the Homebrew tap update for both the CLI formula and app cask. Homebrew continues to use the glibc Linux assets. If the final dispatch is rate-limited, the tarballs and app zip may still be present; rerun or manually update the tap formula/cask from the published assets.
~/Projects/agent-scripts/docs/RELEASING-MAC.md; resolve any conflicts toward CodexBar’s specifics.swiftformat, swiftlint, make test (zero warnings/errors)./Scripts/build_icon.sh if icon changed./Scripts/sign-and-notarize.shScripts/release.sh or Scripts/make_appcast.sh; use SPARKLE_PRIVATE_KEY_FILE only if overriding Keychain signing.
Scripts/check-release-assets.sh <tag> to confirm the app zip, dSYM zip, CLI tarballs, and CLI checksums are present on GitHub../Scripts/make_appcast.sh CodexBar-macos-universal-<ver>.zip https://raw.githubusercontent.com/steipete/CodexBar/main/appcast.xmlSPARKLE_CHANNEL=beta to tag the entry../Scripts/verify_appcast.sh <ver>../homebrew-tap/Casks/codexbar.rb (app zip url + sha256) and ../homebrew-tap/Formula/codexbar.rb (CLI tarball urls + sha256), then verify:
gh run watch <release-cli-run-id> --exit-statusScripts/check-release-assets.sh v<version>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-macos-universal-<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>.