Skip to content

Commit ce11aba

Browse files
committed
feat: add Sparkle auto update release flow
1 parent 7ab7821 commit ce11aba

12 files changed

Lines changed: 512 additions & 7 deletions

File tree

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,10 @@ DerivedData/
2121
*.xcodeproj/*
2222
!*.xcodeproj/project.pbxproj
2323
!*.xcodeproj/xcshareddata/
24+
!azooKeyMac.xcodeproj/project.xcworkspace/
25+
azooKeyMac.xcodeproj/project.xcworkspace/*
26+
!azooKeyMac.xcodeproj/project.xcworkspace/xcshareddata/
27+
!azooKeyMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/
28+
!azooKeyMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
2429
**/xcshareddata/WorkspaceSettings.xcsettings
2530
!*.xcworkspace/contents.xcworkspacedata

README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,33 @@ ls -lh azooKeyMac/Resources/zenz-v3.1-small-gguf/ggml-model-Q5_K_M.gguf
124124
* Git LFSが導入されていない環境では、重みファイルがローカル環境に落とせていない場合があります。`azooKeyMac/Resources/zenz-v3.1-small-gguf/ggml-model-Q5_K_M.gguf` が数十MB以上あるかを確認し、ポインタのままであれば `git -C azooKeyMac/Resources/zenz-v3.1-small-gguf lfs pull` を実行してください
125125

126126
### pkgファイルの作成
127-
`pkgbuild.sh`によって配布用のdmgファイルを作成できます。`build/azooKeyMac.app` としてDeveloper IDで署名済みの.appを配置してください。
127+
`pkgbuild.sh`によって配布用のpkgファイルを作成できます。作成された `azooKey-release-signed.pkg` は初回インストールと上書きインストールの両方で利用します。
128+
129+
自動アップデートはSparkle経由のpkg更新として配布します。リリースビルドではSparkleの `generate_keys` で作成した公開鍵を `SPARKLE_PUBLIC_ED_KEY` に設定してください。
130+
131+
初回のみ、SparkleのEdDSA鍵を生成します。`generate_keys` は秘密鍵を実行したMacのlogin Keychainに保存し、アプリへ埋め込む公開鍵を出力します。秘密鍵はGitHubやリポジトリに置かないでください。
132+
133+
```sh
134+
xcodebuild -resolvePackageDependencies \
135+
-project azooKeyMac.xcodeproj \
136+
-scheme azooKeyMac \
137+
-clonedSourcePackagesDirPath ./build/source-packages
138+
139+
./build/source-packages/artifacts/sparkle/Sparkle/bin/generate_keys
140+
```
141+
142+
出力された `SUPublicEDKey` の文字列を、以後のrelease時に `SPARKLE_PUBLIC_ED_KEY` として渡します。
143+
144+
GitHub Releaseの作成は `create_release.sh` で行います。このスクリプトは実行中のcommitにtagを打ち、`pkgbuild.sh` を実行し、`azooKey-release-signed.pkg``appcast.xml` をGitHub Releaseへアップロードします。release前に `CURRENT_PROJECT_VERSION` を増やしてください。
145+
146+
```sh
147+
SPARKLE_PUBLIC_ED_KEY="..." ./create_release.sh --stable-release
148+
SPARKLE_PUBLIC_ED_KEY="..." ./create_release.sh --pre-release
149+
```
150+
151+
stable releaseのtagは標準で `vMARKETING_VERSION`、pre-releaseのtagは `vMARKETING_VERSION-pre.CURRENT_PROJECT_VERSION` になります。必要な場合は `--tag``--repo``--remote` で上書きできます。
152+
153+
pkg更新後、postinstallはConverterServerのLaunchAgentを再登録してConverterServerだけを再起動します。既に起動しているazooKeyMacクライアントは終了せず、クライアント側の更新は次回ログイン後に反映されます。
128154

