|
| 1 | +# Release Guide |
| 2 | + |
| 3 | +This document covers building and releasing CF Cache Status for distribution. |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +1. **Apple Developer Account** ($99/year) with: |
| 8 | + - Developer ID Application certificate (for direct distribution) |
| 9 | + - Apple Distribution certificate (for App Store) |
| 10 | + |
| 11 | +2. **Environment variables** in `.env`: |
| 12 | + |
| 13 | + ```bash |
| 14 | + cp .env.example .env |
| 15 | + ``` |
| 16 | + |
| 17 | + | Variable | Description | |
| 18 | + | -------------------- | --------------------------------------------------------------------------- | |
| 19 | + | `APPLE_ID` | Your Apple ID email | |
| 20 | + | `APPLE_TEAM_ID` | 10-character Team ID from [developer.apple.com](https://developer.apple.com/account) | |
| 21 | + | `APPLE_APP_PASSWORD` | App-specific password from [appleid.apple.com](https://appleid.apple.com) | |
| 22 | + |
| 23 | +3. **Xcode** configured with your signing certificates |
| 24 | + |
| 25 | +## Distribution Options |
| 26 | + |
| 27 | +There are two separate release pipelines: |
| 28 | + |
| 29 | +| Channel | Certificate | Output | Use Case | |
| 30 | +| -------------- | ------------------------ | ----------------- | --------------------------- | |
| 31 | +| **Direct** | Developer ID Application | Notarized `.zip` | GitHub releases, website | |
| 32 | +| **App Store** | Apple Distribution | `.pkg` upload | Mac App Store | |
| 33 | + |
| 34 | +Both can be built for the same version — they're stored in separate directories. |
| 35 | + |
| 36 | +--- |
| 37 | + |
| 38 | +## Direct Distribution (GitHub) |
| 39 | + |
| 40 | +For distributing outside the App Store. Requires notarization for Gatekeeper. |
| 41 | + |
| 42 | +### Full Pipeline |
| 43 | + |
| 44 | +```bash |
| 45 | +just release v0.0.6 |
| 46 | +``` |
| 47 | + |
| 48 | +This runs: archive → submit → wait → staple |
| 49 | + |
| 50 | +### Step-by-Step |
| 51 | + |
| 52 | +```bash |
| 53 | +# 1. Build and sign with Developer ID |
| 54 | +just archive v0.0.6 |
| 55 | + |
| 56 | +# 2. Submit for notarization |
| 57 | +just submit |
| 58 | + |
| 59 | +# 3. Check status (optional, non-blocking) |
| 60 | +just status |
| 61 | + |
| 62 | +# 4. Wait for Apple to process (can take minutes to hours) |
| 63 | +just wait |
| 64 | + |
| 65 | +# 5. Staple notarization ticket and create final zip |
| 66 | +just staple |
| 67 | +``` |
| 68 | + |
| 69 | +### Output |
| 70 | + |
| 71 | +``` |
| 72 | +build/ |
| 73 | +└── v0.0.6/ |
| 74 | + ├── CacheStatus.xcarchive # Xcode archive |
| 75 | + ├── CF Cache Status.app # Signed app |
| 76 | + ├── CF.Cache.Status.v0.0.6.zip # Final notarized release |
| 77 | + └── .submission_id # Notarization tracking |
| 78 | +``` |
| 79 | + |
| 80 | +### Utility Commands |
| 81 | + |
| 82 | +```bash |
| 83 | +just history # Show notarization history |
| 84 | +just log <id> # Get notarization log for a submission |
| 85 | +just builds # List available builds |
| 86 | +``` |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +## App Store Distribution |
| 91 | + |
| 92 | +For publishing on the Mac App Store. |
| 93 | + |
| 94 | +### Full Pipeline |
| 95 | + |
| 96 | +```bash |
| 97 | +just release-appstore v0.0.6 |
| 98 | +``` |
| 99 | + |
| 100 | +This runs: archive-appstore → upload-appstore (with validation) |
| 101 | + |
| 102 | +### Step-by-Step |
| 103 | + |
| 104 | +```bash |
| 105 | +# 1. Build and sign with Apple Distribution |
| 106 | +just archive-appstore v0.0.6 |
| 107 | + |
| 108 | +# 2. Validate package (optional, upload does this automatically) |
| 109 | +just validate-appstore |
| 110 | + |
| 111 | +# 3. Upload to App Store Connect |
| 112 | +just upload-appstore |
| 113 | +``` |
| 114 | + |
| 115 | +### Output |
| 116 | + |
| 117 | +``` |
| 118 | +build/ |
| 119 | +└── v0.0.6-appstore/ |
| 120 | + ├── CacheStatus.xcarchive # Xcode archive |
| 121 | + ├── ExportOptions.plist # Export configuration |
| 122 | + └── export/ |
| 123 | + └── CF Cache Status.pkg # App Store package |
| 124 | +``` |
| 125 | + |
| 126 | +### App Store Connect API (Optional) |
| 127 | + |
| 128 | +For automated uploads, you can use API keys instead of Apple ID: |
| 129 | + |
| 130 | +| Variable | Description | |
| 131 | +| ------------------------- | ------------------------------------ | |
| 132 | +| `APPSTORE_API_KEY_ID` | Key ID from App Store Connect | |
| 133 | +| `APPSTORE_API_ISSUER_ID` | Issuer ID from App Store Connect | |
| 134 | +| `APPSTORE_API_KEY_PATH` | Path to `.p8` private key file | |
| 135 | + |
| 136 | +Generate keys at: App Store Connect → Users and Access → Keys |
| 137 | + |
| 138 | +--- |
| 139 | + |
| 140 | +## Building Both |
| 141 | + |
| 142 | +You can build both versions for the same release: |
| 143 | + |
| 144 | +```bash |
| 145 | +# Direct distribution (for GitHub) |
| 146 | +just release v0.0.6 |
| 147 | + |
| 148 | +# App Store (for Mac App Store) |
| 149 | +just release-appstore v0.0.6 |
| 150 | +``` |
| 151 | + |
| 152 | +They don't conflict — outputs go to separate directories: |
| 153 | +- `build/v0.0.6/` — Developer ID build |
| 154 | +- `build/v0.0.6-appstore/` — App Store build |
| 155 | + |
| 156 | +--- |
| 157 | + |
| 158 | +## Troubleshooting |
| 159 | + |
| 160 | +### Notarization Stuck "In Progress" |
| 161 | + |
| 162 | +Apple's notarization service can sometimes take hours. Check status with: |
| 163 | + |
| 164 | +```bash |
| 165 | +just status |
| 166 | +just history |
| 167 | +``` |
| 168 | + |
| 169 | +### Notarization Failed |
| 170 | + |
| 171 | +Get the detailed log: |
| 172 | + |
| 173 | +```bash |
| 174 | +just log <submission-id> |
| 175 | +``` |
| 176 | + |
| 177 | +Common issues: |
| 178 | +- Missing entitlements |
| 179 | +- Hardened runtime not enabled |
| 180 | +- Unsigned frameworks/binaries |
| 181 | + |
| 182 | +### App Store Validation Failed |
| 183 | + |
| 184 | +The upload script validates before uploading. Common issues: |
| 185 | +- Missing provisioning profile |
| 186 | +- Bundle ID mismatch |
| 187 | +- Version/build number conflicts |
| 188 | + |
| 189 | +### Certificate Issues |
| 190 | + |
| 191 | +Verify your certificates in Keychain Access: |
| 192 | +- **Developer ID Application** — for direct distribution |
| 193 | +- **Apple Distribution** — for App Store |
| 194 | + |
| 195 | +Both require the private key to be present. |
| 196 | + |
| 197 | +--- |
| 198 | + |
| 199 | +## Version Checklist |
| 200 | + |
| 201 | +Before releasing a new version: |
| 202 | + |
| 203 | +1. [ ] Update version in Xcode (both targets) |
| 204 | +2. [ ] Update `CHANGELOG.md` |
| 205 | +3. [ ] Create git tag: `git tag v0.0.X` |
| 206 | +4. [ ] Push tag: `git push origin v0.0.X` |
| 207 | +5. [ ] Build releases: |
| 208 | + - [ ] `just release v0.0.X` (direct) |
| 209 | + - [ ] `just release-appstore v0.0.X` (App Store) |
| 210 | +6. [ ] Create GitHub release with the `.zip` file |
| 211 | +7. [ ] Submit App Store version in App Store Connect |
0 commit comments