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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
> make sure you follow our [migration guide](https://docs.sentry.io/platforms/react-native/migration/) first.
<!-- prettier-ignore-end -->

## Unreleased

### Features

- Support `SENTRY_ENVIRONMENT` in bare React Native builds ([#5823](https://github.com/getsentry/sentry-react-native/pull/5823))

## 8.4.0

### Fixes
Expand Down
14 changes: 14 additions & 0 deletions packages/core/scripts/sentry-xcode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,20 @@ if [ "$SENTRY_COPY_OPTIONS_FILE" = true ]; then
echo "[Sentry] $SENTRY_OPTIONS_FILE_PATH not found. $SENTRY_OPTIONS_FILE_ERROR_MESSAGE_POSTFIX" 1>&2
else
cp "$SENTRY_OPTIONS_FILE_PATH" "$SENTRY_OPTIONS_FILE_DESTINATION_PATH"

if [ -n "$SENTRY_ENVIRONMENT" ]; then
if "$LOCAL_NODE_BINARY" -e "
var fs = require('fs');
var destPath = process.argv[1];
var opts = JSON.parse(fs.readFileSync(destPath, 'utf8'));
opts.environment = process.env.SENTRY_ENVIRONMENT;
fs.writeFileSync(destPath, JSON.stringify(opts));
" -- "$SENTRY_OPTIONS_FILE_DESTINATION_PATH" 2>/dev/null; then
echo "[Sentry] Overriding 'environment' from SENTRY_ENVIRONMENT environment variable"
else
echo "[Sentry] Failed to override environment, copied file as-is." 1>&2
fi
fi
echo "[Sentry] Copied $SENTRY_OPTIONS_FILE_PATH to $SENTRY_OPTIONS_FILE_DESTINATION_PATH"
fi
fi
Expand Down
13 changes: 13 additions & 0 deletions packages/core/sentry.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ tasks.register("copySentryJsonConfiguration") {
into androidAssetsDir
rename { String fileName -> configFile }
}

def sentryEnv = System.getenv('SENTRY_ENVIRONMENT')
if (sentryEnv) {
try {
def destFile = new File(androidAssetsDir, configFile)
def content = new groovy.json.JsonSlurper().parseText(destFile.text)
content.environment = sentryEnv
destFile.text = groovy.json.JsonOutput.toJson(content)
logger.lifecycle("Overriding 'environment' from SENTRY_ENVIRONMENT environment variable")
} catch (Exception e) {
logger.warn("Failed to override environment in ${configFile}: ${e.message}. Copied file as-is.")
}
}
logger.lifecycle("Copied ${configFile} to Android assets")
} else {
logger.warn("${configFile} not found in app root (${appRoot})")
Expand Down
97 changes: 97 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,103 @@ describe('sentry-xcode.sh', () => {
expect(result.stdout).toContain('skipping sourcemaps upload');
});

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' });
const optionsFile = path.join(tempDir, 'sentry.options.json');
fs.writeFileSync(optionsFile, optionsContent);

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

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

expect(result.exitCode).toBe(0);
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');
expect(copied.environment).toBe('production');
});

it('overrides environment from SENTRY_ENVIRONMENT env var', () => {
const optionsContent = JSON.stringify({ dsn: 'https://key@sentry.io/123', environment: 'production' });
const optionsFile = path.join(tempDir, 'sentry.options.json');
fs.writeFileSync(optionsFile, optionsContent);

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

const result = runScript({
SENTRY_DISABLE_AUTO_UPLOAD: 'true',
SENTRY_COPY_OPTIONS_FILE: 'true',
SENTRY_OPTIONS_FILE_PATH: optionsFile,
CONFIGURATION_BUILD_DIR: buildDir,
UNLOCALIZED_RESOURCES_FOLDER_PATH: resourcesPath,
SENTRY_ENVIRONMENT: 'staging',
});

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

it('does not modify the source sentry.options.json', () => {
const optionsContent = JSON.stringify({ dsn: 'https://key@sentry.io/123', environment: 'production' });
const optionsFile = path.join(tempDir, 'sentry.options.json');
fs.writeFileSync(optionsFile, optionsContent);

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

runScript({
SENTRY_DISABLE_AUTO_UPLOAD: 'true',
SENTRY_COPY_OPTIONS_FILE: 'true',
SENTRY_OPTIONS_FILE_PATH: optionsFile,
CONFIGURATION_BUILD_DIR: buildDir,
UNLOCALIZED_RESOURCES_FOLDER_PATH: resourcesPath,
SENTRY_ENVIRONMENT: 'staging',
});

const source = JSON.parse(fs.readFileSync(optionsFile, 'utf8'));
expect(source.environment).toBe('production');
});

it('falls back to plain copy when sentry.options.json contains invalid JSON', () => {
const optionsFile = path.join(tempDir, 'sentry.options.json');
fs.writeFileSync(optionsFile, 'invalid json{{{');

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

const result = runScript({
SENTRY_DISABLE_AUTO_UPLOAD: 'true',
SENTRY_COPY_OPTIONS_FILE: 'true',
SENTRY_OPTIONS_FILE_PATH: optionsFile,
CONFIGURATION_BUILD_DIR: buildDir,
UNLOCALIZED_RESOURCES_FOLDER_PATH: resourcesPath,
SENTRY_ENVIRONMENT: 'staging',
});

expect(result.exitCode).toBe(0);
const destPath = path.join(buildDir, resourcesPath, 'sentry.options.json');
expect(fs.readFileSync(destPath, 'utf8')).toBe('invalid json{{{');
expect(result.stdout).toContain('Copied');
});
});

describe('SOURCEMAP_FILE path resolution', () => {
// Returns a mock sentry-cli that prints the SOURCEMAP_FILE env var it received.
const makeSourcemapEchoScript = (dir: string): string => {
Expand Down
Loading