feat(release): notarize the macOS binary - #1378
Conversation
usage was the last jdx.dev CLI signing its macOS binary without notarizing it. A signature settles who built the binary; notarization is what Gatekeeper demands once a download carries the quarantine bit, which is to say whenever someone fetches an archive in a browser rather than with curl. Without a ticket it sits behind the "cannot be verified" dialog that only a deliberate override gets past. `codesign_options: runtime` is the half the action can supply — Apple rejects a submission without the hardened runtime. The secure timestamp it also requires is codesign's own default for a Developer ID identity. Nothing is stapled: the ticket is keyed to the binary's cdhash and lives on Apple's side, so this rewrites neither the archive nor the uploaded asset. `stapler` writes only into bundles, disk images, and installer packages, and this is a bare Mach-O in an archive; Gatekeeper resolves the ticket online. The step matches hk's, including its behaviour when App Store Connect credentials are absent: warn that the release ships un-notarized and carry on, rather than failing the build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Entire-Checkpoint: 01M1QDXPJ6F41KCH69ZNHZBAMW
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughThe macOS release workflow now enables hardened-runtime signing and adds optional Apple notarization. It stages and inspects binaries, submits them with ChangesmacOS notarization
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: 🟡 Moderate · up to A macOS binary may be uploaded before Apple accepts its notarization, potentially leaving a rejected artifact attached to the release. The upload should be delayed until acceptance or failed uploads should be reliably removed before merge. Sequence Diagram(s)sequenceDiagram
participant GitHubActions
participant upload-rust-binary-action
participant xcrunNotarytool
participant AppleNotaryService
GitHubActions->>upload-rust-binary-action: Build and sign macOS binary with hardened runtime
GitHubActions->>GitHubActions: Decode credentials and stage binary
GitHubActions->>xcrunNotarytool: Submit zipped binary
xcrunNotarytool->>AppleNotaryService: Request notarization and wait
AppleNotaryService-->>xcrunNotarytool: Return status and submission id
xcrunNotarytool-->>GitHubActions: Return JSON result
GitHubActions->>xcrunNotarytool: Fetch log if status is not Accepted
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
usage is the last jdx.dev CLI that signs its macOS binary without notarizing
it. mise, hk, fnox, pitchfork, and packslip all submit to
notarytool; thisbrings usage in line.
A signature settles who built the binary. Notarization is what Gatekeeper
demands once a download carries the quarantine bit — whenever someone fetches
an archive through a browser rather than with curl. Without a ticket the
binary sits behind the "cannot be verified" dialog that only a deliberate
override gets past.
Two changes:
codesign_options: runtimeon the existingupload-rust-binary-actionstep. Apple rejects a submission signed without the hardened runtime, and
that input is the only part of the signature the action exposes. The secure
timestamp Apple also requires is
codesign's own default for a Developer IDidentity, so it needs no flag.
universal-apple-darwinbinary andrequires an
Acceptedverdict.--waitis not a gate on its own — it canreturn zero on an
Invalidsubmission — so the reported status is whatdecides, and the notary log is dumped before failing.
Nothing is stapled. The ticket is keyed to the binary's cdhash and lives on
Apple's side, so this rewrites neither the archive nor the uploaded asset;
stapleronly writes into bundles, disk images, and installer packages, andthis is a bare Mach-O in an archive. Gatekeeper resolves the ticket online.
Secrets
This repository has
APPLE_DEVELOPER_ID_APPLICATION_CERTS_P12and itspassword, but none of the App Store Connect credentials the other repos got on
2026-08-26. Three are needed, and they are the same values already in
jdx/mise,jdx/hk,jdx/fnox, andjdx/pitchfork:APPLE_API_KEY_P8— the base64-encoded.p8APPLE_API_KEY_IDAPPLE_API_ISSUER_IDThe step follows hk's behaviour when they are missing: it warns that the
release ships signed but un-notarized and carries on, rather than failing the
build. So this is safe to merge before the secrets are added — releases keep
working, and the warning is visible in the job log until they land.
AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5; version: 2.1.176.
🤖 Generated with Claude Code
Note
Low Risk
Changes are confined to the macOS CI release workflow; missing API secrets only warn, though configured credentials make notarization failure block the macOS publish job.
Overview
Adds Apple notarization to the
publish-climacOS release path so browser downloads pass Gatekeeper, matching the other jdx.dev CLIs.The existing
upload-rust-binary-actionstep now setscodesign_options: runtime(required for notarization). A new Notarize macOS binary job runs only onmacos-latest: it stages the builtusagebinary, zips it fornotarytool, checks for hardened runtime and secure timestamp (workflow warnings only), submits with App Store Connect API secrets, and fails the job unless Apple returnsAccepted(with notary logs on failure). API key material is decoded in a temp directory and removed on exit.If
APPLE_API_KEY_*secrets are missing, the step emits a workflow warning and skips notarization so signed-but-un-notarized releases can still ship until credentials are added. No stapling — Gatekeeper is expected to validate the online ticket for the shipped Mach-O.Reviewed by Cursor Bugbot for commit 4829238. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit