mirror of
https://github.com/warpdotdev/warp.git
synced 2026-05-06 23:32:51 +08:00
238 lines
6.9 KiB
Bash
Executable File
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"
|