diff --git a/packages/react-native-cli/src/lib/Xcode.ts b/packages/react-native-cli/src/lib/Xcode.ts index e7d77c232d..dc7adc5e41 100644 --- a/packages/react-native-cli/src/lib/Xcode.ts +++ b/packages/react-native-cli/src/lib/Xcode.ts @@ -6,10 +6,7 @@ import xcode, { Project } from 'xcode' const DOCS_LINK = 'https://docs.bugsnag.com/platforms/react-native/react-native/showing-full-stacktraces/#ios' const UNLOCATED_PROJ_MSG = `The Xcode project was not in the expected location and so couldn't be updated automatically. -Update the "Bundle React Native Code And Images" build phase with the following environment variables: -export EXTRA_PACKAGER_ARGS="--sourcemap-output $TMPDIR/$(md5 -qs "$CONFIGURATION_BUILD_DIR")-main.jsbundle.map"" - -See ${DOCS_LINK} for more information` +Please see ${DOCS_LINK} for more information` const EXTRA_PACKAGER_ARGS = ['$(SRCROOT)/.xcode.env.local', '$(SRCROOT)/.xcode.env'] @@ -36,10 +33,11 @@ export async function updateXcodeProject (projectRoot: string, endpoint: string| logger.info('Ensuring React Native build phase outputs source maps') const didUpdate = await updateBuildReactNativeTask(buildPhaseMap, logger) + const didUpdateEnv = await updateXcodeEnv(iosDir, logger) logger.info('Adding build phase to upload source maps to Bugsnag') const didAdd = await addUploadSourceMapsTask(proj, buildPhaseMap, endpoint, logger) - const didChange = didUpdate || didAdd + const didChange = didUpdate || didAdd || didUpdateEnv if (!didChange) return @@ -76,17 +74,13 @@ async function addUploadSourceMapsTask ( ): Promise { for (const shellBuildPhaseKey in buildPhaseMap) { const phase = buildPhaseMap[shellBuildPhaseKey] - if (typeof phase.shellScript === 'string' && phase.shellScript.includes('bugsnag-react-native-xcode.sh')) { + if (typeof phase.shellScript === 'string' && (phase.shellScript.includes('bugsnag-react-native-xcode.sh') || phase.shellScript.includes('npm run bugsnag:upload-ios'))) { logger.warn('An "Upload source maps to Bugsnag" build phase already exists') return false } } - let shellScript = 'SOURCE_MAP="$TMPDIR/$(md5 -qs "$CONFIGURATION_BUILD_DIR")-main.jsbundle.map" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh' - - if (endpoint) { - shellScript = `export ENDPOINT='${endpoint}'\\n${shellScript}` - } + const shellScript = 'npm run bugsnag:upload-ios' proj.addBuildPhase( [], @@ -110,3 +104,38 @@ function addExtraPackagerArgs (phaseId: string, existingInputFiles: string[], lo function arrayContainsElements (mainArray: any[], subArray: any[]): boolean { return subArray.every(element => mainArray.some(mainElement => mainElement === element)) } + +async function updateXcodeEnv (iosDir: string, logger: Logger): Promise { + const searchString = 'SOURCEMAP_FILE=' + const sourceMapFilePath = 'ios/build/sourcemaps/main.jsbundle.map' + const envFilePath = path.join(iosDir, '.xcode.env') + + try { + // Check if the file exists + await fs.stat(envFilePath) + + // If the file exists, read its content + const xcodeEnvData = await fs.readFile(envFilePath, 'utf8') + + if (xcodeEnvData.includes(searchString)) { + logger.warn(`The .xcode.env file already contains a section for "${searchString}"`) + return false + } else { + // Append the new data to the existing content + const newData = `${xcodeEnvData}\n\n# React Native Source Map File\nexport ${searchString}${sourceMapFilePath}` + await fs.writeFile(envFilePath, newData, 'utf8') + return true + } + } catch (error) { + // If the file doesn't exist, create it + if (error.code === 'ENOENT') { + const newData = `export NODE_BINARY=$(command -v node)\n# React Native Source Map File\nexport ${searchString}${sourceMapFilePath}` + await fs.writeFile(envFilePath, newData, 'utf8') + return true + } else { + // Other error occurred + console.error(`Error updating .xcode.env file: ${error.message}`) + return false + } + } +}