129155
### v1.0リリースに向けて
130156
[meta: v1.0のリリースに向けたロードマップ(#181](https://github.com/azooKey/azooKey-Desktop/issues/181)をご覧ください.

azooKeyMac.xcodeproj/project.pbxproj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
551434E82D576B6600A9B5CA /* lm_c_abc.marisa in Resources */ = {isa = PBXBuildFile; fileRef = 551434E12D576B6600A9B5CA /* lm_c_abc.marisa */; };
1717
551434EA2D57A8AC00A9B5CA /* ggml-model-Q5_K_M.gguf in Resources */ = {isa = PBXBuildFile; fileRef = 551434E92D57A8AC00A9B5CA /* ggml-model-Q5_K_M.gguf */; };
1818
554A26602DB37657003C5CFB /* Core in Frameworks */ = {isa = PBXBuildFile; productRef = 554A265F2DB37657003C5CFB /* Core */; };
19+
556B9A102EFD000000000001 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 556B9A0F2EFD000000000001 /* Sparkle */; };
1920
556C52FB2BAAAF7E00EB343F /* en.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 556C52F92BAAAF7D00EB343F /* en.tiff */; };
2021
556C52FC2BAAAF7E00EB343F /* en@2x.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 556C52FA2BAAAF7D00EB343F /* en@2x.tiff */; };
2122
55A27D022BAAADDB00512DCD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 55A27D002BAAADDB00512DCD /* InfoPlist.strings */; };
@@ -75,6 +76,7 @@
7576
buildActionMask = 2147483647;
7677
files = (
7778
554A26602DB37657003C5CFB /* Core in Frameworks */,
79+
556B9A102EFD000000000001 /* Sparkle in Frameworks */,
7880
);
7981
runOnlyForDeploymentPostprocessing = 0;
8082
};
@@ -175,6 +177,7 @@
175177
name = azooKeyMac;
176178
packageProductDependencies = (
177179
554A265F2DB37657003C5CFB /* Core */,
180+
556B9A0F2EFD000000000001 /* Sparkle */,
178181
);
179182
productName = azooKeyMac;
180183
productReference = 1A41E61426E745D9009B65D7 /* azooKeyMac.app */;
@@ -256,6 +259,7 @@
256259
mainGroup = 1A41E60B26E745D9009B65D7;
257260
packageReferences = (
258261
554A265E2DB37657003C5CFB /* XCLocalSwiftPackageReference "Core" */,
262+
556B9A0E2EFD000000000001 /* XCRemoteSwiftPackageReference "Sparkle" */,
259263
);
260264
productRefGroup = 1A41E61526E745D9009B65D7 /* Products */;
261265
projectDirPath = "";
@@ -530,6 +534,8 @@
530534
MARKETING_VERSION = 1.0;
531535
PRODUCT_BUNDLE_IDENTIFIER = dev.ensan.inputmethod.azooKeyMac;
532536
PRODUCT_NAME = "$(TARGET_NAME)";
537+
SPARKLE_FEED_URL = "https://github.com/azooKey/azooKey-Desktop/releases/latest/download/appcast.xml";
538+
SPARKLE_PUBLIC_ED_KEY = "";
533539
SWIFT_EMIT_LOC_STRINGS = YES;
534540
SWIFT_OBJC_INTEROP_MODE = objcxx;
535541
SWIFT_VERSION = 5.0;
@@ -566,6 +572,8 @@
566572
MARKETING_VERSION = 1.0;
567573
PRODUCT_BUNDLE_IDENTIFIER = dev.ensan.inputmethod.azooKeyMac;
568574
PRODUCT_NAME = "$(TARGET_NAME)";
575+
SPARKLE_FEED_URL = "https://github.com/azooKey/azooKey-Desktop/releases/latest/download/appcast.xml";
576+
SPARKLE_PUBLIC_ED_KEY = "";
569577
SWIFT_EMIT_LOC_STRINGS = YES;
570578
SWIFT_OBJC_INTEROP_MODE = objcxx;
571579
SWIFT_VERSION = 5.0;
@@ -712,6 +720,17 @@
712720
};
713721
/* End XCLocalSwiftPackageReference section */
714722

723+
/* Begin XCRemoteSwiftPackageReference section */
724+
556B9A0E2EFD000000000001 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
725+
isa = XCRemoteSwiftPackageReference;
726+
repositoryURL = "https://github.com/sparkle-project/Sparkle";
727+
requirement = {
728+
kind = upToNextMajorVersion;
729+
minimumVersion = 2.9.3;
730+
};
731+
};
732+
/* End XCRemoteSwiftPackageReference section */
733+
715734
/* Begin XCSwiftPackageProductDependency section */
716735
554A265F2DB37657003C5CFB /* Core */ = {
717736
isa = XCSwiftPackageProductDependency;
@@ -722,6 +741,11 @@
722741
package = 554A265E2DB37657003C5CFB /* XCLocalSwiftPackageReference "Core" */;
723742
productName = Core;
724743
};
744+
556B9A0F2EFD000000000001 /* Sparkle */ = {
745+
isa = XCSwiftPackageProductDependency;
746+
package = 556B9A0E2EFD000000000001 /* XCRemoteSwiftPackageReference "Sparkle" */;
747+
productName = Sparkle;
748+
};
725749
/* End XCSwiftPackageProductDependency section */
726750
};
727751
rootObject = 1A41E60C26E745D9009B65D7 /* Project object */;

azooKeyMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 104 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

azooKeyMac/AppDelegate.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Cocoa
99
import Core
1010
import InputMethodKit
1111
import KanaKanjiConverterModuleWithDefaultDictionary
12+
import Sparkle
1213
import SwiftUI
1314

1415
// Necessary to launch this app
@@ -34,6 +35,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
3435
var configWindowController: NSWindowController?
3536
var userDictionaryEditorWindowController: NSWindowController?
3637
var kanaKanjiConverter = KanaKanjiConverter.withDefaultDictionary()
38+
private var updaterController: SPUStandardUpdaterController?
3739

3840
private var userDictionaryMemoryDirectoryURL: URL {
3941
AppGroup.memoryDirectoryURL()
@@ -122,10 +124,47 @@ class AppDelegate: NSObject, NSApplicationDelegate {
122124
}
123125
}
124126

127+
@objc private func checkForUpdates(_ sender: Any?) {
128+
guard let updaterController else {
129+
let alert = NSAlert()
130+
alert.messageText = "自動アップデートは未設定です"
131+
alert.informativeText = "SPARKLE_FEED_URL と SPARKLE_PUBLIC_ED_KEY を設定したビルドで利用できます。"
132+
alert.runModal()
133+
return
134+
}
135+
updaterController.checkForUpdates(sender)
136+
}
137+
138+
private func configureUpdaterIfAvailable() {
139+
guard
140+
let feedURL = Bundle.main.object(forInfoDictionaryKey: "SUFeedURL") as? String,
141+
!feedURL.isEmpty,
142+
let publicEDKey = Bundle.main.object(forInfoDictionaryKey: "SUPublicEDKey") as? String,
143+
!publicEDKey.isEmpty
144+
else {
145+
NSLog("Sparkle updater is disabled because SUFeedURL or SUPublicEDKey is not configured.")
146+
return
147+
}
148+
self.updaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)
149+
}
150+
151+
private func addApplicationMenuIfNeeded() {
152+
let appMenuItem = NSMenuItem(title: "azooKey", action: nil, keyEquivalent: "")
153+
NSApp.mainMenu?.addItem(appMenuItem)
154+
155+
let appSubmenu = NSMenu(title: "azooKey")
156+
appMenuItem.submenu = appSubmenu
157+
158+
let checkForUpdatesItem = NSMenuItem(title: "更新を確認...", action: #selector(checkForUpdates(_:)), keyEquivalent: "")
159+
checkForUpdatesItem.target = self
160+
appSubmenu.addItem(checkForUpdatesItem)
161+
}
162+
125163
func applicationDidFinishLaunching(_ notification: Notification) {
126164
// Insert code here to initialize your application
127165
self.server = IMKServer(name: Bundle.main.infoDictionary?["InputMethodConnectionName"] as? String, bundleIdentifier: Bundle.main.bundleIdentifier)
128166
NSLog("tried connection")
167+
self.configureUpdaterIfAvailable()
129168

130169
// Keychainから設定値を非同期で読み込み
131170
Task {
@@ -138,6 +177,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
138177
NSApp.mainMenu = NSMenu()
139178
}
140179

180+
self.addApplicationMenuIfNeeded()
181+
141182
// Add an Edit menu
142183
let editMenu = NSMenuItem(title: "Edit", action: nil, keyEquivalent: "")
143184
NSApp.mainMenu?.addItem(editMenu)

azooKeyMac/Info.plist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
<dict>
55
<key>LSUIElement</key>
66
<true/>
7+
<key>SUEnableInstallerLauncherService</key>
8+
<true/>
9+
<key>SUFeedURL</key>
10+
<string>$(SPARKLE_FEED_URL)</string>
11+
<key>SUPublicEDKey</key>
12+
<string>$(SPARKLE_PUBLIC_ED_KEY)</string>
713
<key>ComponentInputModeDict</key>
814
<dict>
915
<key>tsVisibleInputModeOrderedArrayKey</key>

azooKeyMac/azooKeyMac.entitlements

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
1616
<array>
1717
<string>dev.ensan.inputmethod.azooKeyMac.ConverterServer</string>
18+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)-spks</string>
19+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)-spki</string>
1820
</array>
1921
</dict>
2022
</plist>

0 commit comments

Comments
 (0)