Skip to content

Feature: Sign and notarize release installers #2

Description

@jordancalhoun

Summary

Publish Developer ID-signed and Apple-notarized swiftpkg installer releases instead of the current unsigned .pkg artifacts.

Why

The release workflow currently invokes UNSIGNED=1 ./scripts/release.sh, and the README describes the installer as unsigned. Signed and notarized releases provide a normal Gatekeeper installation experience and are a prerequisite for distributing the official installer through Homebrew Cask.

Proposed work

  • Obtain and protect a Developer ID Application certificate, a Developer ID Installer certificate, and an App Store Connect API key or a notarytool keychain profile.
  • Decide on a trusted release runner:
    • Preferred: a self-hosted, access-controlled macOS runner with the certificates and notary profile installed in its keychain.
    • Alternative: import encrypted/base64 certificate material into a temporary GitHub Actions keychain and configure notarytool with App Store Connect credentials from GitHub Actions secrets.
  • Change the tag-release workflow to run the existing signed path in scripts/release.sh, supplying APP_SIGN_IDENTITY, INSTALLER_SIGN_IDENTITY, and NOTARY_PROFILE; remove UNSIGNED=1 for production tags.
  • Keep the current unsigned path only for explicitly non-production or local testing, if still useful.
  • Ensure the workflow uploads the notarized .pkg and SHA256SUMS to the matching GitHub Release.
  • Update the README to remove the unsigned/Gatekeeper-override guidance once signed releases are live.

Workflow shape

- name: Build, sign, notarize, and publish release
  env:
    APP_SIGN_IDENTITY: ${{ secrets.APP_SIGN_IDENTITY }}
    INSTALLER_SIGN_IDENTITY: ${{ secrets.INSTALLER_SIGN_IDENTITY }}
    NOTARY_PROFILE: swiftpkg-notary
    GH_PUBLISH: "1"
    GITHUB_REPOSITORY: ${{ github.repository }}
    GH_TOKEN: ${{ github.token }}
  run: ./scripts/release.sh

On GitHub-hosted runners, add setup steps before this job to import the Developer ID certificates into a temporary keychain and create the notarytool keychain profile from protected App Store Connect API-key secrets. Do not print certificate passwords, API keys, or profile material in logs.

Acceptance criteria

  • A pushed v<version> tag produces a Universal 2 swiftpkg-<version>-universal.pkg signed with the project Developer ID Installer identity.
  • The embedded executable is signed with the Developer ID Application identity, hardened runtime, and timestamp.
  • The installer is accepted by Apple notarization and stapled.
  • Release verification runs and passes codesign --verify --strict, pkgutil --check-signature, xcrun stapler validate, and spctl --assess --type install.
  • The GitHub Release contains the notarized installer and a matching SHA-256 checksum.
  • The public install documentation accurately describes the signing and notarization status.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions