Skip to content

CI: Apple code signing + notarization for proper DMG builds #19

@Weegy

Description

@Weegy

Problem

The release pipeline (.github/workflows/release.yml) builds macOS DMG + zip artifacts without a real signing identity:

  • app/electron-builder.yml sets identity: null and relies on the afterPack ad-hoc signing hook (app/tools/adhocSign.cjs) as a stopgap.
  • Ad-hoc signed downloads fail soft: Gatekeeper shows the "unverified developer" dialog on every fresh install.
  • macOS auto-update via electron-updater is blocked entirely — Squirrel.Mac rejects builds that are not signed + notarized.

This was a deliberate deferral ("Until GA signing lands…" in electron-builder.yml); this issue tracks landing it.

Goal

The release workflow produces properly signed, notarized, and stapled DMG (and zip) artifacts using the high5 Developer ID Application certificate, so downloads open without Gatekeeper warnings and the future auto-update path is unblocked.

The approach is already fully specified in docs/implementation-plan.md §7 ("Distribution + signing pipeline") and references/apple_dev.md (credential identifiers and gotchas — kept out of this issue intentionally).

Tasks

  • Add GitHub Actions secrets per the apple_dev.md CI naming convention (use the _HIGH5 suffix so a future _BYTE5 set drops in cleanly): APPLE_CERTIFICATE_P12_BASE64, APPLE_CERTIFICATE_PASSWORD, the ASC API key trio (preferred for CI) or APPLE_ID + APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID, KEYCHAIN_PASSWORD (random per run)
  • Extend the macOS leg of the build job in release.yml: create a temporary keychain from the base64 cert, import it, build + sign in one electron-builder pass, tear the keychain down afterwards
  • electron-builder.yml: replace identity: null with the real identity, enable hardenedRuntime, add an entitlements plist — the plist must contain no XML comments (Apple's AMFIUnserializeXML rejects them while plutil accepts them silently; documented gotcha in apple_dev.md)
  • Notarize via xcrun notarytool submit … --wait using the ASC API key, then xcrun stapler staple the .app and .dmg
  • Confirm adhocSign.cjs no-ops once a real identity is used (it should — verify, then keep or remove it)
  • Verify the uploaded artifacts (see acceptance criteria)

Acceptance criteria

  • codesign --verify --deep --strict passes on the .app with the Developer ID identity (not ad-hoc)
  • spctl -a -vv -t install accepts the DMG
  • xcrun stapler validate passes on the stapled .app/.dmg
  • A freshly downloaded DMG from the GitHub release opens on a clean macOS machine without any Gatekeeper dialog
  • Both arches (arm64 + x64) are signed and notarized
  • No credential material appears in workflow logs (keychain torn down, secrets masked)

Out of scope

  • byte5-branded signing — post-GA, user-elected identity swap only (implementation-plan.md §7)
  • electron-updater feed wiring — separate concern; this issue only removes its signing blocker

References

  • docs/implementation-plan.md §7 — Distribution + signing pipeline
  • references/apple_dev.md — credentials, identifiers, CI secret naming, gotchas
  • app/electron-builder.yml — current identity: null stopgap
  • app/tools/adhocSign.cjs — ad-hoc signing hook to be superseded
  • .github/workflows/release.yml — build job to extend

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions