Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

## Unreleased

### Fixes

- Add `SENTRY_PROJECT_ROOT` env var to override project root in Xcode build phase scripts for monorepo setups ([#5961](https://github.com/getsentry/sentry-react-native/pull/5961))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! We should also document this on sentry docs

Copy link
Copy Markdown
Contributor Author

@antonis antonis Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened a PR for this getsentry/sentry-docs#17269 and updated the PR description


### Features

- Enable "Open Sentry" button in Playground for Expo apps ([#5947](https://github.com/getsentry/sentry-react-native/pull/5947))
Expand Down
5 changes: 4 additions & 1 deletion packages/core/scripts/sentry-xcode-debug-files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ set -e
LOCAL_NODE_BINARY=${NODE_BINARY:-node}

# The project root by default is one level up from the ios directory
RN_PROJECT_ROOT="${PROJECT_DIR}/.."
# SENTRY_PROJECT_ROOT can be set to override this for monorepo setups
# where the ios directory is not directly under the project root.
# See: https://github.com/getsentry/sentry-react-native/issues/2880
RN_PROJECT_ROOT="${SENTRY_PROJECT_ROOT:-${PROJECT_DIR}/..}"

[ -z "$SENTRY_PROPERTIES" ] && export SENTRY_PROPERTIES=sentry.properties
[ -z "$SENTRY_DOTENV_PATH" ] && [ -f "$RN_PROJECT_ROOT/.env.sentry-build-plugin" ] && export SENTRY_DOTENV_PATH="$RN_PROJECT_ROOT/.env.sentry-build-plugin"
Expand Down
5 changes: 4 additions & 1 deletion packages/core/scripts/sentry-xcode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ set -x -e
LOCAL_NODE_BINARY=${NODE_BINARY:-node}

# The project root by default is one level up from the ios directory
RN_PROJECT_ROOT="${PROJECT_DIR}/.."
# SENTRY_PROJECT_ROOT can be set to override this for monorepo setups
# where the ios directory is not directly under the project root.
# See: https://github.com/getsentry/sentry-react-native/issues/2880
RN_PROJECT_ROOT="${SENTRY_PROJECT_ROOT:-${PROJECT_DIR}/..}"

[ -z "$SENTRY_PROPERTIES" ] && export SENTRY_PROPERTIES=sentry.properties
[ -z "$SENTRY_DOTENV_PATH" ] && [ -f "$RN_PROJECT_ROOT/.env.sentry-build-plugin" ] && export SENTRY_DOTENV_PATH="$RN_PROJECT_ROOT/.env.sentry-build-plugin"
Expand Down
76 changes: 76 additions & 0 deletions packages/core/test/scripts/sentry-xcode-scripts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,82 @@ describe('sentry-xcode.sh', () => {
expect(result.stdout).toContain('skipping sourcemaps upload');
});

describe('SENTRY_PROJECT_ROOT override', () => {
it('resolves SOURCEMAP_FILE relative to SENTRY_PROJECT_ROOT instead of PROJECT_DIR/..', () => {
const customRoot = path.join(tempDir, 'monorepo-package');
fs.mkdirSync(customRoot, { recursive: true });

const echoScript = path.join(tempDir, 'mock-sentry-cli-echo-sourcemap.js');
fs.writeFileSync(
echoScript,
`
const sourcemapFile = process.env.SOURCEMAP_FILE || 'not-set';
console.log('SOURCEMAP_FILE=' + sourcemapFile);
process.exit(0);
`,
);

const result = runScript({
SENTRY_PROJECT_ROOT: customRoot,
SENTRY_CLI_EXECUTABLE: echoScript,
SOURCEMAP_FILE: 'relative/path.map',
});

const expectedPath = path.join(customRoot, 'relative/path.map');
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain(`SOURCEMAP_FILE=${expectedPath}`);
});

it('resolves SOURCEMAP_FILE relative to PROJECT_DIR/.. when SENTRY_PROJECT_ROOT is not set', () => {
const echoScript = path.join(tempDir, 'mock-sentry-cli-echo-sourcemap.js');
fs.writeFileSync(
echoScript,
`
const sourcemapFile = process.env.SOURCEMAP_FILE || 'not-set';
console.log('SOURCEMAP_FILE=' + sourcemapFile);
process.exit(0);
`,
);

const result = runScript({
SENTRY_CLI_EXECUTABLE: echoScript,
SOURCEMAP_FILE: 'relative/path.map',
});

// Without SENTRY_PROJECT_ROOT, falls back to PROJECT_DIR/..
const projectRoot = path.dirname(tempDir);
const expectedPath = path.join(projectRoot, 'relative/path.map');
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain(`SOURCEMAP_FILE=${expectedPath}`);
});

it('finds sentry.options.json in SENTRY_PROJECT_ROOT', () => {
const customRoot = path.join(tempDir, 'monorepo-package');
fs.mkdirSync(customRoot, { recursive: true });

const optionsContent = JSON.stringify({ dsn: 'https://key@sentry.io/123' });
fs.writeFileSync(path.join(customRoot, 'sentry.options.json'), optionsContent);

const buildDir = path.join(tempDir, 'build');
const resourcesPath = 'Resources';
fs.mkdirSync(path.join(buildDir, resourcesPath), { recursive: true });

const result = runScript({
SENTRY_PROJECT_ROOT: customRoot,
SENTRY_DISABLE_AUTO_UPLOAD: 'true',
SENTRY_COPY_OPTIONS_FILE: 'true',
CONFIGURATION_BUILD_DIR: buildDir,
UNLOCALIZED_RESOURCES_FOLDER_PATH: resourcesPath,
});

expect(result.exitCode).toBe(0);
expect(result.stdout).toContain('Copied');
const destPath = path.join(buildDir, resourcesPath, 'sentry.options.json');
const copied = JSON.parse(fs.readFileSync(destPath, 'utf8'));
expect(copied.dsn).toBe('https://key@sentry.io/123');
});
});

describe('sentry.options.json SENTRY_ENVIRONMENT override', () => {
it('copies file without modification when SENTRY_ENVIRONMENT is not set', () => {
const optionsContent = JSON.stringify({ dsn: 'https://key@sentry.io/123', environment: 'production' });
Expand Down
Loading