Skip to content

Commit 6f2a283

Browse files
committed
fix(ios): Add wait logic for dSYM generation in Xcode build phase
1 parent 77018cc commit 6f2a283

6 files changed

Lines changed: 742 additions & 0 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# dSYM Upload Fix - Testing Checklist
2+
3+
## Prerequisites
4+
- [ ] Expo project configured with Sentry
5+
- [ ] EAS CLI installed (`npm install -g eas-cli`)
6+
- [ ] Access to Sentry project settings
7+
- [ ] Ability to build locally or on EAS
8+
9+
## Phase 1: Reproduce Issue (v7.12.1)
10+
11+
### Setup
12+
- [ ] Install `@sentry/react-native@7.12.1`
13+
- [ ] Run `npx expo prebuild --clean`
14+
15+
### Build
16+
- [ ] Run `eas build --platform ios --profile production --local`
17+
- [ ] Save build logs
18+
19+
### Verification
20+
- [ ] Check Sentry Debug Files page
21+
- [ ] Expected: Only framework dSYMs uploaded
22+
- [ ] Expected: Main app shows as "Mach-O Executable" (not "debug companion")
23+
- [ ] Expected: Missing ~145MB dSYM file
24+
25+
### Evidence Captured
26+
- [ ] Screenshot of Sentry Debug Files showing issue
27+
- [ ] Build log showing upload phase
28+
- [ ] Note: Did you see "Upload Debug Symbols to Sentry" in logs?
29+
30+
---
31+
32+
## Phase 2: Test Fix
33+
34+
### Setup
35+
- [ ] Build SDK: `cd /Users/antonis/git/sentry-react-native && yarn build`
36+
- [ ] Link to local version in test project
37+
- [ ] Run `npx expo prebuild --clean`
38+
39+
### Build with Debug Logging
40+
- [ ] Set `SENTRY_DSYM_DEBUG=true`
41+
- [ ] Run `eas build --platform ios --profile production --local`
42+
- [ ] Save build logs
43+
44+
### Check Build Logs For:
45+
- [ ] ✓ "Checking for dSYM files in: [path]"
46+
- [ ] ✓ "DEBUG: DWARF_DSYM_FOLDER_PATH=[path]"
47+
- [ ] ✓ "DEBUG: DWARF_DSYM_FILE_NAME=[filename]"
48+
- [ ] ✓ "Found X dSYM bundle(s)"
49+
- [ ] ✓ "Verified main app dSYM is complete: [filename]"
50+
51+
### If Script Waited:
52+
- [ ] Note: How long did it wait? _____ seconds
53+
- [ ] Note: Which attempt succeeded? _____ / 10
54+
- [ ] Note: Progressive intervals working? (0.5s, 1s, 2s)
55+
56+
### If Script Timed Out:
57+
- [ ] Note: What was in DWARF_DSYM_FOLDER_PATH?
58+
- [ ] Note: Was DWARF_DSYM_FILE_NAME set?
59+
- [ ] **This suggests it's NOT a race condition!**
60+
61+
### Verification in Sentry
62+
- [ ] Check Sentry Debug Files page
63+
- [ ] Expected: Main app dSYM with "debug" tag
64+
- [ ] Expected: File size ~145MB
65+
- [ ] Expected: All framework dSYMs also present
66+
67+
### Evidence Captured
68+
- [ ] Screenshot of Sentry Debug Files showing fix working
69+
- [ ] Build log with debug output
70+
- [ ] Timing information if waited
71+
72+
---
73+
74+
## Analysis
75+
76+
### Issue Confirmed?
77+
- [ ] YES - Issue reproduced with v7.12.1
78+
- [ ] NO - Main app dSYM uploaded fine with v7.12.1
79+
80+
### Fix Works?
81+
- [ ] YES - Main app dSYM uploaded with fix
82+
- [ ] NO - Still missing with fix
83+
84+
### Root Cause Identified?
85+
- [ ] Race condition (script found dSYM after waiting)
86+
- [ ] Path issue (DWARF_DSYM_FOLDER_PATH incorrect)
87+
- [ ] Missing variable (DWARF_DSYM_FILE_NAME not set)
88+
- [ ] Other: _________________________________
89+
90+
### Performance Impact
91+
- Wait time observed: _____ seconds
92+
- [ ] Acceptable (< 5s)
93+
- [ ] Moderate (5-10s)
94+
- [ ] Concerning (> 10s)
95+
96+
---
97+
98+
## Next Steps
99+
100+
### If Fix Works:
101+
- [ ] Run tests: `yarn jest test/expo-plugin test/scripts`
102+
- [ ] Review commit message
103+
- [ ] Ready to commit
104+
105+
### If Fix Doesn't Work:
106+
- [ ] Share debug logs with team
107+
- [ ] Investigate alternative root causes
108+
- [ ] May need different solution
109+
110+
### If Not a Race Condition:
111+
- [ ] Investigate path configuration
112+
- [ ] Check EAS build environment differences
113+
- [ ] Consider alternative fixes (path search, etc.)
114+
115+
---
116+
117+
## Notes
118+
119+
Add any observations, errors, or unexpected behavior:
120+
121+
```
122+
[Your notes here]
123+
```

