|
| 1 | +--- |
| 2 | +name: openclaw-mac-release |
| 3 | +description: "Run or recover OpenClaw macOS release signing, notarization, appcast, and asset promotion." |
| 4 | +--- |
| 5 | + |
| 6 | +# OpenClaw Mac Release |
| 7 | + |
| 8 | +Use with `$openclaw-release-maintainer`, `$openclaw-release-ci`, and `$one-password` when stable macOS assets, private mac preflight, notarization, appcast promotion, or mac release recovery is involved. |
| 9 | + |
| 10 | +## Credentials |
| 11 | + |
| 12 | +- Canonical ASC item: vault `Molty`, title `API Key - App Store Connect - Personal - Release`. |
| 13 | +- Fields: `private_key_p8`, `key_id`, `issuer_id`. |
| 14 | +- Current known good key id: `AKVLXW849T`. |
| 15 | +- Legacy mirror: vault `Private`, title `API Key - App Store Connect - Personal`; keep it synced for older refs. |
| 16 | +- Stale/revoked key symptom: `xcrun notarytool submit` fails with `HTTP status code: 401. Unauthenticated`. |
| 17 | +- Validate candidate ASC credentials with `xcrun notarytool history` before setting GitHub secrets. |
| 18 | + |
| 19 | +## 1Password |
| 20 | + |
| 21 | +- Use `$one-password`: all `op` work inside one persistent tmux session, no secret output. |
| 22 | +- Prefer `OP_SERVICE_ACCOUNT_TOKEN` from `~/.profile` for Molty reads. |
| 23 | +- Do not assume `MOLTY_OP_SERVICE_ACCOUNT_TOKEN` is alive; it has previously pointed at a deleted service account. |
| 24 | +- If a service token fails, run status-only checks: token present/length and `op whoami`; never print token values. |
| 25 | +- If desktop app auth is needed but Touch ID is unavailable, set `OP_BIOMETRIC_UNLOCK_ENABLED=false` for the manual `op account add --signin` path. |
| 26 | + |
| 27 | +## GitHub Secrets |
| 28 | + |
| 29 | +Target private repo environment: `openclaw/releases-private`, env `mac-release`. |
| 30 | + |
| 31 | +Set only after local notary auth validation: |
| 32 | + |
| 33 | +- `APP_STORE_CONNECT_API_KEY_P8` |
| 34 | +- `APP_STORE_CONNECT_KEY_ID` |
| 35 | +- `APP_STORE_CONNECT_ISSUER_ID` |
| 36 | + |
| 37 | +Do not update these from mixed sources. All three ASC fields must come from the same 1Password item. |
| 38 | + |
| 39 | +## Workflow Shape |
| 40 | + |
| 41 | +- Public release branch may carry mac-only packaging fixes after the stable tag/npm are already live. |
| 42 | +- Use `source_ref=release/YYYY.M.D` for private mac preflight/validation when building that branch variation. |
| 43 | +- Keep `tag=vYYYY.M.D` pointing at the original stable release commit. |
| 44 | +- Real mac publish must reuse: |
| 45 | + - a successful private mac preflight run for the same tag/source SHA |
| 46 | + - a successful private mac validation run for the same tag/source SHA |
| 47 | +- If preflight source SHA differs from tag SHA, validation must also use the same `source_ref`; promotion rejects mismatched proof. |
| 48 | + |
| 49 | +## Notarization |
| 50 | + |
| 51 | +- OpenClaw uses `scripts/notarize-mac-artifact.sh`. |
| 52 | +- `xcrun notarytool submit` should use `--no-s3-acceleration`; accelerated upload can surface misleading 401s even when `notarytool history` succeeds. |
| 53 | +- If signing succeeds but notarization fails immediately with 401, check ASC key freshness first. |
| 54 | +- If notarization stays in progress for several minutes after key-file write, that is normal Apple wait time; do not edit blindly. |
| 55 | + |
| 56 | +## Dispatch |
| 57 | + |
| 58 | +Private preflight: |
| 59 | + |
| 60 | +```bash |
| 61 | +gh workflow run openclaw-macos-publish.yml --repo openclaw/releases-private --ref main \ |
| 62 | + -f tag=vYYYY.M.D \ |
| 63 | + -f source_ref=release/YYYY.M.D \ |
| 64 | + -f preflight_only=true \ |
| 65 | + -f smoke_test_only=false \ |
| 66 | + -f allow_late_calver_recovery=false \ |
| 67 | + -f public_release_branch=release/YYYY.M.D |
| 68 | +``` |
| 69 | + |
| 70 | +Private validation for a branch-variation preflight: |
| 71 | + |
| 72 | +```bash |
| 73 | +gh workflow run openclaw-macos-validate.yml --repo openclaw/releases-private --ref main \ |
| 74 | + -f tag=vYYYY.M.D \ |
| 75 | + -f source_ref=release/YYYY.M.D |
| 76 | +``` |
| 77 | + |
| 78 | +Real publish: |
| 79 | + |
| 80 | +```bash |
| 81 | +gh workflow run openclaw-macos-publish.yml --repo openclaw/releases-private --ref main \ |
| 82 | + -f tag=vYYYY.M.D \ |
| 83 | + -f preflight_only=false \ |
| 84 | + -f smoke_test_only=false \ |
| 85 | + -f preflight_run_id=<successful-preflight-run> \ |
| 86 | + -f validate_run_id=<successful-validation-run> \ |
| 87 | + -f allow_late_calver_recovery=false \ |
| 88 | + -f public_release_branch=release/YYYY.M.D |
| 89 | +``` |
| 90 | + |
| 91 | +## Verify |
| 92 | + |
| 93 | +- `gh release view vYYYY.M.D --repo openclaw/openclaw` shows zip, dmg, dSYM zip, not draft, not prerelease. |
| 94 | +- Public `main` `appcast.xml` points at `OpenClaw-YYYY.M.D.zip`. |
| 95 | +- Appcast entry has `sparkle:version`, `sparkle:shortVersionString`, length, and `sparkle:edSignature`. |
0 commit comments