Repository navigation
Sign releases with TAM's Developer ID and notarize them - #8
Conversation
Downloads open like any other app from the internet: no more trip to Privacy & Security to allow an ad hoc signed app. The packaging script signs with the Developer ID, the hardened runtime and a secure timestamp. It notarizes and staples the app, packages the stapled app, then signs, notarizes and staples the DMG. It stops unless Apple accepts both and the team, tickets and Gatekeeper's verdict check out, and nothing reaches dist/ before that. Without an identity it still makes ad hoc packages for local testing. The release workflow imports the certificate into a temporary keychain, lets Apple check the notarization credentials before building, and removes the keychain afterwards. Its secrets live in the release environment, which only v* tags and main may use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5ec608d3a5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - name: Build, sign, notarize and verify release packages | ||
| run: bash scripts/package-release.sh "$RELEASE_TAG" |
There was a problem hiding this comment.
Reject tags without the signing-aware packager
When a workflow-dispatch run targets a tag predating this commit, checkout at lines 49–52 replaces scripts/package-release.sh with that tag's ad-hoc-only version. The new credential setup still succeeds, but this step invokes the old script and the later publish step can make the resulting unnotarized artifacts public; this is especially reachable because docs/RELEASING.md explicitly recommends rerunning the workflow with an existing tag to resume a draft. Reject tags lacking the signing implementation or independently verify the produced app and DMG before publication.
Useful? React with 👍 / 👎.
| runs-on: macos-15 | ||
| timeout-minutes: 30 | ||
| # Notarization waits for Apple twice: once for the app, once for the disk image. | ||
| timeout-minutes: 60 |
There was a problem hiding this comment.
Leave headroom for both notarization waits
The packaging script performs two sequential notarization submissions, each allowed to wait up to 30 minutes, while this 60-minute job limit also includes checkout, dependency resolution, tests, compilation, signing, packaging, stapling, verification, and publishing. If Apple's two responses consume nearly their configured limits, GitHub terminates an otherwise successful release before it can publish; set the job timeout above the combined notarization limits plus build overhead.
Useful? React with 👍 / 👎.
Downloads now open like any other app from the internet: no more Privacy & Security → Open Anyway for an ad hoc signed app.
What changes
scripts/package-release.shsigns with the Developer ID, the hardened runtime and a secure timestamp. It notarizes and staples the app (so the ZIP's copy opens offline too), packages the stapled app, then signs, notarizes and staples the DMG. It stops unless Apple answersAcceptedand the team, stapled tickets and Gatekeeper's verdict check out. Packages are assembled outsidedist/, so a failed notarization leaves nothing to upload. WithoutSHEPHERDR_SIGN_IDENTITYit still makes ad hoc packages for local testing.release.ymlchecks that signing is configured before the tests run. It imports the.p12into a temporary keychain, picks the Developer ID identity ofAPPLE_TEAM_IDby hash, and has Apple check the notarization credentials before building. It deletes the keychain afterwards. The job uses thereleaseenvironment, which onlyv*tags andmainmay deploy to. The timeout is now 60 minutes, because notarization runs twice.RELEASING.mddocuments the secrets and how to set up a certificate.INSTALL.txt, the README, the guide and the release notes drop the Open Anyway instructions.Setup already done
67266UR7NA, issued from a CSR whose key stays in the maintainer's keychain.releaseenvironment holdsDEVELOPER_ID_P12_BASE64,DEVELOPER_ID_P12_PASSWORD,NOTARY_APPLE_ID,NOTARY_PASSWORDand the variableAPPLE_TEAM_ID. The.p12holds only that identity and was tested by importing it into a throwaway keychain.Verified
source=Notarized Developer ID, origin The Agile Monkeys SL (67266UR7NA), with stapled tickets, runtime flags and the microphone entitlement.🤖 Generated with Claude Code