packages/core/scripts/sentry-xcode-debug-files.sh

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,139 @@ EXTRA_ARGS="$SENTRY_CLI_EXTRA_ARGS $SENTRY_CLI_DEBUG_FILES_UPLOAD_EXTRA_ARGS $IN
5858

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

61+
# Function to wait for dSYM files to be generated
62+
# This addresses a race condition where the upload script runs before dSYM generation completes
63+
wait_for_dsym_files() {
64+
local max_attempts="${SENTRY_DSYM_WAIT_MAX_ATTEMPTS:-10}"
65+
local wait_interval="${SENTRY_DSYM_WAIT_INTERVAL:-2}"
66+
local attempt=1
67+
68+
# Check if we should wait for dSYM files
69+
if [ "$SENTRY_DSYM_WAIT_ENABLED" == "false" ]; then
70+
echo "SENTRY_DSYM_WAIT_ENABLED=false, skipping dSYM wait check"
71+
return 0
72+
fi
73+
74+
# Warn if DWARF_DSYM_FILE_NAME is not set - we can't verify the main app dSYM
75+
if [ -z "$DWARF_DSYM_FILE_NAME" ]; then
76+
echo "warning: DWARF_DSYM_FILE_NAME not set, cannot verify main app dSYM specifically"
77+
echo "warning: Will proceed when any dSYM bundle is found"
78+
fi
79+
80+
echo "Checking for dSYM files in: $DWARF_DSYM_FOLDER_PATH"
81+
82+
# Debug information to help diagnose issues
83+
if [ -n "${SENTRY_DSYM_DEBUG}" ]; then
84+
echo "DEBUG: DWARF_DSYM_FOLDER_PATH=$DWARF_DSYM_FOLDER_PATH"
85+
echo "DEBUG: DWARF_DSYM_FILE_NAME=$DWARF_DSYM_FILE_NAME"
86+
echo "DEBUG: PRODUCT_NAME=$PRODUCT_NAME"
87+
if [ -d "$DWARF_DSYM_FOLDER_PATH" ]; then
88+
echo "DEBUG: Contents of dSYM folder:"
89+
ls -la "$DWARF_DSYM_FOLDER_PATH" 2>/dev/null || echo "Cannot list folder"
90+
else
91+
echo "DEBUG: dSYM folder does not exist yet"
92+
fi
93+
fi
94+
95+
while [ $attempt -le $max_attempts ]; do
96+
# Check if the dSYM folder exists
97+
if [ -d "$DWARF_DSYM_FOLDER_PATH" ]; then
98+
# Check if there are any .dSYM bundles in the folder
99+
local dsym_count=$(find "$DWARF_DSYM_FOLDER_PATH" -name "*.dSYM" -type d 2>/dev/null | wc -l | tr -d ' ')
100+
101+
if [ "$dsym_count" -gt 0 ]; then
102+
echo "Found $dsym_count dSYM bundle(s) in $DWARF_DSYM_FOLDER_PATH"
103+
104+
# If DWARF_DSYM_FILE_NAME is set, verify the main app dSYM exists and is complete
105+
if [ -n "$DWARF_DSYM_FILE_NAME" ]; then
106+
local main_dsym="$DWARF_DSYM_FOLDER_PATH/$DWARF_DSYM_FILE_NAME"
107+
108+
if [ -d "$main_dsym" ]; then
109+
# Directory exists, now verify the actual DWARF binary exists inside
110+
local dwarf_dir="$main_dsym/Contents/Resources/DWARF"
111+
112+
if [ -d "$dwarf_dir" ]; then
113+
# Check if there are any files in the DWARF directory
114+
local dwarf_files=$(find "$dwarf_dir" -type f 2>/dev/null | head -1)
115+
116+
if [ -n "$dwarf_files" ]; then
117+
# Verify the DWARF file is not empty (still being written)
118+
local dwarf_size=$(find "$dwarf_dir" -type f -size +0 2>/dev/null | head -1)
119+
120+
if [ -n "$dwarf_size" ]; then
121+
echo "Verified main app dSYM is complete: $DWARF_DSYM_FILE_NAME"
122+
return 0
123+
else
124+
echo "Main app dSYM DWARF binary is empty (still being written): $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
125+
fi
126+
else
127+
echo "Main app dSYM DWARF directory is empty: $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
128+
fi
129+
else
130+
echo "Main app dSYM structure incomplete (missing DWARF directory): $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
131+
fi
132+
else
133+
echo "Main app dSYM not found yet: $DWARF_DSYM_FILE_NAME (attempt $attempt/$max_attempts)"
134+
fi
135+
else
136+
# DWARF_DSYM_FILE_NAME not set, check if any dSYM has valid DWARF content
137+
# This is less strict but better than nothing
138+
local has_valid_dsym=false
139+
for dsym in "$DWARF_DSYM_FOLDER_PATH"/*.dSYM; do
140+
if [ -d "$dsym/Contents/Resources/DWARF" ]; then
141+
local dwarf_files=$(find "$dsym/Contents/Resources/DWARF" -type f -size +0 2>/dev/null | head -1)
142+
if [ -n "$dwarf_files" ]; then
143+
has_valid_dsym=true
144+
break
145+
fi
146+
fi
147+
done
148+
149+
if [ "$has_valid_dsym" = true ]; then
150+
echo "Found dSYM bundle(s) with valid DWARF content"
151+
return 0
152+
else
153+
echo "Found dSYM bundle(s) but none have complete DWARF content yet (attempt $attempt/$max_attempts)"
154+
fi
155+
fi
156+
else
157+
echo "No dSYM bundles found yet in $DWARF_DSYM_FOLDER_PATH (attempt $attempt/$max_attempts)"
158+
fi
159+
else
160+
echo "dSYM folder does not exist yet: $DWARF_DSYM_FOLDER_PATH (attempt $attempt/$max_attempts)"
161+
fi
162+
163+
if [ $attempt -lt $max_attempts ]; then
164+
# Progressive backoff: quick checks first, longer waits later
165+
# Attempts 1-3: 0.5s (total 1.5s)
166+
# Attempts 4-6: 1s (total 3s)
167+
# Attempts 7+: 2s (remaining time)
168+
local current_interval="$wait_interval"
169+
if [ -z "${SENTRY_DSYM_WAIT_INTERVAL}" ]; then
170+
# Only use progressive intervals if user hasn't set custom interval
171+
if [ $attempt -le 3 ]; then
172+
current_interval=0.5
173+
elif [ $attempt -le 6 ]; then
174+
current_interval=1
175+
else
176+
current_interval=2
177+
fi
178+
fi
179+
180+
echo "Waiting ${current_interval}s for dSYM generation to complete..."
181+
sleep $current_interval
182+
fi
183+
184+
attempt=$((attempt + 1))
185+
done
186+
187+
# Timeout reached
188+
echo "warning: Timeout waiting for dSYM files after $((max_attempts * wait_interval))s"
189+
echo "warning: This may result in incomplete debug symbol uploads"
190+
echo "warning: To disable this check, set SENTRY_DSYM_WAIT_ENABLED=false"
191+
return 1
192+
}
193+
61194
XCODE_BUILD_CONFIGURATION="${CONFIGURATION}"
62195

63196
if [ "$SENTRY_DISABLE_AUTO_UPLOAD" == true ]; then
@@ -67,6 +200,12 @@ elif [ "$SENTRY_DISABLE_XCODE_DEBUG_UPLOAD" == true ]; then
67200
elif echo "$XCODE_BUILD_CONFIGURATION" | grep -iq "debug"; then # case insensitive check for "debug"
68201
echo "Skipping debug files upload for *Debug* configuration"
69202
else
203+
# Wait for dSYM files to be generated (addresses race condition in EAS builds)
204+
# Don't fail the script if wait times out - we still want to attempt upload
205+
set +e
206+
wait_for_dsym_files
207+
set -e
208+
70209
# 'warning:' triggers a warning in Xcode, 'error:' triggers an error
71210
set +x +e # disable printing commands otherwise we might print `error:` by accident and allow continuing on error
72211
SENTRY_UPLOAD_COMMAND_OUTPUT=$(/bin/sh -c "\"$LOCAL_NODE_BINARY\" $UPLOAD_DEBUG_FILES" 2>&1)

0 commit comments

Comments
 (0)