Mac App Store以外でmacOSアプリを配布するには、アプリの署名、Appleの公証、自動アップデートの仕組みが必要になる。ここでは、Developer ID署名、公証(notarization)、Sparkleによる自動アップデートを組み合わせて、GitHub Releasesでアプリを配布するまでの手順を、各記事へのリンクとともにまとめる。
各記事の実行例は、Xcode 27.0、macOS 27.0.1、Sparkle 2.10.0のもの。GitHub Actionsのランナーには、Xcode 27.0が入ったxcode-27を使っている。
全体の流れ
アプリのビルドから、ユーザーのアプリが更新を検出するまでの流れは、次のとおりである。
graph TD
A[アーカイブしてエクスポート] --> B[Developer ID署名]
B --> C[公証に提出]
C --> D{公証の結果}
D -->|Invalid| E[ログで原因を調べて修正]
E --> B
D -->|Accepted| F[staple]
F --> G[配布用のzipを作成]
G --> H[appcast.xmlを生成]
H --> I[GitHub Releasesに公開]
I --> J[アプリが更新を検出]
GitHub Actionsのワークフローでは、タグをpushするだけで、アーカイブからGitHub Releasesへの公開までを自動で実行できる。
必要なもの
手順を始める前に、次のものを用意する。
- Apple Developer Programのアカウント(Developer ID証明書の作成は、Account Holderの権限が必要)
- Developer ID Applicationの証明書
- 公証に使うApple IDとApp用パスワード
- Sparkleの署名鍵(EdDSA)
- 公開リポジトリのGitHubリポジトリ(appcast.xmlとzipの配信先)
記事一覧
準備
- 【Developer ID】アプリ配布用の署名証明書を作成する
opensslでCSRを作り、Developer ID Applicationの証明書を発行して、キーチェーンに登録する。 - 【Xcode】公証のためにHardened Runtimeを有効にする 公証の必須要件であるHardened Runtimeを、XcodeのCapabilityで有効にする。
ビルドと署名
- 【xcodebuild】Developer ID署名でアーカイブしてエクスポートする
archiveと-exportArchiveで、Developer ID署名のアプリを作る。 - 【codesign】署名の内容と整合性を検証する
codesign -dvと--verifyで、署名とタイムスタンプ、内部のバイナリの署名を確認する。
公証
- 【notarytool】App用パスワードで公証用の認証情報を保存する
App用パスワードを発行して、
notarytool store-credentialsでキーチェーンに保存する。 - 【notarytool】アプリを公証してstaple(公証チケットを添付)する
zipを公証に提出し、
stapler stapleで公証チケットをアプリに添付する。 - 【notarytool】公証に失敗した理由をログから調べる
notarytool logで、Invalidになった理由と対処法を調べる。 - 【spctl】Gatekeeperの判定を配布前に確認する
spctl --assessと隔離属性で、配布先のMacでの動作を確認する。
Sparkle
- 【Sparkle】SwiftPMで導入してアプリに更新チェックを組み込む パッケージを追加し、更新確認のコードとInfo.plistの設定を書く。
- 【Sparkle】EdDSA署名鍵を生成して公開鍵をInfo.plistに設定する
generate_keysで署名鍵を生成し、公開鍵を設定する。 - 【Sparkle】generate_appcastでappcast.xmlを作る zipからappcast.xmlと差分更新のファイルを生成する。
- 【Sparkle】ビルド番号とバージョン番号を使い分ける 更新の判定に使うビルド番号と、バージョン番号の比較の挙動を調べる。
配信
- 【GitHub Releases】appcast.xmlを固定URLで配信する
releases/latest/download/で、appcast.xmlを固定のURLで配信する。
GitHub Actions
- 【GitHub Actions】一時keychainに証明書をインポートして署名する
.p12をSecretsに登録し、ランナーのキーチェーンにインポートする。 - 【GitHub Actions】CIでだけ署名設定をDeveloper IDに切り替える
xcodebuildの引数で、CIだけ署名の設定を上書きする。 - 【GitHub Actions】タグpushで公証からRelease作成まで自動化する 署名、公証、appcast.xmlの更新、Releaseの作成までを、1つのワークフローにまとめる。
仕上げ
- 【Sparkle】古いバージョンから更新できることを動作確認する 古いバージョンのアプリで、新しいバージョンへの更新を実際に確認する。
つまずきやすい点
つまずきやすい点を、記事の順にまとめる。詳細は、記事一覧の各記事で解説している。
- Developer ID証明書の作成画面では、Sub-CAの既定が「Previous Sub-CA」で、2027年2月に失効する。「G2 Sub-CA」を選ぶ
- Homebrewの
openssl(OpenSSL 3)で作った.p12は、security importで失敗する - App用パスワードのラベルに、括弧などの記号は使えない
notarytool submit --waitは、公証がInvalidでも終了コードが0である- 公証していないコピーも、同じ署名であれば、公証済みと判定される
- キーチェーンに
ed25519の鍵があると、generate_keysは新しい鍵を作らず、既存の鍵を使う - ビルド番号のハイフン以降は、比較に使われない
- 過去のappcast.xmlは、
generate_appcastの対象のディレクトリに置かないと、引き継がれない - リリースの作成から
latest/download/への反映まで、時間を要する場合がある
この記事群で扱わないこと
次の内容は、この記事群では扱っていない。
- Mac App Storeでの配布
.pkgインストーラや.dmgでの配布- App Store Connect APIキーによる公証の認証
- App Sandboxを有効にしたアプリでのSparkleの設定
\第一線のプログラマーの行動原理を学べる!/
