Skip to content

Commit f77e7d8

Browse files
committed
Finish Sparkle fallback plumbing
1 parent 0c65f39 commit f77e7d8

6 files changed

Lines changed: 41 additions & 30 deletions

File tree

Sources/Update/UpdateDriver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class UpdateDriver: NSObject, SPUUserDriver {
118118
let details = formatErrorForLog(error)
119119
UpdateLogStore.shared.append("show updater error: \(details)")
120120
if usesStandardPresentation,
121-
let manualDownloadURL = UpdateViewModel.manualDownloadURL(for: error) {
121+
let manualDownloadURL = UpdateViewModel.manualDownloadURL(for: error, infoFeedURLString: lastFeedURLString) {
122122
clearCustomStateForStandardPresentation()
123123
presentManualDownloadAlert(for: error, manualDownloadURL: manualDownloadURL) { [weak self] shouldRetry in
124124
self?.finishUserInitiatedCheckPresentation()

Sources/Update/UpdatePopoverView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ fileprivate struct UpdateErrorView: View {
345345
technicalDetails: error.technicalDetails,
346346
feedURLString: error.feedURLString
347347
)
348-
let manualDownloadURL = UpdateViewModel.manualDownloadURL(for: error.error)
348+
let manualDownloadURL = UpdateViewModel.manualDownloadURL(for: error)
349349

350350
VStack(alignment: .leading, spacing: 16) {
351351
VStack(alignment: .leading, spacing: 8) {

Sources/Update/UpdateViewModel.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,10 @@ class UpdateViewModel: ObservableObject {
353353
return URL(string: isNightly ? manualDownloadNightlyDMGURLString : manualDownloadDMGURLString)
354354
}
355355

356+
static func manualDownloadURL(for updateError: UpdateState.Error) -> URL? {
357+
manualDownloadURL(for: updateError.error, infoFeedURLString: updateError.feedURLString)
358+
}
359+
356360
private static func networkError(from error: NSError) -> NSError? {
357361
if error.domain == NSURLErrorDomain {
358362
return error

cmuxTests/ShortcutAndCommandPaletteTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,24 @@ final class UpdateViewModelPresentationTests: XCTestCase {
997997
)
998998
}
999999

1000+
func testUpdateStateErrorManualDownloadURLUsesFeedURLString() {
1001+
let updateError = UpdateState.Error(
1002+
error: NSError(
1003+
domain: SUSparkleErrorDomain,
1004+
code: 4005,
1005+
userInfo: [NSLocalizedDescriptionKey: "Failed to create installation cache directory"]
1006+
),
1007+
retry: {},
1008+
dismiss: {},
1009+
feedURLString: "https://github.com/manaflow-ai/cmux/releases/download/nightly/appcast.xml"
1010+
)
1011+
1012+
XCTAssertEqual(
1013+
UpdateViewModel.manualDownloadURL(for: updateError)?.absoluteString,
1014+
"https://github.com/manaflow-ai/cmux/releases/download/nightly/cmux-nightly-macos.dmg"
1015+
)
1016+
}
1017+
10001018
func testSparkleInstallationErrorDetailsUseSparkleCodeName() {
10011019
let error = NSError(
10021020
domain: SUSparkleErrorDomain,

scripts/codesign_app_bundle.sh

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,9 @@ resolve_sparkle_version_dir() {
6767

6868
code_paths_by_depth() {
6969
local root="$1"
70-
find "$root" -mindepth 1 \
71-
\( -name '*.framework' -o -name '*.xpc' -o -name '*.app' -o -name '*.dylib' \) \
72-
-print |
73-
awk -F/ '{print NF ":" $0}' |
74-
LC_ALL=C sort -t: -k1,1nr -k2,2 |
75-
cut -d: -f2-
70+
find "$root" -depth -mindepth 1 \
71+
\( -name '*.framework' -o -name '*.xpc' -o -name '*.app' -o -name '*.bundle' -o -name '*.dylib' \) \
72+
-print
7673
}
7774

7875
FRAMEWORKS_DIR="$APP_PATH/Contents/Frameworks"
@@ -85,16 +82,9 @@ fi
8582

8683
if [ -n "$SPARKLE_VERSION_DIR" ]; then
8784
sign_without_entitlements "$SPARKLE_VERSION_DIR/Autoupdate"
88-
if [ -d "$SPARKLE_VERSION_DIR/XPCServices" ]; then
89-
while IFS= read -r dependency; do
90-
sign_without_entitlements "$dependency"
91-
done < <(code_paths_by_depth "$SPARKLE_VERSION_DIR/XPCServices")
92-
fi
9385
while IFS= read -r dependency; do
9486
sign_without_entitlements "$dependency"
95-
done < <(
96-
find "$SPARKLE_VERSION_DIR" -mindepth 1 -maxdepth 1 -name '*.app' -print | LC_ALL=C sort
97-
)
87+
done < <(code_paths_by_depth "$SPARKLE_VERSION_DIR")
9888
fi
9989

10090
sign_without_entitlements "$SPARKLE_FRAMEWORK"
@@ -106,12 +96,6 @@ if [ -d "$FRAMEWORKS_DIR" ]; then
10696
esac
10797
sign_without_entitlements "$dependency"
10898
done < <(code_paths_by_depth "$FRAMEWORKS_DIR")
109-
while IFS= read -r dependency; do
110-
[ "$dependency" = "$SPARKLE_FRAMEWORK" ] && continue
111-
sign_without_entitlements "$dependency"
112-
done < <(
113-
find "$FRAMEWORKS_DIR" -mindepth 1 -maxdepth 1 -name '*.bundle' -print | LC_ALL=C sort
114-
)
11599
fi
116100

117101
sign_with_entitlements "$APP_PATH/Contents/Resources/bin/cmux"

tests/test_ci_codesign_app_bundle.sh

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ trap 'rm -rf "$TMP_DIR"' EXIT
1111
APP_PATH="$TMP_DIR/cmux.app"
1212
SPARKLE_FRAMEWORK="$APP_PATH/Contents/Frameworks/Sparkle.framework"
1313
SPARKLE_VERSION_DIR="$SPARKLE_FRAMEWORK/Versions/B"
14-
EXTRA_SPARKLE_XPC="$SPARKLE_VERSION_DIR/XPCServices/InstallerStatus.xpc"
14+
NESTED_SPARKLE_XPC="$SPARKLE_VERSION_DIR/XPCServices/Installer.xpc/Contents/XPCServices/InstallerStatus.xpc"
15+
NESTED_SPARKLE_FRAMEWORK="$SPARKLE_VERSION_DIR/Updater.app/Contents/Frameworks/UpdaterSupport.framework"
1516
OTHER_FRAMEWORK="$APP_PATH/Contents/Frameworks/Sentry.framework"
17+
NESTED_SENTRY_BUNDLE="$OTHER_FRAMEWORK/Resources/Crashpad.bundle"
1618
CLI_PATH="$APP_PATH/Contents/Resources/bin/cmux"
1719
HELPER_PATH="$APP_PATH/Contents/Resources/bin/ghostty"
1820
ENTITLEMENTS="cmux.entitlements"
@@ -25,9 +27,10 @@ fi
2527
mkdir -p \
2628
"$SPARKLE_VERSION_DIR/XPCServices/Installer.xpc" \
2729
"$SPARKLE_VERSION_DIR/XPCServices/Downloader.xpc" \
28-
"$EXTRA_SPARKLE_XPC" \
30+
"$NESTED_SPARKLE_XPC" \
31+
"$NESTED_SPARKLE_FRAMEWORK" \
2932
"$SPARKLE_VERSION_DIR/Updater.app" \
30-
"$OTHER_FRAMEWORK" \
33+
"$NESTED_SENTRY_BUNDLE" \
3134
"$(dirname "$CLI_PATH")"
3235
ln -s B "$SPARKLE_FRAMEWORK/Versions/Current"
3336
touch \
@@ -47,35 +50,37 @@ line_number_regex() {
4750

4851
installer_line="$(line_number_regex 'Installer\.xpc$')"
4952
downloader_line="$(line_number_regex 'Downloader\.xpc$')"
50-
extra_xpc_line="$(line_number_regex 'InstallerStatus\.xpc$')"
53+
nested_xpc_line="$(line_number_regex 'InstallerStatus\.xpc$')"
5154
autoupdate_line="$(line_number_regex '/Autoupdate$')"
55+
updater_support_line="$(line_number_regex 'UpdaterSupport\.framework$')"
5256
updater_line="$(line_number_regex 'Updater\.app$')"
5357
sparkle_line="$(line_number_regex 'Sparkle\.framework$')"
58+
nested_bundle_line="$(line_number_regex 'Crashpad\.bundle$')"
5459
sentry_line="$(line_number_regex 'Sentry\.framework$')"
5560
cli_line="$(line_number_regex '/Resources/bin/cmux$')"
5661
helper_line="$(line_number_regex '/Resources/bin/ghostty$')"
5762
app_line="$(line_number_regex '--entitlements cmux\.entitlements .*/cmux\.app$')"
5863
verify_line="$(line_number_regex '--verify --deep --strict --verbose=2 .*/cmux\.app$')"
5964

60-
for value_name in installer_line downloader_line extra_xpc_line autoupdate_line updater_line sparkle_line sentry_line cli_line helper_line app_line verify_line; do
65+
for value_name in installer_line downloader_line nested_xpc_line autoupdate_line updater_support_line updater_line sparkle_line nested_bundle_line sentry_line cli_line helper_line app_line verify_line; do
6166
if [ -z "${!value_name}" ]; then
6267
echo "FAIL: expected $value_name in signing plan"
6368
printf '%s\n' "$OUTPUT"
6469
exit 1
6570
fi
6671
done
6772

68-
if [ "$installer_line" -ge "$sparkle_line" ] || [ "$downloader_line" -ge "$sparkle_line" ] || [ "$extra_xpc_line" -ge "$sparkle_line" ] || [ "$autoupdate_line" -ge "$sparkle_line" ] || [ "$updater_line" -ge "$sparkle_line" ]; then
73+
if [ "$nested_xpc_line" -ge "$installer_line" ] || [ "$installer_line" -ge "$sparkle_line" ] || [ "$downloader_line" -ge "$sparkle_line" ] || [ "$autoupdate_line" -ge "$sparkle_line" ] || [ "$updater_support_line" -ge "$updater_line" ] || [ "$updater_line" -ge "$sparkle_line" ]; then
6974
echo "FAIL: Sparkle nested components must be signed before Sparkle.framework"
7075
exit 1
7176
fi
7277

73-
if [ "$sparkle_line" -ge "$sentry_line" ] || [ "$sentry_line" -ge "$cli_line" ] || [ "$helper_line" -ge "$app_line" ] || [ "$app_line" -ge "$verify_line" ]; then
78+
if [ "$nested_bundle_line" -ge "$sentry_line" ] || [ "$sparkle_line" -ge "$sentry_line" ] || [ "$sentry_line" -ge "$cli_line" ] || [ "$helper_line" -ge "$app_line" ] || [ "$app_line" -ge "$verify_line" ]; then
7479
echo "FAIL: signing order is incorrect"
7580
exit 1
7681
fi
7782

78-
for sparkle_component in Installer.xpc Downloader.xpc InstallerStatus.xpc /Autoupdate Updater.app Sparkle.framework Sentry.framework; do
83+
for sparkle_component in Installer.xpc Downloader.xpc InstallerStatus.xpc /Autoupdate UpdaterSupport.framework Updater.app Crashpad.bundle Sparkle.framework Sentry.framework; do
7984
if printf '%s\n' "$OUTPUT" | grep -F "$sparkle_component" | grep -Fq -- '--entitlements'; then
8085
echo "FAIL: $sparkle_component must not be signed with app entitlements"
8186
exit 1

0 commit comments

Comments
 (0)