Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions packages/core/scripts/sentry-xcode-debug-files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,139 @@ EXTRA_ARGS="$SENTRY_CLI_EXTRA_ARGS $SENTRY_CLI_DEBUG_FILES_UPLOAD_EXTRA_ARGS $IN

UPLOAD_DEBUG_FILES="\"$SENTRY_CLI_EXECUTABLE\" debug-files upload $EXTRA_ARGS \"$DWARF_DSYM_FOLDER_PATH\""

# Function to wait for dSYM files to be generated
# This addresses a race condition where the upload script runs before dSYM generation completes
wait_for_dsym_files() {
local max_attempts="${SENTRY_DSYM_WAIT_MAX_ATTEMPTS:-10}"
local wait_interval="${SENTRY_DSYM_WAIT_INTERVAL:-2}"
local attempt=1

# Check if we should wait for dSYM files
if [ "$SENTRY_DSYM_WAIT_ENABLED" == "false" ]; then
echo "SENTRY_DSYM_WAIT_ENABLED=false, skipping dSYM wait check"
return 0
fi

# Warn if DWARF_DSYM_FILE_NAME is not set - we can't verify the main app dSYM
if [ -z "$DWARF_DSYM_FILE_NAME" ]; then
echo "warning: DWARF_DSYM_FILE_NAME not set, cannot verify main app dSYM specifically"
echo "warning: Will proceed when any dSYM bundle is found"
fi

echo "Checking for dSYM files in: $DWARF_DSYM_FOLDER_PATH"

# Debug information to help diagnose issues
if [ -n "${SENTRY_DSYM_DEBUG}" ]; then
echo "DEBUG: DWARF_DSYM_FOLDER_PATH=$DWARF_DSYM_FOLDER_PATH"
echo "DEBUG: DWARF_DSYM_FILE_NAME=$DWARF_DSYM_FILE_NAME"
echo "DEBUG: PRODUCT_NAME=$PRODUCT_NAME"
if [ -d "$DWARF_DSYM_FOLDER_PATH" ]; then
echo "DEBUG: Contents of dSYM folder:"
ls -la "$DWARF_DSYM_FOLDER_PATH" 2>/dev/null || echo "Cannot list folder"
else
echo "DEBUG: dSYM folder does not exist yet"
fi
fi

while [ $attempt -le $max_attempts ]; do
# Check if the dSYM folder exists
if [ -d "$DWARF_DSYM_FOLDER_PATH" ]; then
# Check if there are any .dSYM bundles in the folder
local dsym_count=$(find "$DWARF_DSYM_FOLDER_PATH" -name "*.dSYM" -type d 2>/dev/null | wc -l | tr -d ' ')

if [ "$dsym_count" -gt 0 ]; then
echo "Found $dsym_count dSYM bundle(s) in $DWARF_DSYM_FOLDER_PATH"

# If DWARF_DSYM_FILE_NAME is set, verify the main app dSYM exists and is complete
if [ -n "$DWARF_DSYM_FILE_NAME" ]; then
local main_dsym="$DWARF_DSYM_FOLDER_PATH/$DWARF_DSYM_FILE_NAME"

if [ -d "$main_dsym" ]; then
# Directory exists, now verify the actual DWARF binary exists inside
local dwarf_dir="$main_dsym/Contents/Resources/DWARF"

if [ -d "$dwarf_dir" ]; then
# Check if there are any files in the DWARF directory
local dwarf_files=$(find "$dwarf_dir" -type f 2>/dev/null | head -1)

if [ -n "$dwarf_files" ]; then
# Verify the DWARF file is not empty (still being written)
local dwarf_size=$(find "$dwarf_dir" -type f -size +0 2>/dev/null | head -1)

if [ -n "$dwarf_size" ]; then
echo "Verified main app dSYM is complete: $DWARF_DSYM_FILE_NAME"
return 0
else
echo "Main app dSYM DWARF binary is empty (still being written): $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
fi
else
echo "Main app dSYM DWARF directory is empty: $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
fi
else
echo "Main app dSYM structure incomplete (missing DWARF directory): $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
fi
else
echo "Main app dSYM not found yet: $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
fi
else
# DWARF_DSYM_FILE_NAME not set, check if any dSYM has valid DWARF content
# This is less strict but better than nothing
local has_valid_dsym=false
for dsym in "$DWARF_DSYM_FOLDER_PATH"/*.dSYM; do
if [ -d "$dsym/Contents/Resources/DWARF" ]; then
local dwarf_files=$(find "$dsym/Contents/Resources/DWARF" -type f -size +0 2>/dev/null | head -1)
if [ -n "$dwarf_files" ]; then
has_valid_dsym=true
break
fi
fi
done

if [ "$has_valid_dsym" = true ]; then
echo "Found dSYM bundle(s) with valid DWARF content"
return 0
else
echo "Found dSYM bundle(s) but none have complete DWARF content yet (attempt $attempt/$max_attempts)"
fi
fi
else
echo "No dSYM bundles found yet in $DWARF_DSYM_FOLDER_PATH (attempt $attempt/$max_attempts)"
fi
else
echo "dSYM folder does not exist yet: $DWARF_DSYM_FOLDER_PATH (attempt $attempt/$max_attempts)"
fi

if [ $attempt -lt $max_attempts ]; then
# Progressive backoff: quick checks first, longer waits later
# Attempts 1-3: 0.5s (total 1.5s)
# Attempts 4-6: 1s (total 3s)
# Attempts 7+: 2s (remaining time)
local current_interval="$wait_interval"
if [ -z "${SENTRY_DSYM_WAIT_INTERVAL}" ]; then
# Only use progressive intervals if user hasn't set custom interval
if [ $attempt -le 3 ]; then
current_interval=0.5
elif [ $attempt -le 6 ]; then
current_interval=1
else
current_interval=2
fi
fi

echo "Waiting ${current_interval}s for dSYM generation to complete..."
sleep $current_interval
fi

attempt=$((attempt + 1))
done

# Timeout reached
echo "warning: Timeout waiting for dSYM files after $((max_attempts * wait_interval))s"
echo "warning: This may result in incomplete debug symbol uploads"
echo "warning: To disable this check, set SENTRY_DSYM_WAIT_ENABLED=false"
return 1
}

XCODE_BUILD_CONFIGURATION="${CONFIGURATION}"

if [ "$SENTRY_DISABLE_AUTO_UPLOAD" == true ]; then
Expand All @@ -67,6 +200,12 @@ elif [ "$SENTRY_DISABLE_XCODE_DEBUG_UPLOAD" == true ]; then
elif echo "$XCODE_BUILD_CONFIGURATION" | grep -iq "debug"; then # case insensitive check for "debug"
echo "Skipping debug files upload for *Debug* configuration"
else
# Wait for dSYM files to be generated (addresses race condition in EAS builds)
# Don't fail the script if wait times out - we still want to attempt upload
set +e
wait_for_dsym_files
set -e

# 'warning:' triggers a warning in Xcode, 'error:' triggers an error
set +x +e # disable printing commands otherwise we might print `error:` by accident and allow continuing on error
SENTRY_UPLOAD_COMMAND_OUTPUT=$(/bin/sh -c "\"$LOCAL_NODE_BINARY\" $UPLOAD_DEBUG_FILES" 2>&1)
Expand Down
125 changes: 125 additions & 0 deletions packages/core/scripts/test-dsym-fix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/bin/bash
# Test script to verify dSYM upload fix
# Usage: ./test-dsym-fix.sh [test-project-path]

set -e

PROJECT_PATH="${1:-.}"
SDK_PATH="$(cd "$(dirname "$0")/../../.." && pwd)"

echo "=== Sentry React Native dSYM Fix Testing ==="
echo ""
echo "SDK Path: $SDK_PATH"
echo "Project Path: $PROJECT_PATH"
echo ""

# Function to check Sentry debug files
check_sentry_debug_files() {
echo "=== Checking Sentry Debug Files ==="
echo ""
echo "Please check Sentry Debug Files manually:"
echo "1. Go to: https://sentry.io"
echo "2. Navigate to: Settings > Projects > [Your Project] > Debug Files"
echo "3. Look for recent uploads with 'debug' tag"
echo ""
echo "Expected to see:"
echo " ✓ Main app dSYM with 'debug' tag (~145MB)"
echo " ✓ Framework dSYMs"
echo ""
read -p "Press Enter to continue..."
}

# Test with current version
test_current_version() {
echo "=== Phase 1: Testing with v7.12.1 (current stable) ==="
echo ""

cd "$PROJECT_PATH"

echo "Installing @sentry/react-native@7.12.1..."
yarn add @sentry/react-native@7.12.1 || npm install @sentry/react-native@7.12.1

echo ""
echo "Cleaning and regenerating native code..."
npx expo prebuild --clean

echo ""
echo "Building with EAS..."
echo "Watch for 'Upload Debug Symbols to Sentry' in logs"
echo ""

eas build --platform ios --profile production --local 2>&1 | tee build-v7.12.1.log

echo ""
check_sentry_debug_files
}

# Test with our fix
test_with_fix() {
echo "=== Phase 2: Testing with dSYM wait fix ==="
echo ""

cd "$SDK_PATH"
echo "Building SDK..."
yarn build

cd "$PROJECT_PATH"

echo ""
echo "Linking to local SDK..."
yarn link "$SDK_PATH/packages/core" || npm link "$SDK_PATH/packages/core"

echo ""
echo "Cleaning and regenerating native code..."
npx expo prebuild --clean

echo ""
echo "Building with debug logging enabled..."
echo "Look for:"
echo " - 'DEBUG: DWARF_DSYM_FOLDER_PATH=...'"
echo " - 'DEBUG: DWARF_DSYM_FILE_NAME=...'"
echo " - 'Verified main app dSYM is complete'"
echo ""

SENTRY_DSYM_DEBUG=true eas build --platform ios --profile production --local 2>&1 | tee build-with-fix.log

echo ""
check_sentry_debug_files
}

# Main menu
echo "Choose test to run:"
echo "1) Test current v7.12.1 (reproduce issue)"
echo "2) Test with fix (verify solution)"
echo "3) Run both tests"
echo ""
read -p "Enter choice [1-3]: " choice

case $choice in
1)
test_current_version
;;
2)
test_with_fix
;;
3)
test_current_version
echo ""
echo "========================================"
echo ""
test_with_fix
;;
*)
echo "Invalid choice"
exit 1
;;
esac

echo ""
echo "=== Testing Complete ==="
echo ""
echo "Build logs saved:"
echo " - build-v7.12.1.log (if tested)"
echo " - build-with-fix.log (if tested)"
echo ""
echo "Please compare the results in Sentry Debug Files"
61 changes: 61 additions & 0 deletions packages/core/scripts/test-dsym-wait.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
# Manual test script for dSYM wait functionality
# This simulates the wait behavior without needing a full Xcode build

set -x

# Create a test directory
TEST_DIR="/tmp/sentry-dsym-wait-test-$$"
mkdir -p "$TEST_DIR"

echo "=== Test 1: dSYM appears immediately ==="
DSYM_DIR="$TEST_DIR/test1"
mkdir -p "$DSYM_DIR/TestApp.app.dSYM"
export DWARF_DSYM_FOLDER_PATH="$DSYM_DIR"
export DWARF_DSYM_FILE_NAME="TestApp.app.dSYM"
export SENTRY_DSYM_WAIT_MAX_ATTEMPTS=3
export SENTRY_DSYM_WAIT_INTERVAL=1

# Source the wait function
source "$(dirname "$0")/sentry-xcode-debug-files.sh" 2>/dev/null || {
# If sourcing fails, extract just the wait function
eval "$(sed -n '/^wait_for_dsym_files()/,/^}/p' "$(dirname "$0")/sentry-xcode-debug-files.sh")"
}

wait_for_dsym_files
echo "Test 1 result: $?"
echo ""

echo "=== Test 2: dSYM appears after delay ==="
DSYM_DIR2="$TEST_DIR/test2"
mkdir -p "$DSYM_DIR2"
export DWARF_DSYM_FOLDER_PATH="$DSYM_DIR2"
export DWARF_DSYM_FILE_NAME="DelayedApp.app.dSYM"

# Create dSYM in background after 2 seconds
(sleep 2 && mkdir -p "$DSYM_DIR2/DelayedApp.app.dSYM" && echo "Background: Created dSYM") &

wait_for_dsym_files
echo "Test 2 result: $?"
echo ""

echo "=== Test 3: dSYM never appears (timeout) ==="
DSYM_DIR3="$TEST_DIR/test3"
mkdir -p "$DSYM_DIR3"
export DWARF_DSYM_FOLDER_PATH="$DSYM_DIR3"
export DWARF_DSYM_FILE_NAME="NeverExists.app.dSYM"
export SENTRY_DSYM_WAIT_MAX_ATTEMPTS=2

wait_for_dsym_files
echo "Test 3 result: $?"
echo ""

echo "=== Test 4: Wait disabled ==="
export SENTRY_DSYM_WAIT_ENABLED=false
wait_for_dsym_files
echo "Test 4 result: $?"
echo ""

# Cleanup
rm -rf "$TEST_DIR"
echo "=== All tests complete ==="
Loading
Loading