Skip to content

Commit d4234fe

Browse files
committed
Merge branch 'main' into v8
# Conflicts: # CHANGELOG.md
2 parents be1aafb + 429cf8f commit d4234fe

3 files changed

Lines changed: 103 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
### Fixes
4848

4949
- Fix `SENTRY_ALLOW_FAILURE` environment variable not being respected in Xcode build scripts ([#5616](https://github.com/getsentry/sentry-react-native/pull/5616))
50+
- Fix iOS dSYM upload for main app in Expo EAS builds by adding inputPaths to build phase ([#5617](https://github.com/getsentry/sentry-react-native/pull/5617))
5051

5152
### Dependencies
5253

packages/core/plugin/src/withSentryIOS.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ export const withSentryIOS: ConfigPlugin<{ sentryProperties: string; useNativeIn
2828
xcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, {
2929
shellPath: '/bin/sh',
3030
shellScript: `/bin/sh ${SENTRY_REACT_NATIVE_XCODE_DEBUG_FILES_PATH}`,
31+
inputPaths: [
32+
'"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"',
33+
'"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"',
34+
],
3135
});
3236
}
3337

packages/core/test/expo-plugin/modifyXcodeProject.test.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,101 @@ describe('Configures iOS native project correctly', () => {
7777
expect(warnOnce).toHaveBeenCalled();
7878
});
7979
});
80+
81+
describe('Upload Debug Symbols to Sentry build phase', () => {
82+
let mockXcodeProject: any;
83+
let addBuildPhaseSpy: jest.Mock;
84+
const expectedShellScript =
85+
"/bin/sh `${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`";
86+
87+
const getOptions = () => {
88+
const callArgs = addBuildPhaseSpy.mock.calls[0];
89+
return callArgs[4];
90+
};
91+
92+
beforeEach(() => {
93+
addBuildPhaseSpy = jest.fn();
94+
mockXcodeProject = {
95+
pbxItemByComment: jest.fn().mockReturnValue(null),
96+
addBuildPhase: addBuildPhaseSpy,
97+
};
98+
});
99+
100+
afterEach(() => {
101+
jest.clearAllMocks();
102+
});
103+
104+
it('creates Upload Debug Symbols build phase with correct shell script', () => {
105+
mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, {
106+
shellPath: '/bin/sh',
107+
shellScript: expectedShellScript,
108+
});
109+
110+
expect(addBuildPhaseSpy).toHaveBeenCalledWith(
111+
[],
112+
'PBXShellScriptBuildPhase',
113+
'Upload Debug Symbols to Sentry',
114+
null,
115+
{
116+
shellPath: '/bin/sh',
117+
shellScript: expectedShellScript,
118+
},
119+
);
120+
});
121+
122+
it('does not include inputPaths in options before fix', () => {
123+
mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, {
124+
shellPath: '/bin/sh',
125+
shellScript: expectedShellScript,
126+
});
127+
128+
const options = getOptions();
129+
130+
expect(options.inputPaths).toBeUndefined();
131+
});
132+
133+
it('skips creating build phase if it already exists', () => {
134+
mockXcodeProject.pbxItemByComment = jest.fn().mockReturnValue({
135+
shellScript: 'existing',
136+
});
137+
138+
expect(addBuildPhaseSpy).not.toHaveBeenCalled();
139+
});
140+
141+
it('includes inputPaths with escaped quotes to avoid pbxproj serialization issues', () => {
142+
mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, {
143+
shellPath: '/bin/sh',
144+
shellScript: expectedShellScript,
145+
inputPaths: [
146+
'"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"',
147+
'"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"',
148+
],
149+
});
150+
151+
const options = getOptions();
152+
153+
expect(options.inputPaths).toBeDefined();
154+
expect(options.inputPaths).toHaveLength(2);
155+
});
156+
157+
it('inputPaths values are wrapped in escaped quotes', () => {
158+
mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, {
159+
shellPath: '/bin/sh',
160+
shellScript: expectedShellScript,
161+
inputPaths: [
162+
'"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"',
163+
'"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"',
164+
],
165+
});
166+
167+
const options = getOptions();
168+
169+
// Verify paths are wrapped in quotes to prevent pbxproj corruption
170+
expect(options.inputPaths[0]).toMatch(/^".*"$/);
171+
expect(options.inputPaths[1]).toMatch(/^".*"$/);
172+
expect(options.inputPaths[0]).toBe(
173+
'"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"',
174+
);
175+
expect(options.inputPaths[1]).toBe('"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"');
176+
});
177+
});

0 commit comments

Comments
 (0)