this repo has no description
at main 106 lines 8.4 kB view raw view rendered
1--- 2summary: "CodexBar release checklist: package, sign, notarize, appcast, and asset validation." 3read_when: 4 - Starting a CodexBar release 5 - Updating signing/notarization or appcast steps 6 - Validating release assets or Sparkle feed 7--- 8 9# Release process (CodexBar) 10 11SwiftPM-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. 12 13**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. 14 15## Expectations 16- When someone says “release CodexBar”, do the entire end-to-end flow: bump versions/CHANGELOG, build, sign and notarize, upload the zip to the GitHub release, generate/update the appcast with the new signature, publish the tag/release, and verify the enclosure URL responds with 200/OK and installs via Sparkle (no 404s or stale feeds). 17 18### Release automation notes (Scripts/release.sh) 19- Always forces a fresh build/notarization (no cached artifacts) before publishing. 20- Fails fast if: git tree is dirty, the top changelog section is still “Unreleased” or mismatched, the target version already exists in the appcast, or the build number is not greater than the latest appcast entry. 21- Sparkle key probe runs up front; appcast entry + signature verified automatically after generation. 22- Release notes are extracted directly from the current changelog section and passed to the GitHub release (no manual notes flag needed). 23- Requires tools/env on PATH: `swiftformat`, `swiftlint`, `swift`, `sign_update`, `gh`, `python3`, `zip`, `curl`, plus `APP_STORE_CONNECT_*` and `SPARKLE_PRIVATE_KEY_FILE`. 24 25## Prereqs 26- Xcode 26+ installed at `/Applications/Xcode.app` (for ictool/iconutil and SDKs). 27- Developer ID Application cert installed: `Developer ID Application: Peter Steinberger (Y5PE65HELJ)`. 28- ASC API creds in env: `APP_STORE_CONNECT_API_KEY_P8`, `APP_STORE_CONNECT_KEY_ID`, `APP_STORE_CONNECT_ISSUER_ID`. 29- Sparkle keys: public key already in Info.plist; private key path set via `SPARKLE_PRIVATE_KEY_FILE` when generating appcast. 30 31## Icon (glass .icon → .icns) 32``` 33./Scripts/build_icon.sh Icon.icon CodexBar 34``` 35Uses Xcode’s `ictool` + transparent padding + iconset → Icon.icns. 36 37## Build, sign, notarize (arm64) 38``` 39./Scripts/sign-and-notarize.sh 40``` 41What it does: 42- `swift build -c release --arch arm64` 43- Packages `CodexBar.app` with Info.plist and Icon.icns 44- Embeds Sparkle.framework, Updater, Autoupdate, XPCs 45- Codesigns **everything** with runtime + timestamp (deep) and adds rpath 46- Zips to `CodexBar-<version>.zip` 47- Submits to notarytool, waits, staples, validates 48 49Gotchas fixed: 50- Sparkle needs signing for framework, Autoupdate, Updater, XPCs (Downloader/Installer) or notarization fails. 51- Use `--timestamp` and `--deep` when signing the app to avoid invalid signature errors. 52- Avoid `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. 53- Manual sanity check before uploading: `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. 54 55## Appcast (Sparkle) 56After notarization: 57``` 58SPARKLE_PRIVATE_KEY_FILE=/path/to/ed25519-priv.key \ 59./Scripts/make_appcast.sh CodexBar-0.1.0.zip \ 60 https://raw.githubusercontent.com/steipete/CodexBar/main/appcast.xml 61``` 62Uploads not handled automatically—commit/publish appcast + zip to the feed location (GitHub Releases/raw URL). 63 64## Tag & release 65``` 66git tag v<version> 67./Scripts/make_appcast.sh ... 68# upload zip + appcast to Releases 69# then create GitHub release (gh release create v<version> ...) 70``` 71 72## Checklist (quick) 73- [ ] Read both this file and `~/Projects/agent-scripts/docs/RELEASING-MAC.md`; resolve any conflicts toward CodexBar’s specifics. 74- [ ] Update versions (scripts/Info.plist, CHANGELOG, About text) — changelog top section must be finalized; release script pulls notes from it automatically. 75- [ ] `swiftformat`, `swiftlint`, `swift test` (zero warnings/errors) 76- [ ] `./Scripts/build_icon.sh` if icon changed 77- [ ] `./Scripts/sign-and-notarize.sh` 78- [ ] Generate Sparkle appcast with private key 79 - Sparkle ed25519 private key path: `/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) 80 - Upload the dSYM archive alongside the app zip on the GitHub release; the release script now automates this and will fail if it’s missing. 81 - After publishing the release, run `Scripts/check-release-assets.sh <tag>` to confirm both the app zip and dSYM zip are present on GitHub. 82 - Sign the zip with `sign_update --ed-key-file "$SPARKLE_PRIVATE_KEY_FILE" CodexBar-<ver>.zip`; use that exact signature and length in the appcast (no manual base64 copy/paste). 83 - After generating the appcast, download the enclosure URL and re-run `sign_update --ed-key-file "$SPARKLE_PRIVATE_KEY_FILE" <downloaded.zip>`; abort if signature or length differs from the appcast. 84- [ ] Upload zip + appcast to feed; publish tag + GitHub release so Sparkle URL is live (avoid 404) 85- [ ] Version continuity: confirm the new version is the immediate next patch/minor (no gaps) and CHANGELOG has no skipped numbers (e.g., after 0.2.0 use 0.2.1, not 0.2.2) 86- [ ] Changelog sanity: single top-level title, no duplicate version sections, versions strictly descending with no repeats 87- [ ] Release pages: title format `CodexBar <version>`, notes as Markdown list (no stray blank lines) 88- [ ] Changelog/release notes are user-facing: avoid internal-only bullets (build numbers, script bumps) and keep entries concise 89- [ ] Download uploaded `CodexBar-<ver>.zip`, unzip via `ditto`, run, and verify signature (`spctl -a -t exec -vv CodexBar.app` + `stapler validate`) 90- [ ] Confirm `appcast.xml` points to the new zip/version and renders correct release notes 91- [ ] Verify on GitHub Releases: assets present (zip, appcast), release notes match changelog, version/tag correct 92- [ ] Open the appcast URL in browser to confirm the new entry is visible and enclosure URL is reachable 93- [ ] Manually visit the enclosure URL (curl -I) to ensure 200/OK (no 404) after publishing assets/release 94- [ ] Ensure `sparkle:edSignature` is present for the enclosure in appcast (generate with `sign_update`/ed25519 key) 95- [ ] When creating the GitHub release, paste the CHANGELOG entry as Markdown list (one `-` per line, blank line between sections); visually confirm bullets render correctly after publishing 96- [ ] Keep a previous signed build in `/Applications/CodexBar.app` to test Sparkle delta/full update to the new release 97- [ ] Manual Gatekeeper sanity: after packaging, `find CodexBar.app -name '._*'` is empty, `spctl --assess --type execute --verbose CodexBar.app` and `codesign --verify --deep --strict --verbose CodexBar.app` succeed 98- [ ] For Sparkle verification: if replacing `/Applications/CodexBar.app`, quit first, replace, relaunch, and test update 99- **Definition of “done” for a release:** all of the above are complete, the appcast/enclosure link resolves, and a previous public build can update to the new one via Sparkle. Anything short of that is not a finished release. 100 101## Troubleshooting 102- **White plate icon**: regenerate icns via `build_icon.sh` (ictool) to ensure transparent padding. 103- **Notarization invalid**: verify deep+timestamp signing, especially Sparkle’s Autoupdate/Updater and XPCs; rerun package + sign-and-notarize. 104- **App won’t launch**: ensure Sparkle.framework is embedded under `Contents/Frameworks` and rpath added; codesign deep. 105- **App “damaged” dialog after unzip**: re-extract with `ditto -x -k`, removing any `._*` files, then re-verify with `spctl`. 106- **Update download fails (404)**: ensure the release asset referenced in appcast exists and is published in the corresponding GitHub release; verify with `curl -I <enclosure-url>`.