Skip to content

Prepare Developer ID signing and notarization for macOS - #188

Merged
Gorka Gonzalo (d0ubl3g) merged 1 commit into
devfrom
feat/macos-signing-prep
Oct 15, 2026
Merged

Gorka Gonzalo (d0ubl3g) merged 1 commit into
devfrom
feat/macos-signing-prep

Conversation

@d0ubl3g

Copy link
Copy Markdown
Contributor

Refs #50

Release workflow

  • Variable off (MACOS_SIGNING_ENABLED not true, or a manual dry run): the macOS job writes macOS signing: skipped — MACOS_SIGNING_ENABLED is not true; the binary is not Developer ID signed or notarized. to the run summary and emits a ::notice::. Nothing else changes.
  • Variable on: same import, sign, notarize and package steps as before, plus checks that fail the job:
    • after signing: codesign --verify --strict, and codesign -dvv must show the Developer ID Application authority, a TeamIdentifier, the hardened runtime and a timestamp;
    • after notarization: spctl --assess --type execute must report source=Notarized Developer ID for the binary (retried briefly, since the ticket is looked up online), and the package must show a Developer ID Installer signature, pass stapler validate and spctl --assess --type install;
    • the run summary states signed and notarized with the Team ID. No secret is printed.
  • The "secret is missing" fail-closed check is unchanged.

macOS signing check (new, workflow_dispatch only)

Bound to the release-signing environment, so it needs the same approval. It builds a tiny universal executable, then runs import, codesign, notarize and verify on it and on a throwaway .pkg, deletes the temporary keychain always, and uploads nothing. If any of the nine secrets is absent it fails and lists the missing names in the step summary; it never skips.

The signing steps are kept inline in both workflows rather than moved to a script: the sign-macos job deliberately checks nothing out and runs no repository code, and a shared script would need a checkout in the job that holds the keys. Both files carry a comment to keep them in step.

Note for enabling: the release-signing environment accepts deployments from v* tags only, so running the check needs main added to its allowed branches temporarily (documented).

Docs and changelog

docs/release-signing.md (identities, secret names, who may change them, enabling steps, compromise procedure), docs/verifying-releases.md (macOS verification, applies from the first Developer ID signed release), CHANGELOG entry.

I could not run actionlint or zizmor locally; shellcheck over every new or changed run block is clean. workflow-lint will run on this PR.

The release workflow already holds the macOS signing steps behind the
MACOS_SIGNING_ENABLED variable. This makes them safe to switch on:

- When signing is off, the macOS job says so in the run summary and as
  a notice, so a skip cannot be read as a pass.
- When signing is on, the job checks the Developer ID Application
  authority, the Team ID, the hardened runtime and the timestamp after
  signing, and asserts that Gatekeeper reports the binary as Notarized
  Developer ID and that the package is signed, stapled and accepted. It
  writes the result to the run summary.
- A new on-demand "macOS signing check" workflow, bound to the
  release-signing environment, runs the same chain on a throwaway
  executable and package. It fails and lists the names of any missing
  secret.
- docs/release-signing.md describes the identities, the secrets, who may
  change them and what to do if they are compromised;
  docs/verifying-releases.md explains how to verify the signatures.

The signing steps stay inline in both workflows: the signing job checks
nothing out and runs no repository code, and a shared script would
break that.

Refs #50

Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com>
@d0ubl3g
Gorka Gonzalo (d0ubl3g) merged commit fa8cce2 into dev Oct 15, 2026
22 checks passed
@d0ubl3g
Gorka Gonzalo (d0ubl3g) deleted the feat/macos-signing-prep branch October 15, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant