diff --git a/CHANGELOG.md b/CHANGELOG.md index 3147923cf9..8ab951e197 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Don't crash the iOS app when Sentry is initialized with an invalid DSN ([#6825](https://github.com/getsentry/sentry-react-native/pull/6825)) - Populate the Hermes runtime version on JS profiles instead of sending an empty value ([#6817](https://github.com/getsentry/sentry-react-native/pull/6817)) - Mark `@sentry/react-native` as side-effect free so bundlers can tree-shake unused exports ([#6829](https://github.com/getsentry/sentry-react-native/pull/6829)) +- Resolve `@sentry/react-native` from the Android project directory in the Expo plugin `build.gradle` line, instead of the directory where Gradle started ([#6840](https://github.com/getsentry/sentry-react-native/pull/6840)) ## 8.29.0 diff --git a/packages/core/plugin/src/withSentryAndroid.ts b/packages/core/plugin/src/withSentryAndroid.ts index 97478b01ec..18058ccbda 100644 --- a/packages/core/plugin/src/withSentryAndroid.ts +++ b/packages/core/plugin/src/withSentryAndroid.ts @@ -33,14 +33,24 @@ export const withSentryAndroid: ConfigPlugin<{ ]); }; -const resolveSentryReactNativePackageJsonPath = - '["node", "--print", "require(\'path\').dirname(require.resolve(\'@sentry/react-native/package.json\'))"].execute().text.trim()'; +const resolveSentryReactNativePackageJsonPathCommand = + '["node", "--print", "require(\'path\').dirname(require.resolve(\'@sentry/react-native/package.json\'))"]'; +const resolveSentryReactNativePackageJsonPath = `${resolveSentryReactNativePackageJsonPathCommand}.execute(null, rootDir).text.trim()`; +// Without a working directory, node resolves the package from the directory where Gradle started. +const legacyResolveSentryReactNativePackageJsonPath = `${resolveSentryReactNativePackageJsonPathCommand}.execute().text.trim()`; /** * Writes to projectDirectory/android/app/build.gradle, * adding the relevant @sentry/react-native script. */ export function modifyAppBuildGradle(buildGradle: string, disableAutoUpload: boolean = false): string { + if (buildGradle.includes(legacyResolveSentryReactNativePackageJsonPath)) { + return modifyAppBuildGradle( + buildGradle.split(legacyResolveSentryReactNativePackageJsonPath).join(resolveSentryReactNativePackageJsonPath), + disableAutoUpload, + ); + } + if (buildGradle.includes('sentry.gradle.kts')) { if (disableAutoUpload && !buildGradle.includes('shouldSentryAutoUploadGeneral')) { return buildGradle.replace( diff --git a/packages/core/test/expo-plugin/modifyAppBuildGradle.test.ts b/packages/core/test/expo-plugin/modifyAppBuildGradle.test.ts index 53d91b6af9..5c3c18d19c 100644 --- a/packages/core/test/expo-plugin/modifyAppBuildGradle.test.ts +++ b/packages/core/test/expo-plugin/modifyAppBuildGradle.test.ts @@ -4,7 +4,7 @@ import { modifyAppBuildGradle } from '../../plugin/src/withSentryAndroid'; jest.mock('../../plugin/src/logger'); const buildGradleWithSentry = ` -apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle.kts") +apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute(null, rootDir).text.trim(), "sentry.gradle.kts") android { } @@ -16,7 +16,7 @@ android { `; const monoRepoBuildGradleWithSentry = ` -apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle.kts") +apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute(null, rootDir).text.trim(), "sentry.gradle.kts") android { } @@ -28,7 +28,14 @@ android { `; const buildGradleWithOldSentryGradle = ` -apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle") +apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute(null, rootDir).text.trim(), "sentry.gradle") + +android { +} +`; + +const buildGradleWithLegacyResolve = ` +apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle.kts") android { } @@ -65,6 +72,26 @@ describe('Configures Android native project correctly', () => { expect(modifyAppBuildGradle(buildGradleWithOldSentryGradle)).toStrictEqual(buildGradleWithSentry); }); + it('Resolves @sentry/react-native from the Gradle root project directory', () => { + expect(modifyAppBuildGradle(buildGradleWithOutSentry)).toContain('.execute(null, rootDir).text.trim()'); + }); + + it('Migrates the legacy resolve without a working directory to rootDir', () => { + expect(modifyAppBuildGradle(buildGradleWithLegacyResolve)).toStrictEqual(buildGradleWithSentry); + }); + + it('Migrates the legacy resolve and old sentry.gradle reference in one pass', () => { + const legacy = buildGradleWithLegacyResolve.replace('sentry.gradle.kts', 'sentry.gradle'); + expect(modifyAppBuildGradle(legacy)).toStrictEqual(buildGradleWithSentry); + }); + + it('Migrates the legacy resolve and applies disableAutoUpload in one pass', () => { + const result = modifyAppBuildGradle(buildGradleWithLegacyResolve, true); + expect(result).not.toContain('.execute().text.trim()'); + expect(result).toContain('.execute(null, rootDir).text.trim()'); + expect(result).toContain('project.ext.shouldSentryAutoUploadGeneral = { -> return false }'); + }); + it('Migrates old sentry.gradle and applies disableAutoUpload in one pass', () => { const result = modifyAppBuildGradle(buildGradleWithOldSentryGradle, true); expect(result).toContain('sentry.gradle.kts'); @@ -102,7 +129,7 @@ describe('Configures Android native project correctly', () => { it('Does not duplicate override if already present', () => { const gradleWithOverride = ` -apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle.kts") +apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute(null, rootDir).text.trim(), "sentry.gradle.kts") project.ext.shouldSentryAutoUploadGeneral = { -> return false } android { @@ -114,7 +141,7 @@ android { it('Removes override when toggling disableAutoUpload back to false', () => { const gradleWithOverride = ` -apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle.kts") +apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute(null, rootDir).text.trim(), "sentry.gradle.kts") project.ext.shouldSentryAutoUploadGeneral = { -> return false } android {