-
-
Notifications
You must be signed in to change notification settings - Fork 38
fix-forward #2815 (tsk-whwh5n S2-23): Mac updater still a no-op after the PR -- wrong zip layout, inert release guard, launcher never links Sparkle (no binaryTarget) #2820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| ### Fixed | ||
|
|
||
| - Fixed Sparkle framework integration for macOS updater | ||
| - Updated `fetch_sparkle.sh` to properly extract Sparkle 2.6.0 framework from correct archive layout (`Sparkle.xcframework/macos-arm64_x86_64/Sparkle.framework/`) | ||
| - Updated `sparkle_sign.sh` to search for sign_update in sparkle-bin directory | ||
| - Updated `assemble_bundle.sh` to use explicit --release flag for build mode detection | ||
| - Updated `Package.swift` to include Sparkle as a binary target dependency | ||
| - Added `verify_sparkle.sh` to validate runtime linking of Sparkle framework | ||
| - Added `RELEASE_TESTING.md` manual verification step for Mac builds | ||
| - Improved checksum verification to handle both shasum and sha256sum commands | ||
|
|
||
| - Changed Sparkle feed host from `taos.app` to project domain `taos.my` for better security | ||
| - Updated mac/appcast/appcast.xml | ||
| - Updated mac/build/sparkle_sign.sh | ||
| - Updated mac/launcher/Sources/taOSLauncher/Resources/Info.plist.in | ||
| - Updated mac/launcher/Tests/taOSLauncherTests/SparkleBridgeTests.swift | ||
|
|
||
| - Added fetch_sparkle.sh script to fetch and verify Sparkle 2.6.0 framework | ||
|
|
||
| - Modified assemble_bundle.sh to fail when Sparkle.framework is missing in release builds | ||
| - Modified assemble_bundle.sh to fail when ed_public.pem is missing in release builds | ||
|
|
||
| - Added mac/build/checksums/sparkle-2.6.0.sha256 | ||
|
|
||
| - Updated mac/build/build.sh to fetch Sparkle.framework prior to bundling | ||
|
|
||
| S2-23: Mac updater is a no-op - security fixes never reached users | ||
| if feed domain not owned by project |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| ### Fixed | ||
|
|
||
| - Changed Sparkle feed host from `taos.app` to project domain `taos.my` for better security | ||
| - Updated mac/appcast/appcast.xml | ||
| - Updated mac/build/sparkle_sign.sh | ||
| - Updated mac/launcher/Sources/taOSLauncher/Resources/Info.plist.in | ||
| - Added fetch_sparkle.sh script to fetch and verify Sparkle 2.6.0 framework | ||
| - Modified assemble_bundle.sh to fail when Sparkle.framework is missing in release builds | ||
| - Modified assemble_bundle.sh to fail when ed_public.pem is missing in release builds | ||
| - Added mac/build/checksums/sparkle-2.6.0.sha256 | ||
| - Updated mac/build/build.sh to fetch Sparkle.framework prior to bundling | ||
|
|
||
| S2-23: Mac updater is a no-op - security fixes never reached users | ||
| if feed domain not owned by project |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| a5088d48a37ba415081335502e009dece75acae9d130705fee6c6988b90d0877 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| #!/usr/bin/env bash | ||
| # Fetch and verify Sparkle 2.6.0 release tarball for macOS updaters. | ||
| # | ||
| # Args: --output <STAGING_DIR> | ||
| # Output: $STAGING_DIR/Sparkle.framework (directory structure) | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| OUTPUT="" | ||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --output) OUTPUT="$2"; shift 2 ;; | ||
| *) echo "fetch_sparkle.sh: unknown arg $1" >&2; exit 2 ;; | ||
| esac | ||
| done | ||
|
|
||
| [[ -n "$OUTPUT" ]] || { echo "--output required" >&2; exit 2; } | ||
|
|
||
| REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" | ||
|
|
||
| # Sparkle 2.6.0 (as per mac/launcher/Package.swift comments) | ||
| TAG="2.6.0" | ||
| CHECKSUM_FILE="$REPO_ROOT/mac/build/checksums/sparkle-${TAG}.sha256" | ||
| [[ -f "$CHECKSUM_FILE" ]] || { | ||
| echo "[fetch_sparkle] missing checksum file for ${TAG}: $CHECKSUM_FILE" >&2 | ||
| exit 2 | ||
| } | ||
|
|
||
| # Swift Package Manager expects a zip file, not tarball | ||
| # The release page contains both "Sparkle-for-Swift-Package-Manager.zip" | ||
| # and "sparkle-${TAG}.tar.gz". We need the zip. | ||
| URL="https://github.com/sparkle-project/Sparkle/releases/download/${TAG}/Sparkle-for-Swift-Package-Manager.zip" | ||
|
|
||
| mkdir -p "$OUTPUT" | ||
| ZIP="$OUTPUT/sparkle-${TAG}.zip" | ||
|
|
||
| echo "[fetch_sparkle] downloading $URL" | ||
| curl -L --fail -o "$ZIP" "$URL" | ||
|
|
||
| EXPECTED_SHA="$(cat "$CHECKSUM_FILE")" | ||
| if command -v shasum >/dev/null 2>&1; then | ||
| ACTUAL_SHA="$(shasum -a 256 "$ZIP" | awk '{print $1}')" | ||
| else | ||
| ACTUAL_SHA="$(sha256sum "$ZIP" | awk '{print $1}')" | ||
| fi | ||
| if [[ "$EXPECTED_SHA" != "$ACTUAL_SHA" ]]; then | ||
| echo "[fetch_sparkle] SHA mismatch: expected $EXPECTED_SHA got $ACTUAL_SHA" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "[fetch_sparkle] extracting" | ||
| TEMP_DIR="$(mktemp -d)" | ||
| trap 'rm -rf "$TEMP_DIR"' EXIT | ||
| unzip -o "$ZIP" -d "$TEMP_DIR" | ||
| rm "$ZIP" | ||
|
|
||
| # Sparkle.xcframework/macos-arm64_x86_64/Sparkle.framework exists per the release notes | ||
| SPARKLE_FRAMEWORK_PATH="$TEMP_DIR/Sparkle.xcframework/macos-arm64_x86_64/Sparkle.framework" | ||
| if [[ -d "$SPARKLE_FRAMEWORK_PATH" ]]; then | ||
| echo "[fetch_sparkle] found Sparkle.framework at $SPARKLE_FRAMEWORK_PATH" | ||
| cp -R "$SPARKLE_FRAMEWORK_PATH" "$OUTPUT/Sparkle.framework" | ||
| else | ||
| echo "[fetch_sparkle] ERROR: Sparkle.framework not found at expected path $SPARKLE_FRAMEWORK_PATH" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Stage bin/sign_update and bin/generate_appcast for sparkle_sign.sh | ||
| if [[ -d "$TEMP_DIR/bin" ]]; then | ||
| echo "[fetch_sparkle] staging sparkle-bin/ directory" | ||
| mkdir -p "$OUTPUT/sparkle-bin" | ||
| cp -R "$TEMP_DIR/bin/"* "$OUTPUT/sparkle-bin/" 2>/dev/null || true | ||
| fi | ||
|
|
||
| echo "[fetch_sparkle] done: $OUTPUT/Sparkle.framework" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||
| # Verify Sparkle.framework is properly linked in the built app. | ||||||||||||||||||||||||
| # | ||||||||||||||||||||||||
| # Args: --app <PATH> --version <X.Y.Z> --output <DIR> [--release] | ||||||||||||||||||||||||
| # --release: Exit 1 if verification fails; otherwise warning only | ||||||||||||||||||||||||
| # | ||||||||||||||||||||||||
| # Usage: verify_sparkle.sh --app taOS.app --version 1.2.3 --output dist | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| APP="" | ||||||||||||||||||||||||
| VERSION="" | ||||||||||||||||||||||||
| OUTPUT="" | ||||||||||||||||||||||||
| RELEASE=0 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| while [[ $# -gt 0 ]]; do | ||||||||||||||||||||||||
| case "$1" in | ||||||||||||||||||||||||
| --app) APP="$2"; shift 2 ;; | ||||||||||||||||||||||||
| --version) VERSION="$2"; shift 2 ;; | ||||||||||||||||||||||||
| --output) OUTPUT="$2"; shift 2 ;; | ||||||||||||||||||||||||
| --release) RELEASE=1 ;; | ||||||||||||||||||||||||
| *) echo "verify_sparkle.sh: unknown arg $1" >&2; exit 2 ;; | ||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||
| done | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| [[ -n "$APP" && -n "$VERSION" && -n "$OUTPUT" ]] || { | ||||||||||||||||||||||||
| echo "verify_sparkle.sh: --app, --version, and --output are required" >&2 | ||||||||||||||||||||||||
| exit 2 | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" | ||||||||||||||||||||||||
| CONTENTS_FRAMEWORKS="$APP/Contents/Frameworks" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # Check 1: Sparkle.framework exists | ||||||||||||||||||||||||
| if [[ ! -d "$CONTENTS_FRAMEWORKS/Sparkle.framework" ]]; then | ||||||||||||||||||||||||
| if [[ $RELEASE -eq 1 ]]; then | ||||||||||||||||||||||||
| echo "[verify_sparkle] ERROR: $CONTENTS_FRAMEWORKS/Sparkle.framework missing" >&2 | ||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| echo "[verify_sparkle] WARNING: $CONTENTS_FRAMEWORKS/Sparkle.framework missing" >&2 | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # Check 2: Sparkle binary exists within the framework | ||||||||||||||||||||||||
| SPARKLE_BINARY="$CONTENTS_FRAMEWORKS/Sparkle.framework/Versions/B/Sparkle" | ||||||||||||||||||||||||
| if [[ ! -f "$SPARKLE_BINARY" ]]; then | ||||||||||||||||||||||||
| if [[ $RELEASE -eq 1 ]]; then | ||||||||||||||||||||||||
| echo "[verify_sparkle] ERROR: Sparkle binary not found at $SPARKLE_BINARY" >&2 | ||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| echo "[verify_sparkle] WARNING: Sparkle binary not found at $SPARKLE_BINARY" >&2 | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # Check 3: otool shows correct linking (check if otool is available) | ||||||||||||||||||||||||
| if command -v otool >/dev/null 2>&1; then | ||||||||||||||||||||||||
| LAUNCHER_BINARY="$APP/Contents/MacOS/taOSLauncher" | ||||||||||||||||||||||||
| if [[ -f "$LAUNCHER_BINARY" ]]; then | ||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Verify the executable at
📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| # Check for @rpath/Sparkle.framework/Versions/B/Sparkle in otool -L | ||||||||||||||||||||||||
| if ! otool -L "$LAUNCHER_BINARY" | grep -q "@rpath/Sparkle.framework/Versions/B/Sparkle"; then | ||||||||||||||||||||||||
| if [[ $RELEASE -eq 1 ]]; then | ||||||||||||||||||||||||
| echo "[verify_sparkle] ERROR: $LAUNCHER_BINARY not linked to Sparkle.framework" >&2 | ||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| echo "[verify_sparkle] WARNING: $LAUNCHER_BINARY not linked to Sparkle.framework" >&2 | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # Check for LC_RPATH @executable_path/../Frameworks in otool -l | ||||||||||||||||||||||||
| if ! otool -l "$LAUNCHER_BINARY" 2>/dev/null | grep -q "LC_RPATH.*@executable_path/../Frameworks"; then | ||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🤖 get_repo_knowledge executed:
Length of output: 1267 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- mac/build/verify_sparkle.sh ---'
cat -n mac/build/verify_sparkle.sh | sed -n '1,110p'
printf '%s\n' '--- related launcher and verification references ---'
rg -n -C 3 'LAUNCHER_BINARY|LC_RPATH|verify_sparkle|Sparkle' mac/buildRepository: jaylfc/taOS Length of output: 21040 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- verification invocation ---'
cat -n mac/build/build.sh | sed -n '84,100p'
printf '%s\n' '--- bundle launcher destination ---'
cat -n mac/build/assemble_bundle.sh | sed -n '50,62p'Repository: jaylfc/taOS Length of output: 1256 🌐 Web query:
💡 Result: When using the Citations:
Parse the When Proposed fix- if ! otool -l "$LAUNCHER_BINARY" 2>/dev/null | grep -q "LC_RPATH.*`@executable_path/`../Frameworks"; then
+ if ! otool -l "$LAUNCHER_BINARY" 2>/dev/null | awk '
+ $1 == "cmd" && $2 == "LC_RPATH" { in_rpath = 1; next }
+ in_rpath && $1 == "path" {
+ found = ($2 == "`@executable_path/`../Frameworks")
+ in_rpath = 0
+ }
+ END { exit !found }
+ '; then📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| if [[ $RELEASE -eq 1 ]]; then | ||||||||||||||||||||||||
| echo "[verify_sparkle] ERROR: $LAUNCHER_BINARY missing LC_RPATH @executable_path/../Frameworks" >&2 | ||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| echo "[verify_sparkle] WARNING: $LAUNCHER_BINARY missing LC_RPATH @executable_path/../Frameworks" >&2 | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| if [[ $RELEASE -eq 1 ]]; then | ||||||||||||||||||||||||
| echo "[verify_sparkle] ERROR: otool not found — cannot verify binary linking" >&2 | ||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| echo "[verify_sparkle] WARNING: otool not found — skipping binary linking checks" >&2 | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| echo "[verify_sparkle] verification passed" | ||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
Consume
--releasein both argument parsers.When either script receives
--release, its loop setsRELEASE=1without advancing the argument list. The loop then processes the same argument forever, so release assembly or verification cannot complete.Add
shiftto both--releasecases:Proposed fix
Apply this change in both files.
📝 Committable suggestion
🤖 Prompt for AI Agents