Commit 46a9cd1
authored
ci(desktop): sign macOS releases and refuse unsigned tagged builds (#123)
## Related Issue
No issue — found while wiring up the first real macOS signing
credentials.
## Problem
Two gaps meant a remote release could never be properly signed:
1. **The API-key notarization path was unreachable in CI.** The job
exported only the Apple ID trio (`APPLE_ID` /
`APPLE_APP_SPECIFIC_PASSWORD` / `APPLE_TEAM_ID`). The App Store Connect
key is a *file*, so it cannot be passed as a plain secret string and had
no handling at all.
2. **A tagged release could ship unsigned and still go green.** With no
certificate secret the job set `CSC_IDENTITY_AUTO_DISCOVERY=false`,
printed `No macOS signing certificate configured; building unsigned.`
and exited zero. macOS refuses updates from an unsigned app, so that
publishes a release users cannot install or update from — while the
pipeline reports success.
## What changed
- Accept `APPLE_API_KEY_P8` as a base64 secret, decode it to
`$RUNNER_TEMP/AuthKey.p8` with mode 600, and export `APPLE_API_KEY` as
the path electron-builder and notarytool expect. Kept outside the
workspace so it cannot be swept into the packaged app.
- Also export `CSC_NAME`, which the signing preflight requires whenever
`CSC_LINK` supplies the certificate.
- Add a `Require signing for tagged releases` step that runs only on
`desktop-v*` tags and calls the existing `assertMacReleaseReady`
preflight through a small entry script. Manual `workflow_dispatch` runs
stay free to build unsigned for packaging checks.
The gate reuses the preflight rather than re-checking credentials, so CI
and local `dist:mac` cannot drift apart.
## Verification
The gate was exercised directly, all three paths:
```
no credentials -> exit 1: "macOS notarization credentials are required: set
APPLE_KEYCHAIN_PROFILE, the Apple ID trio, or the App Store
Connect API key trio"
p12 + API key -> exit 0: "signing via p12; notarization via api-key"
p12 without password -> exit 1: "CSC_KEY_PASSWORD is required when CSC_LINK
supplies a macOS signing certificate"
```
- Workflow YAML parses; the gate lands after credential resolution and
before packaging.
- `cd apps/desktop && npx vitest run` — 97 passed
- `pnpm --filter @pymodel/pythinker-desktop run typecheck` — clean
- `pnpm run lint` — no `: error ` lines
## Known limitation
The DMG produced remotely is signed (via `dmg.sign`) and its `.app` is
notarized and stapled, but **the DMG itself is not stapled in CI**.
Stapling mutates the file after electron-builder has hashed it for
`latest-mac.yml`, and the current job builds and publishes in one
`--publish always` invocation, so there is no point at which the DMG can
be stapled without invalidating the already-uploaded metadata. Doing it
properly requires splitting build from publish. Local `dist:mac` does
staple, because it controls that ordering. Left as follow-up rather than
half-done.
## Checklist
- [x] I have read the CONTRIBUTING document.
- [x] I have linked a related issue, or explained the problem above.
- [x] I have added tests that prove my feature works.
- [x] Ran `gen-changesets` skill, or this PR needs no changeset.
- [x] Ran `gen-docs` skill, or this PR needs no doc update.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved MCP server form alignment and spacing for clearer
configuration.
* Long fields now span the full form width, with responsive layout
support on smaller screens.
* Provider manager dialogs now maintain clean rounded corners without
content overflow.
* **Release Improvements**
* macOS releases now support signing and notarization through Apple API
credentials.
* Tagged macOS releases validate signing configuration and fail when
required credentials are unavailable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->1 parent 5f51b83 commit 46a9cd1
3 files changed
Lines changed: 57 additions & 2 deletions
File tree
- .changeset
- .github/workflows
- apps/desktop/scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
| 139 | + | |
139 | 140 | | |
140 | 141 | | |
141 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
142 | 146 | | |
143 | | - | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
144 | 152 | | |
145 | 153 | | |
146 | | - | |
| 154 | + | |
147 | 155 | | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
148 | 165 | | |
149 | 166 | | |
150 | 167 | | |
151 | 168 | | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
152 | 177 | | |
153 | 178 | | |
154 | 179 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
0 commit comments