diff --git a/CHANGELOG.md b/CHANGELOG.md index b73dbd4c68..256af5bcd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ ## Unreleased +### Fixes + +- Fix `SENTRY_ALLOW_FAILURE` environment variable not being respected in Xcode build scripts ([#5616](https://github.com/getsentry/sentry-react-native/pull/5616)) +- 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)) + ### Features - Extends the experimental support of UI profiling to iOS ([#5611](https://github.com/getsentry/sentry-react-native/pull/5611)) @@ -53,10 +58,6 @@ - [changelog](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/main/CHANGELOG.md#490) - [diff](https://github.com/getsentry/sentry-javascript-bundler-plugins/compare/4.8.0...4.9.0) -### Fixes - -- Fix `SENTRY_ALLOW_FAILURE` environment variable not being respected in Xcode build scripts ([#5616](https://github.com/getsentry/sentry-react-native/pull/5616)) - ## 7.11.0 ### Features diff --git a/packages/core/plugin/src/withSentryIOS.ts b/packages/core/plugin/src/withSentryIOS.ts index e10f820282..0c2ee9a3b9 100644 --- a/packages/core/plugin/src/withSentryIOS.ts +++ b/packages/core/plugin/src/withSentryIOS.ts @@ -23,6 +23,10 @@ export const withSentryIOS: ConfigPlugin = (config, sentryProperties: st xcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, { shellPath: '/bin/sh', shellScript: `/bin/sh ${SENTRY_REACT_NATIVE_XCODE_DEBUG_FILES_PATH}`, + inputPaths: [ + '"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"', + '"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"', + ], }); } diff --git a/packages/core/test/expo-plugin/modifyXcodeProject.test.ts b/packages/core/test/expo-plugin/modifyXcodeProject.test.ts index bbd570fdf9..fc0c2e7a99 100644 --- a/packages/core/test/expo-plugin/modifyXcodeProject.test.ts +++ b/packages/core/test/expo-plugin/modifyXcodeProject.test.ts @@ -77,3 +77,101 @@ describe('Configures iOS native project correctly', () => { expect(warnOnce).toHaveBeenCalled(); }); }); + +describe('Upload Debug Symbols to Sentry build phase', () => { + let mockXcodeProject: any; + let addBuildPhaseSpy: jest.Mock; + const expectedShellScript = + "/bin/sh `${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`"; + + const getOptions = () => { + const callArgs = addBuildPhaseSpy.mock.calls[0]; + return callArgs[4]; + }; + + beforeEach(() => { + addBuildPhaseSpy = jest.fn(); + mockXcodeProject = { + pbxItemByComment: jest.fn().mockReturnValue(null), + addBuildPhase: addBuildPhaseSpy, + }; + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('creates Upload Debug Symbols build phase with correct shell script', () => { + mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, { + shellPath: '/bin/sh', + shellScript: expectedShellScript, + }); + + expect(addBuildPhaseSpy).toHaveBeenCalledWith( + [], + 'PBXShellScriptBuildPhase', + 'Upload Debug Symbols to Sentry', + null, + { + shellPath: '/bin/sh', + shellScript: expectedShellScript, + }, + ); + }); + + it('does not include inputPaths in options before fix', () => { + mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, { + shellPath: '/bin/sh', + shellScript: expectedShellScript, + }); + + const options = getOptions(); + + expect(options.inputPaths).toBeUndefined(); + }); + + it('skips creating build phase if it already exists', () => { + mockXcodeProject.pbxItemByComment = jest.fn().mockReturnValue({ + shellScript: 'existing', + }); + + expect(addBuildPhaseSpy).not.toHaveBeenCalled(); + }); + + it('includes inputPaths with escaped quotes to avoid pbxproj serialization issues', () => { + mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, { + shellPath: '/bin/sh', + shellScript: expectedShellScript, + inputPaths: [ + '"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"', + '"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"', + ], + }); + + const options = getOptions(); + + expect(options.inputPaths).toBeDefined(); + expect(options.inputPaths).toHaveLength(2); + }); + + it('inputPaths values are wrapped in escaped quotes', () => { + mockXcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', null, { + shellPath: '/bin/sh', + shellScript: expectedShellScript, + inputPaths: [ + '"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"', + '"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"', + ], + }); + + const options = getOptions(); + + // Verify paths are wrapped in quotes to prevent pbxproj corruption + expect(options.inputPaths[0]).toMatch(/^".*"$/); + expect(options.inputPaths[1]).toMatch(/^".*"$/); + expect(options.inputPaths[0]).toBe( + '"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Resources/DWARF/$(PRODUCT_NAME)"', + ); + expect(options.inputPaths[1]).toBe('"$(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)"'); + }); +});