Files
warp/script/macos/update_sentry_cocoa
2026-04-28 08:43:33 -05:00

238 lines
6.9 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Clean up zip files on exit.
cleanup() {
if [[ -n "${zip_file:-}" ]] && [[ -f "$zip_file" ]]; then
rm -f "$zip_file"
fi
}
trap cleanup EXIT
# Parse arguments.
DIR=""
VERSION=""
STATIC=false
while [[ $# -gt 0 ]]; do
case $1 in
--dir)
DIR="$2"
shift 2
;;
--version)
VERSION="$2"
shift 2
;;
--static)
STATIC=true
shift
;;
*)
echo "Unknown argument: $1"
echo "Usage: $0 --dir <frameworks_dir> --version <version> [--static]"
exit 1
;;
esac
done
if [[ -z "$DIR" ]] || [[ -z "$VERSION" ]]; then
echo "Error: Both --dir and --version are required"
echo "Usage: $0 --dir <frameworks_dir> --version <version> [--static]"
exit 1
fi
# Ensure DIR is absolute or relative to current directory.
if [[ ! "$DIR" = /* ]]; then
DIR="$(pwd)/$DIR"
fi
# Determine framework type.
if [[ "$STATIC" == "true" ]]; then
FRAMEWORK_TYPE="static"
XCFRAMEWORK_NAME="Sentry.xcframework"
else
FRAMEWORK_TYPE="dynamic"
XCFRAMEWORK_NAME="Sentry-Dynamic-WithARM64e.xcframework"
fi
# Framework path.
FRAMEWORK_PATH="$DIR/$XCFRAMEWORK_NAME/macos-arm64_arm64e_x86_64/Sentry.framework"
# Function to get framework version from Info.plist.
get_framework_version() {
local framework_path="$1"
local plist_path="$framework_path/Resources/Info.plist"
if [[ ! -f "$plist_path" ]]; then
echo ""
return
fi
/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$plist_path" 2>/dev/null || echo ""
}
# Fetch a URL with retries. Writes the response body to stdout.
# Usage: fetch_with_retries <url> [curl_args...]
fetch_with_retries() {
local url="$1"
shift
local max_retries=3
local attempt=1
local wait_seconds=2
while (( attempt <= max_retries )); do
local http_code
local response
# Fetch the URL, capturing both the response body and the HTTP status code.
# --fail-with-body ensures we still get the response body on HTTP errors.
response=$(curl --fail-with-body --show-error --write-out "\n%{http_code}" "$@" "$url") || true
http_code=$(echo "$response" | tail -n1)
response=$(echo "$response" | sed '$d')
if [[ "$http_code" =~ ^2 ]]; then
echo "$response"
return 0
fi
# Only retry on transient errors (rate limiting or server errors).
local is_retryable=false
if [[ "$http_code" == "429" || "$http_code" =~ ^5 ]]; then
is_retryable=true
fi
echo "[attempt $attempt/$max_retries] HTTP $http_code from $url" >&2
if [[ "$is_retryable" == "true" ]] && (( attempt < max_retries )); then
echo "Retrying in ${wait_seconds}s..." >&2
sleep "$wait_seconds"
wait_seconds=$(( wait_seconds * 2 ))
attempt=$(( attempt + 1 ))
else
if [[ "$is_retryable" != "true" ]]; then
echo "Non-retryable HTTP status; giving up." >&2
fi
break
fi
done
echo "Error: Failed to fetch $url (HTTP $http_code). Response:" >&2
echo "$response" >&2
return 1
}
# Function to download and extract framework.
download_framework() {
local xcframework_name="$1"
local xcframework_dir="$DIR/$xcframework_name"
local download_url="https://github.com/getsentry/sentry-cocoa/releases/download/${VERSION}/${xcframework_name}.zip"
zip_file="$DIR/${xcframework_name}.zip"
echo "Downloading $xcframework_name version $VERSION..."
# Create directory if it doesn't exist.
mkdir -p "$DIR"
# Require jq for SHA256 verification.
if ! command -v jq &> /dev/null; then
echo "Error: jq is required for SHA256 verification"
exit 1
fi
# Fetch release metadata from GitHub API.
# Prefer `gh api` for authenticated requests (avoids GitHub rate limits in CI).
local api_url="https://api.github.com/repos/getsentry/sentry-cocoa/releases/tags/${VERSION}"
echo "Fetching release metadata from $api_url"
local api_response
if command -v gh &> /dev/null; then
if ! api_response=$(gh api "repos/getsentry/sentry-cocoa/releases/tags/${VERSION}"); then
exit 1
fi
else
if ! api_response=$(fetch_with_retries "$api_url" --silent); then
exit 1
fi
fi
# Validate that the response contains an assets array before trying to iterate it.
local assets_type
assets_type=$(echo "$api_response" | jq -r '.assets | type')
if [[ "$assets_type" != "array" ]]; then
echo "Error: GitHub API response does not contain an assets array (got: $assets_type)." >&2
echo "Raw API response:" >&2
echo "$api_response" | head -50 >&2
exit 1
fi
local expected_sha256
expected_sha256=$(echo "$api_response" | jq -r ".assets[] | select(.name == \"$xcframework_name.zip\") | .digest // empty" | cut -d: -f2)
if [[ -z "$expected_sha256" ]]; then
echo "Error: Could not find SHA256 checksum for $xcframework_name.zip in release $VERSION."
echo "Available assets:"
echo "$api_response" | jq -r '.assets[].name'
exit 1
fi
echo "Expected SHA256: $expected_sha256"
# Download the framework. Prefer `gh release download` for authentication.
echo "Downloading from $download_url"
if command -v gh &> /dev/null; then
if ! gh release download "${VERSION}" --repo getsentry/sentry-cocoa --pattern "${xcframework_name}.zip" --dir "$DIR" --clobber; then
echo "Error: Failed to download $xcframework_name via gh CLI"
exit 1
fi
else
if ! curl -L -f --show-error -o "$zip_file" "$download_url"; then
echo "Error: Failed to download $xcframework_name from $download_url"
exit 1
fi
fi
# Verify checksum if we have one.
if [[ -n "$expected_sha256" ]]; then
echo "Verifying checksum..."
local actual_sha256
actual_sha256=$(shasum -a 256 "$zip_file" | awk '{print $1}')
if [[ "$actual_sha256" != "$expected_sha256" ]]; then
echo "Error: SHA256 checksum mismatch!"
echo " Expected: $expected_sha256"
echo " Actual: $actual_sha256"
exit 1
fi
echo "Checksum verified successfully"
fi
# Remove existing framework if present.
if [[ -d "$xcframework_dir" ]]; then
rm -rf "$xcframework_dir"
fi
# Extract only the macos-arm64_arm64e_x86_64 subdirectory.
echo "Extracting $xcframework_name (macOS frameworks only)..."
if ! unzip -q "$zip_file" "${xcframework_name}/macos-arm64_arm64e_x86_64/*" -d "$DIR"; then
echo "Error: Failed to extract framework from zip. Expected path: ${xcframework_name}/macos-arm64_arm64e_x86_64/"
exit 1
fi
echo "Successfully installed $xcframework_name version $VERSION"
}
# Check and download the needed framework.
CURRENT_VERSION=$(get_framework_version "$FRAMEWORK_PATH")
if [[ -z "$CURRENT_VERSION" ]] || [[ "$CURRENT_VERSION" != "$VERSION" ]]; then
if [[ -z "$CURRENT_VERSION" ]]; then
echo "$FRAMEWORK_TYPE framework not found or missing Info.plist"
else
echo "$FRAMEWORK_TYPE framework version mismatch: found $CURRENT_VERSION, expected $VERSION"
fi
download_framework "$XCFRAMEWORK_NAME"
else
echo "$FRAMEWORK_TYPE framework version $VERSION already installed"
fi
echo "Framework up to date"