Skip to content
Closed
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

### Fixes

- Load `ios/.xcode.env` and `ios/.xcode.env.local` in the Expo plugin "Upload Debug Symbols to Sentry" phase before it runs Node, so the phase finds Node when Xcode starts from the Dock ([#6861](https://github.com/getsentry/sentry-react-native/pull/6861))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • 馃毇 The changelog entry seems to be part of an already released section ## 8.30.0.
    Consider moving the entry to the ## Unreleased section, please.

- Preserve Hermes internal bytecode frames as non-application frames when rewriting Expo stack traces ([#6848](https://github.com/getsentry/sentry-react-native/pull/6848))
- Fix stale `turbo_module.*` tags on Android native crashes ([#6823](https://github.com/getsentry/sentry-react-native/pull/6823))
- Forward image attachments to Spotlight instead of stripping them from the envelope ([#6818](https://github.com/getsentry/sentry-react-native/pull/6818))
Expand Down
7 changes: 6 additions & 1 deletion packages/core/plugin/src/withSentryIOS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ const SENTRY_REACT_NATIVE_XCODE_PATH =
const SENTRY_REACT_NATIVE_XCODE_DEBUG_FILES_PATH =
"`${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`";
const SENTRY_DISABLE_AUTO_UPLOAD_EXPORT = 'export SENTRY_DISABLE_AUTO_UPLOAD=true';
// Xcode started from the Dock has no node on PATH, so load NODE_BINARY the same way as with-environment.sh.
const LOAD_XCODE_ENV = `XCODE_ENV_PATH="\${PODFILE_DIR:-$PODS_ROOT/..}/.xcode.env"
[ -f "$XCODE_ENV_PATH" ] && . "$XCODE_ENV_PATH"
[ -f "$XCODE_ENV_PATH.local" ] && . "$XCODE_ENV_PATH.local"
`;

export const withSentryIOS: ConfigPlugin<{
sentryProperties: string;
Expand Down Expand Up @@ -114,7 +119,7 @@ export function getDebugFilesUploadScript(disableAutoUpload: boolean = false): s
// The resolved script path is wrapped in double quotes so a project path containing spaces is
// passed to `/bin/sh` as a single argument instead of being word-split. See issue #6583.
const disableAutoUploadExport = disableAutoUpload ? `${SENTRY_DISABLE_AUTO_UPLOAD_EXPORT}\n` : '';
return `${disableAutoUploadExport}/bin/sh "${SENTRY_REACT_NATIVE_XCODE_DEBUG_FILES_PATH}"`;
return `${disableAutoUploadExport}${LOAD_XCODE_ENV}/bin/sh "${SENTRY_REACT_NATIVE_XCODE_DEBUG_FILES_PATH}"`;
}

export function requoteExistingSentryBundleScript(script: BuildPhase): void {
Expand Down
64 changes: 62 additions & 2 deletions packages/core/test/expo-plugin/modifyXcodeProject.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { execFileSync } from 'child_process';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';

import { warnOnce } from '../../plugin/src/logger';
import {
addDisableAutoUploadToExistingScript,
Expand Down Expand Up @@ -470,7 +475,8 @@ describe('overwriteDebugFilesUploadScript: existing phase re-quoted on upgrade (
overwriteDebugFilesUploadScript(script, true);
const parsed = JSON.parse(script.shellScript);
expect(parsed).toBe(getDebugFilesUploadScript(true));
expect(parsed).toMatch(/^export SENTRY_DISABLE_AUTO_UPLOAD=true\n\/bin\/sh "`/);
expect(parsed).toMatch(/^export SENTRY_DISABLE_AUTO_UPLOAD=true\n/);
expect(parsed).toContain('/bin/sh "`');
});

it('drops a previously injected export when disableAutoUpload is toggled back to false', () => {
Expand Down Expand Up @@ -564,8 +570,62 @@ export NODE_BINARY=node

it('quotes the debug files upload script path with disableAutoUpload', () => {
const result = getDebugFilesUploadScript(true);
expect(result).toMatch(/^export SENTRY_DISABLE_AUTO_UPLOAD=true\n\/bin\/sh "`/);
expect(result).toMatch(/^export SENTRY_DISABLE_AUTO_UPLOAD=true\n/);
expect(result).toContain('/bin/sh "`');
expect(result).toContain('sentry-xcode-debug-files.sh');
expect(result).not.toMatch(/\/bin\/sh `/);
});
});

describe('Upload Debug Symbols phase loads .xcode.env before it resolves the script (issue #6859)', () => {
let projectDir: string;
let iosDir: string;

beforeEach(() => {
projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sentry-expo-phase-'));
iosDir = path.join(projectDir, 'ios');
const sentryDir = path.join(projectDir, 'node_modules', '@sentry', 'react-native');
fs.mkdirSync(path.join(sentryDir, 'scripts'), { recursive: true });
fs.mkdirSync(path.join(iosDir, 'Pods'), { recursive: true });
fs.writeFileSync(path.join(sentryDir, 'package.json'), '{"name":"@sentry/react-native"}');
fs.writeFileSync(
path.join(sentryDir, 'scripts', 'sentry-xcode-debug-files.sh'),
'echo "debug files script ran with SENTRY_DISABLE_AUTO_UPLOAD=$SENTRY_DISABLE_AUTO_UPLOAD"\n',
);
fs.writeFileSync(path.join(iosDir, '.xcode.env'), 'export NODE_BINARY=$(command -v node)\n');
});

afterEach(() => {
fs.rmSync(projectDir, { recursive: true, force: true });
});

const runPhase = (script: string, env: Record<string, string>): string =>
execFileSync('/bin/sh', ['-c', script], {
cwd: iosDir,
env: { HOME: os.homedir(), PATH: '/usr/bin:/bin:/usr/sbin:/sbin', ...env },
encoding: 'utf8',
stdio: 'pipe',
});

it('includes the .xcode.env loading before the script path is resolved', () => {
const result = getDebugFilesUploadScript();
expect(result.indexOf('.xcode.env')).toBeLessThan(result.indexOf('--print'));
expect(result).toContain('. "$XCODE_ENV_PATH.local"');
});

it('uses NODE_BINARY from .xcode.env.local when node is not on PATH', () => {
fs.writeFileSync(path.join(iosDir, '.xcode.env.local'), `export NODE_BINARY="${process.execPath}"\n`);

const stdout = runPhase(getDebugFilesUploadScript(true), { PODS_ROOT: path.join(iosDir, 'Pods') });

expect(stdout).toContain('debug files script ran with SENTRY_DISABLE_AUTO_UPLOAD=true');
});

it('uses PODFILE_DIR before PODS_ROOT to find .xcode.env', () => {
fs.writeFileSync(path.join(iosDir, '.xcode.env.local'), `export NODE_BINARY="${process.execPath}"\n`);

const stdout = runPhase(getDebugFilesUploadScript(), { PODFILE_DIR: iosDir, PODS_ROOT: '/nonexistent' });

expect(stdout).toContain('debug files script ran');
});
});
Loading