Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae83ea7dab | ||
|
|
39205230b6 | ||
|
|
55a266014c | ||
|
|
c002cab616 | ||
|
|
117134cead | ||
|
|
35711d33c0 | ||
|
|
4f3d56dc3c | ||
|
|
0d80a0f912 | ||
|
|
b1d6e61f05 | ||
|
|
2dd2c2154f | ||
|
|
c6ecbbe511 | ||
|
|
77a145604c | ||
|
|
0016030ff3 | ||
|
|
615d664731 | ||
|
|
5644fbdfe0 | ||
|
|
9b5883fe77 | ||
|
|
5d15810802 | ||
|
|
519d15ed10 | ||
|
|
446bbe7f98 | ||
|
|
b67fffd3f0 | ||
|
|
84935ee8fd | ||
|
|
0f266f7046 | ||
|
|
bff7c44c29 | ||
|
|
f930e8334f | ||
|
|
0032ad9b57 | ||
|
|
b7f5d1a762 | ||
|
|
5dc5621871 | ||
|
|
2a848c3251 | ||
|
|
bb4f972d58 | ||
|
|
62d4a9ac96 | ||
|
|
75fe670779 | ||
|
|
a961baab28 | ||
|
|
7246b132f6 | ||
|
|
1afce31641 | ||
|
|
281016bfc9 | ||
|
|
144ad27aa6 | ||
|
|
aa655bb7d6 | ||
|
|
1ac34e1f04 | ||
|
|
5f045c113a | ||
|
|
2dbe739c97 | ||
|
|
da9dd2f7ed | ||
|
|
2ae67b6675 | ||
|
|
989717539c | ||
|
|
6d05419abb | ||
|
|
be37bf526a | ||
|
|
6c1f5c6d25 | ||
|
|
32f97ff7d4 | ||
|
|
dbbe1752d1 | ||
|
|
2fe9821ac1 | ||
|
|
87d4bffb99 | ||
|
|
92782716fc | ||
|
|
002c9e8cf2 | ||
|
|
8820244589 | ||
|
|
48d2f0ea42 | ||
|
|
1947d05d78 | ||
|
|
86039cd5a9 | ||
|
|
4f9c008498 | ||
|
|
76818578b9 | ||
|
|
9070882f38 | ||
|
|
541927c30a | ||
|
|
ab3a7ca469 | ||
|
|
ee27efc0d4 | ||
|
|
c3f445e3c3 | ||
|
|
215c24d5a2 | ||
|
|
b96b018f70 | ||
|
|
65a65939a7 | ||
|
|
25723b7f07 | ||
|
|
10683ebc73 | ||
|
|
393bcf27e1 | ||
|
|
839a513fde | ||
|
|
77e82753ba | ||
|
|
bbb0b580b0 | ||
|
|
dd225b2b8e | ||
|
|
76b01352ac | ||
|
|
fcca8cee38 | ||
|
|
94d1b3fec4 | ||
|
|
4352ae1476 | ||
|
|
846e0b149b | ||
|
|
11ca4dbede | ||
|
|
1d8bdfe491 | ||
|
|
4f5a07822f | ||
|
|
67709dfda6 | ||
|
|
6753226087 | ||
|
|
a3671acf38 | ||
|
|
0aa773a0b3 | ||
|
|
adbc061d0b | ||
|
|
4deae63d43 | ||
|
|
b570006074 | ||
|
|
fd0d8d1adb | ||
|
|
78d5bd9bd5 | ||
|
|
091fd4ef38 | ||
|
|
656d6403fd | ||
|
|
db4c2aa930 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,6 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Fixed
|
||||
- Fixed Sparkle updater ZIP archive creation: replaced `zip` command with `ditto` to properly preserve app bundle code signatures during extraction, resolving "damaged app" errors on update installation.
|
||||
- Fixed code signature issues for sandboxed apps by removing entitlements parameter from non-sandboxed builds.
|
||||
- Fixed Sparkle framework deep code signing to handle complex framework structure.
|
||||
- Fixed missing XPC service entitlements (`com.apple.security.xpc.aConnectionServices`, `com.apple.security.xpc.aStatusServices`) required for Sparkle installer to communicate with sandboxed app.
|
||||
|
||||
### Changed
|
||||
- Re-enabled app sandbox with minimal entitlements (network.client only) for improved security while maintaining Sparkle update functionality.
|
||||
- Enhanced Sparkle error logging to include error domain and code information, making update failures easier to diagnose.
|
||||
- Updated build script to use `ditto -c -k --keepParent` for creating update ZIPs, which properly preserves code signatures that `zip` command breaks.
|
||||
|
||||
### Added
|
||||
- Added in-app Sparkle update logs in Preferences → Updates tab with Show/Hide toggle for real-time debugging of update operations.
|
||||
- Log entries include timestamps and distinguish between info and error messages.
|
||||
- Users can clear logs manually and logs persist during the session (max 100 entries).
|
||||
|
||||
### Previous Changes
|
||||
- Flattened the project structure so sources live at the repository root instead of the nested `iKeyMon/` folder and updated the Xcode project accordingly.
|
||||
- Fixed build settings (entitlements, preview assets) and placeholder previews to work with the new layout.
|
||||
- Migrated the updated API layer and unified `ServerInfo` model from the previous branch.
|
||||
@@ -10,5 +28,5 @@
|
||||
- Introduced repository-wide version management via `version.json` + `scripts/sync_version.sh`, ensuring Xcode targets and release artifacts stay aligned.
|
||||
- Enhanced `scripts/build_release.sh` to timestamp/harden signatures, notarize DMGs, and optionally publish tagged releases (pre-release by default) with ZIP/DMG assets directly to Gitea when credentials are configured.
|
||||
- Integrated Sparkle (via Swift Package Manager) to handle automatic update checks, downloads, signature verification, and relaunches, replacing the previous custom updater UI. Preferences now simply surface Sparkle's check/download toggles.
|
||||
- `scripts/build_release.sh` can optionally run Sparkle’s `generate_appcast` (when signing key and download prefix env vars are set), producing a ready-to-host `appcast.xml` alongside the ZIP/DMG artifacts.
|
||||
- `scripts/build_release.sh` can optionally run Sparkle's `generate_appcast` (when signing key and download prefix env vars are set), producing a ready-to-host `appcast.xml` alongside the ZIP/DMG artifacts.
|
||||
- Further reduced MainView console noise by removing redundant refresh/onAppear logs.
|
||||
|
||||
@@ -60,6 +60,7 @@ GITEA_REPO="iKeyMon"
|
||||
# optional Sparkle feed helpers:
|
||||
# SPARKLE_EDDSA_KEY_FILE="$HOME/.config/Sparkle/iKeyMon.key"
|
||||
# SPARKLE_DOWNLOAD_BASE_TEMPLATE="https://git.24unix.net/tracer/iKeyMon/releases/download/v{{VERSION}}"
|
||||
# If you prefer SPARKLE_DOWNLOAD_BASE_URL, it will automatically append `/v<version>` for you.
|
||||
# SPARKLE_APPCAST_OUTPUT="$ROOT_DIR/Sparkle/appcast.xml" # default
|
||||
```
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ final class SparkleUpdater: NSObject, ObservableObject {
|
||||
}()
|
||||
private let logger = Logger(subsystem: "net.24unix.iKeyMon", category: "Sparkle")
|
||||
private let verboseLogging: Bool
|
||||
@Published var logMessages: [String] = []
|
||||
|
||||
override init() {
|
||||
self.verboseLogging = ProcessInfo.processInfo.environment["SPARKLE_VERBOSE_LOGGING"] == "1"
|
||||
@@ -34,6 +35,7 @@ final class SparkleUpdater: NSObject, ObservableObject {
|
||||
|
||||
private func log(_ message: String) {
|
||||
logger.log("\(message, privacy: .public)")
|
||||
addLogMessage("[INFO] \(message)")
|
||||
if verboseLogging {
|
||||
print("[Sparkle] \(message)")
|
||||
}
|
||||
@@ -41,11 +43,21 @@ final class SparkleUpdater: NSObject, ObservableObject {
|
||||
|
||||
private func logError(_ message: String) {
|
||||
logger.error("\(message, privacy: .public)")
|
||||
addLogMessage("[ERROR] \(message)")
|
||||
if verboseLogging {
|
||||
fputs("[Sparkle][error] \(message)\n", stderr)
|
||||
}
|
||||
}
|
||||
|
||||
private func addLogMessage(_ message: String) {
|
||||
let timestamp = DateFormatter.localizedString(from: Date(), dateStyle: .none, timeStyle: .medium)
|
||||
let timestampedMessage = "[\(timestamp)] \(message)"
|
||||
logMessages.append(timestampedMessage)
|
||||
if logMessages.count > 100 {
|
||||
logMessages.removeFirst()
|
||||
}
|
||||
}
|
||||
|
||||
private func describe(update item: SUAppcastItem) -> String {
|
||||
let short = item.displayVersionString
|
||||
let build = item.versionString
|
||||
@@ -53,41 +65,63 @@ final class SparkleUpdater: NSObject, ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
extension SparkleUpdater: SPUUpdaterDelegate {
|
||||
func updater(_ updater: SPUUpdater, didFinishLoading appcast: SUAppcast) {
|
||||
log("Loaded Sparkle appcast containing \(appcast.items.count) item(s).")
|
||||
nonisolated func updater(_ updater: SPUUpdater, didFinishLoading appcast: SUAppcast) {
|
||||
Task { @MainActor in
|
||||
log("Loaded Sparkle appcast containing \(appcast.items.count) item(s).")
|
||||
}
|
||||
}
|
||||
|
||||
func updater(_ updater: SPUUpdater, didFindValidUpdate item: SUAppcastItem) {
|
||||
log("Found valid update \(describe(update: item))")
|
||||
nonisolated func updater(_ updater: SPUUpdater, didFindValidUpdate item: SUAppcastItem) {
|
||||
Task { @MainActor in
|
||||
log("Found valid update \(describe(update: item))")
|
||||
}
|
||||
}
|
||||
|
||||
func updaterDidNotFindUpdate(_ updater: SPUUpdater) {
|
||||
log("No updates available.")
|
||||
nonisolated func updaterDidNotFindUpdate(_ updater: SPUUpdater) {
|
||||
Task { @MainActor in
|
||||
log("No updates available.")
|
||||
}
|
||||
}
|
||||
|
||||
func updater(_ updater: SPUUpdater, willDownloadUpdate item: SUAppcastItem, with request: NSMutableURLRequest) {
|
||||
log("Downloading \(describe(update: item)) from \(request.url?.absoluteString ?? "unknown URL")")
|
||||
nonisolated func updater(_ updater: SPUUpdater, willDownloadUpdate item: SUAppcastItem, with request: NSMutableURLRequest) {
|
||||
Task { @MainActor in
|
||||
log("Downloading \(describe(update: item)) from \(request.url?.absoluteString ?? "unknown URL")")
|
||||
}
|
||||
}
|
||||
|
||||
func updater(_ updater: SPUUpdater, didDownloadUpdate item: SUAppcastItem) {
|
||||
log("Finished downloading \(describe(update: item))")
|
||||
nonisolated func updater(_ updater: SPUUpdater, didDownloadUpdate item: SUAppcastItem) {
|
||||
Task { @MainActor in
|
||||
log("Finished downloading \(describe(update: item))")
|
||||
}
|
||||
}
|
||||
|
||||
func updater(_ updater: SPUUpdater, failedToDownloadUpdate item: SUAppcastItem, error: Error) {
|
||||
logError("Failed to download \(describe(update: item)): \(error.localizedDescription)")
|
||||
nonisolated func updater(_ updater: SPUUpdater, failedToDownloadUpdate item: SUAppcastItem, error: Error) {
|
||||
Task { @MainActor in
|
||||
logError("Failed to download \(describe(update: item)): \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
func userDidCancelDownload(_ updater: SPUUpdater) {
|
||||
log("User cancelled Sparkle download.")
|
||||
nonisolated func userDidCancelDownload(_ updater: SPUUpdater) {
|
||||
Task { @MainActor in
|
||||
log("User cancelled Sparkle download.")
|
||||
}
|
||||
}
|
||||
|
||||
func updater(_ updater: SPUUpdater, willInstallUpdate item: SUAppcastItem) {
|
||||
log("Will install update \(describe(update: item))")
|
||||
nonisolated func updater(_ updater: SPUUpdater, willInstallUpdate item: SUAppcastItem) {
|
||||
Task { @MainActor in
|
||||
log("Will install update \(describe(update: item))")
|
||||
}
|
||||
}
|
||||
|
||||
func updater(_ updater: SPUUpdater, didAbortWithError error: Error) {
|
||||
logError("Sparkle aborted: \(error.localizedDescription)")
|
||||
nonisolated func updater(_ updater: SPUUpdater, didAbortWithError error: Error) {
|
||||
Task { @MainActor in
|
||||
let errorDescription = error as NSError
|
||||
let details = "Domain: \(errorDescription.domain), Code: \(errorDescription.code), Description: \(error.localizedDescription)"
|
||||
logError("Sparkle aborted: \(details)")
|
||||
if let underlying = errorDescription.userInfo[NSUnderlyingErrorKey] as? NSError {
|
||||
logError("Underlying error: Domain: \(underlying.domain), Code: \(underlying.code), Description: \(underlying.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ struct InfoCell: View {
|
||||
.font(monospaced ? .system(.body, design: .monospaced) : .body)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if let subtext {
|
||||
// Text(subtext)
|
||||
// .font(.caption)
|
||||
|
||||
@@ -12,7 +12,6 @@ struct MainView: View {
|
||||
private static let serverOrderKeyStatic = "serverOrder"
|
||||
private static let storedServersKeyStatic = "storedServers"
|
||||
|
||||
@EnvironmentObject private var sparkleUpdater: SparkleUpdater
|
||||
@State var showAddServerSheet: Bool = false
|
||||
@State private var serverBeingEdited: Server?
|
||||
@State private var serverToDelete: Server?
|
||||
@@ -60,14 +59,6 @@ struct MainView: View {
|
||||
}
|
||||
.help("Add Host")
|
||||
}
|
||||
ToolbarItem {
|
||||
Button {
|
||||
sparkleUpdater.checkForUpdates()
|
||||
} label: {
|
||||
Image(systemName: "square.and.arrow.down")
|
||||
}
|
||||
.help("Check for Updates")
|
||||
}
|
||||
}
|
||||
.navigationTitle("Servers")
|
||||
.onChange(of: selectedServerID) {
|
||||
|
||||
@@ -252,11 +252,6 @@ private struct UpdatesPreferencesView: View {
|
||||
Label("Check for Updates Now", systemImage: "sparkles")
|
||||
}
|
||||
|
||||
Text("Updates are delivered via Sparkle. Configure your appcast URL and public EdDSA key in Info.plist (keys `SUFeedURL` and `SUPublicEDKey`).")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.top, 4)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.toggleStyle(.switch)
|
||||
|
||||
30
Sparkle/appcast.xml
vendored
30
Sparkle/appcast.xml
vendored
@@ -3,28 +3,28 @@
|
||||
<channel>
|
||||
<title>iKeyMon</title>
|
||||
<item>
|
||||
<title>26.0.27</title>
|
||||
<pubDate>Sun, 07 Dec 2025 16:47:33 +0100</pubDate>
|
||||
<sparkle:version>57</sparkle:version>
|
||||
<sparkle:shortVersionString>26.0.27</sparkle:shortVersionString>
|
||||
<title>26.0.69</title>
|
||||
<pubDate>Sat, 03 Jan 2026 14:00:40 +0100</pubDate>
|
||||
<sparkle:version>150</sparkle:version>
|
||||
<sparkle:shortVersionString>26.0.69</sparkle:shortVersionString>
|
||||
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/iKeyMon-26.0.27.zip" length="4811492" type="application/octet-stream" sparkle:edSignature="6aEv0ii20pAkIl8kYWNkHM7+8APyDQtsus0SkF3C7/7q2X73HAsrsskNXjiiq0YF6bPVNAEs5y8G8GpwmerrCw=="/>
|
||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.69/iKeyMon-26.0.69.zip" length="2993457" type="application/octet-stream" sparkle:edSignature="cIqWamcPRsxA7zPaGcUuUOqLYs5KTcoAgXQkhblCF+Wc2tEnGHFVysARtMH68jGq7ObfhDuI3oZJNg857rQ0Dg=="/>
|
||||
</item>
|
||||
<item>
|
||||
<title>26.0.21</title>
|
||||
<pubDate>Wed, 26 Nov 2025 18:44:41 +0100</pubDate>
|
||||
<sparkle:version>49</sparkle:version>
|
||||
<sparkle:shortVersionString>26.0.21</sparkle:shortVersionString>
|
||||
<title>26.0.68</title>
|
||||
<pubDate>Sat, 03 Jan 2026 13:52:33 +0100</pubDate>
|
||||
<sparkle:version>148</sparkle:version>
|
||||
<sparkle:shortVersionString>26.0.68</sparkle:shortVersionString>
|
||||
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.21/iKeyMon-26.0.21.zip" length="4802995" type="application/octet-stream" sparkle:edSignature="bYXN15YyKlSmHKNXPizEW2WrVXQSgD5XOgbtzOYNL+maG8DB/jZ08A+cYtGgqUeSRd+X6Z5Ue+Tpdn4/ewsFBw=="/>
|
||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.68/iKeyMon-26.0.68.zip" length="2993469" type="application/octet-stream" sparkle:edSignature="M5WBkO4BN8RwMJ0ZU3Ku4CyQllnbEzz9X6MYR4IVX5prO9oyMBGoceHA3C97wZA6+++9u7RnRsKrFvei2CsWBQ=="/>
|
||||
</item>
|
||||
<item>
|
||||
<title>26.0.20</title>
|
||||
<pubDate>Wed, 26 Nov 2025 18:36:41 +0100</pubDate>
|
||||
<sparkle:version>47</sparkle:version>
|
||||
<sparkle:shortVersionString>26.0.20</sparkle:shortVersionString>
|
||||
<title>26.0.67</title>
|
||||
<pubDate>Sat, 03 Jan 2026 13:36:29 +0100</pubDate>
|
||||
<sparkle:version>146</sparkle:version>
|
||||
<sparkle:shortVersionString>26.0.67</sparkle:shortVersionString>
|
||||
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.20/iKeyMon-26.0.20.zip" length="4802865" type="application/octet-stream" sparkle:edSignature="hCJu2I1Db/TaU6pCs1gZi9EO5igr49Fjt/VNnyD8+jm45WINuhzGc4lShcLPxUQTy4iNHnVhmOPYwlthVMXPAg=="/>
|
||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.67/iKeyMon-26.0.67.zip" length="2993400" type="application/octet-stream" sparkle:edSignature="kr7vKMSM0002I/Fx2KVFGqNA6uMHb5Ll6Cr8NSG+8/Ct6KkC9dAwcd50xeUVPVJ7UT8lNBVPoBjZoFssgIEPAw=="/>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
@@ -3,9 +3,11 @@ set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
REMOTE_NAME="${1:-origin}"
|
||||
QUIET_RELEASE="${QUIET_RELEASE:-1}"
|
||||
RELEASE_LOG="${RELEASE_LOG:-$ROOT_DIR/build/release.log}"
|
||||
|
||||
if [[ -n "${SKIP_RELEASE:-}" ]]; then
|
||||
echo "⚙️ SKIP_RELEASE set — skipping automated release build."
|
||||
echo "release: skipped (SKIP_RELEASE=1)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -34,29 +36,49 @@ if [[ "$should_release" != true ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🚀 Detected push to master — bumping version and building release..."
|
||||
NEW_VERSION="$("$ROOT_DIR/scripts/bump_version.sh")"
|
||||
echo "🔢 marketing_version -> ${NEW_VERSION}"
|
||||
"$ROOT_DIR/scripts/sync_version.sh"
|
||||
if [[ "$QUIET_RELEASE" == "1" ]]; then
|
||||
mkdir -p "$(dirname "$RELEASE_LOG")"
|
||||
: >"$RELEASE_LOG"
|
||||
fi
|
||||
|
||||
run_logged() {
|
||||
if [[ "$QUIET_RELEASE" == "1" ]]; then
|
||||
"$@" >>"$RELEASE_LOG" 2>&1
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "$QUIET_RELEASE" == "1" ]]; then
|
||||
NEW_VERSION="$("$ROOT_DIR/scripts/bump_version.sh" 2>>"$RELEASE_LOG" | tee -a "$RELEASE_LOG")"
|
||||
else
|
||||
NEW_VERSION="$("$ROOT_DIR/scripts/bump_version.sh")"
|
||||
fi
|
||||
run_logged "$ROOT_DIR/scripts/sync_version.sh"
|
||||
|
||||
git -C "$ROOT_DIR" add "$ROOT_DIR/version.json" "$ROOT_DIR/iKeyMon.xcodeproj/project.pbxproj"
|
||||
|
||||
"$ROOT_DIR/scripts/build_release.sh"
|
||||
echo "release: building v${NEW_VERSION}..."
|
||||
if ! run_logged "$ROOT_DIR/scripts/build_release.sh"; then
|
||||
echo "release: failed (log: $RELEASE_LOG)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git -C "$ROOT_DIR" add "$ROOT_DIR/version.json" "$ROOT_DIR/iKeyMon.xcodeproj/project.pbxproj" "$ROOT_DIR/Sparkle/appcast.xml"
|
||||
|
||||
if git -C "$ROOT_DIR" diff --cached --quiet; then
|
||||
echo "⚠️ No release changes detected; skipping release commit."
|
||||
echo "release: no changes detected; skipping commit"
|
||||
else
|
||||
git -C "$ROOT_DIR" commit -m "chore: release ${NEW_VERSION}"
|
||||
echo "📝 Committed release ${NEW_VERSION}."
|
||||
run_logged git -C "$ROOT_DIR" commit -m "chore: release ${NEW_VERSION}" || {
|
||||
echo "release: commit failed (log: $RELEASE_LOG)"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
echo "📤 Pushing release commit..."
|
||||
if SKIP_RELEASE=1 git -C "$ROOT_DIR" push "$REMOTE_NAME" "${release_local_ref:-refs/heads/master}:${release_remote_ref:-refs/heads/master}"; then
|
||||
echo "✅ Release ${NEW_VERSION} pushed. Original push cancelled (already done)."
|
||||
if SKIP_RELEASE=1 git -C "$ROOT_DIR" push --quiet "$REMOTE_NAME" "${release_local_ref:-refs/heads/master}:${release_remote_ref:-refs/heads/master}"; then
|
||||
echo "release: success v${NEW_VERSION}"
|
||||
exit 1
|
||||
else
|
||||
echo "❌ Failed to push release ${NEW_VERSION}. Please resolve manually."
|
||||
echo "release: push failed (log: $RELEASE_LOG)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -6,5 +6,7 @@
|
||||
<string>https://git.24unix.net/tracer/iKeyMon/raw/branch/master/Sparkle/appcast.xml</string>
|
||||
<key>SUPublicEDKey</key>
|
||||
<string>EgJgrOGQ79L5me616jA7kDCEOgx+Rg11uYLYLLIyzTI=</string>
|
||||
<key>SUEnableInstallerLauncherService</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<false/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
5221016D2EE5E82700D04952 /* appcast.xml in Resources */ = {isa = PBXBuildFile; fileRef = 5221016B2EE5E82700D04952 /* appcast.xml */; };
|
||||
52A9B79F2EC8E7EE004DD4A2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B7872EC8E7EE004DD4A2 /* Assets.xcassets */; };
|
||||
52A9B8222EC8FA8A004DD4A2 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B8212EC8FA8A004DD4A2 /* CHANGELOG.md */; };
|
||||
52A9B9722ECF751C004DD4A2 /* signing.env.example in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B9712ECF751C004DD4A2 /* signing.env.example */; };
|
||||
@@ -28,6 +29,7 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
5203C24D2D997D2800576D4A /* iKeyMon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iKeyMon.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
5221016B2EE5E82700D04952 /* appcast.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = appcast.xml; sourceTree = "<group>"; };
|
||||
52A9B7872EC8E7EE004DD4A2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
52A9B7882EC8E7EE004DD4A2 /* iKeyMon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = iKeyMon.entitlements; sourceTree = "<group>"; };
|
||||
52A9B8212EC8FA8A004DD4A2 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
|
||||
@@ -76,6 +78,7 @@
|
||||
52A9B9712ECF751C004DD4A2 /* signing.env.example */,
|
||||
52A9BEC92ED3874F004DD4A2 /* README.md */,
|
||||
52A9BD122ED37E08004DD4A2 /* Frameworks */,
|
||||
5221016C2EE5E82700D04952 /* Sparkle */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -87,6 +90,14 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5221016C2EE5E82700D04952 /* Sparkle */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5221016B2EE5E82700D04952 /* appcast.xml */,
|
||||
);
|
||||
path = Sparkle;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
52A9BD122ED37E08004DD4A2 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -166,6 +177,7 @@
|
||||
files = (
|
||||
52A9B8222EC8FA8A004DD4A2 /* CHANGELOG.md in Resources */,
|
||||
52A9BECA2ED3874F004DD4A2 /* README.md in Resources */,
|
||||
5221016D2EE5E82700D04952 /* appcast.xml in Resources */,
|
||||
52A9B79F2EC8E7EE004DD4A2 /* Assets.xcassets in Resources */,
|
||||
52A9B9722ECF751C004DD4A2 /* signing.env.example in Resources */,
|
||||
);
|
||||
@@ -310,7 +322,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = iKeyMon.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 57;
|
||||
CURRENT_PROJECT_VERSION = 150;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Q5486ZVAFT;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@@ -325,7 +337,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 26.0.27;
|
||||
MARKETING_VERSION = 26.0.69;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.24unix.iKeyMon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -341,7 +353,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = iKeyMon.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 57;
|
||||
CURRENT_PROJECT_VERSION = 150;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"Preview Content\"";
|
||||
DEVELOPMENT_TEAM = Q5486ZVAFT;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
@@ -356,7 +368,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 26.0.27;
|
||||
MARKETING_VERSION = 26.0.69;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.24unix.iKeyMon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
|
||||
@@ -32,8 +32,13 @@ generate_appcast() {
|
||||
local download_prefix=""
|
||||
if [[ -n "${SPARKLE_DOWNLOAD_BASE_TEMPLATE:-}" ]]; then
|
||||
download_prefix="${SPARKLE_DOWNLOAD_BASE_TEMPLATE//\{\{VERSION\}\}/$VERSION}"
|
||||
else
|
||||
download_prefix="${SPARKLE_DOWNLOAD_BASE_URL:-}"
|
||||
elif [[ -n "${SPARKLE_DOWNLOAD_BASE_URL:-}" ]]; then
|
||||
download_prefix="${SPARKLE_DOWNLOAD_BASE_URL%/}/v${VERSION}"
|
||||
fi
|
||||
|
||||
# Ensure the version segment is present to match Gitea's /download/vX.Y.Z/ layout.
|
||||
if [[ -n "$download_prefix" ]] && [[ "$download_prefix" != *"/$VERSION"* ]]; then
|
||||
download_prefix="${download_prefix%/}/v${VERSION}"
|
||||
fi
|
||||
|
||||
if [[ -z "$generator" || -z "${SPARKLE_EDDSA_KEY_FILE:-}" || -z "$download_prefix" ]]; then
|
||||
@@ -154,6 +159,14 @@ if [[ ! -d "$APP_PATH" ]]; then
|
||||
fi
|
||||
|
||||
if [[ -n "${CODESIGN_IDENTITY:-}" ]]; then
|
||||
echo "🔏 Codesigning Sparkle framework..."
|
||||
codesign \
|
||||
--force \
|
||||
--options runtime \
|
||||
--timestamp \
|
||||
--sign "$CODESIGN_IDENTITY" \
|
||||
"$APP_PATH/Contents/Frameworks/Sparkle.framework"
|
||||
|
||||
echo "🔏 Codesigning app with identity: $CODESIGN_IDENTITY"
|
||||
codesign \
|
||||
--deep \
|
||||
@@ -184,9 +197,7 @@ print(data.get("marketing_version", "dev"))
|
||||
PY
|
||||
)"
|
||||
ZIP_NAME="iKeyMon-${VERSION}.zip"
|
||||
pushd "$(dirname "$APP_PATH")" >/dev/null
|
||||
zip -r "$ARTIFACTS_DIR/$ZIP_NAME" "$(basename "$APP_PATH")"
|
||||
popd >/dev/null
|
||||
ditto -c -k --keepParent "$APP_PATH" "$ARTIFACTS_DIR/$ZIP_NAME"
|
||||
|
||||
DMG_NAME="iKeyMon-${VERSION}.dmg"
|
||||
hdiutil create -volname "iKeyMon" -srcfolder "$STAGING_DIR" -ov -format UDZO "$ARTIFACTS_DIR/$DMG_NAME"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"marketing_version": "26.0.27"
|
||||
"marketing_version": "26.0.69"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user