Skip to content

Commit

Permalink
Merge a08fb3a into ad17b3e
Browse files Browse the repository at this point in the history
  • Loading branch information
krystofwoldrich authored Dec 20, 2022
2 parents ad17b3e + a08fb3a commit 738ca30
Show file tree
Hide file tree
Showing 8 changed files with 999 additions and 43 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/native-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Native Tests

on:
push:
branches: [main]
pull_request:

env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}

jobs:
cancel-previous-workflow:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # pin@0.11.0
with:
access_token: ${{ github.token }}

test:
name: ios
runs-on: macos-latest
steps:
- uses: actions/checkout@v3

- name: NPM cache
uses: actions/cache@v3
id: deps-cache
with:
path: |
node_modules
sample/node_modules
key: ${{ github.workflow }}-${{ github.job }}-npm-${{ hashFiles('yarn.lock', 'sample/yarn.lock') }}

- name: Install SDK JS Dependencies
if: steps.deps-cache.outputs['cache-hit'] != 'true'
run: yarn install

- name: Install App JS Dependencies
if: steps.deps-cache.outputs['cache-hit'] != 'true'
working-directory: sample
run: yarn install

- name: Install App Pods
working-directory: sample/ios
run: PRODUCTION=1 pod install

- name: Build SDK
run: yarn build

- name: Run iOS Tests
working-directory: sample/ios
env:
SCHEME: sample
CONFIGURATION: Release
DESTINATION: 'platform=iOS Simulator,OS=latest,name=iPhone 14'
run: |
env NSUnbufferedIO=YES \
ONLY_ACTIVE_ARCH=yes \
xcodebuild -workspace *.xcworkspace \
-scheme $SCHEME -configuration $CONFIGURATION \
-destination "$DESTINATION" \
test
4 changes: 2 additions & 2 deletions RNSentry.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ Pod::Spec.new do |s|
s.preserve_paths = '*.js'

s.dependency 'React-Core'
s.dependency 'Sentry/HybridSDK', '7.31.3'
s.dependency 'Sentry/HybridSDK', '8.0.0-beta.4'

s.source_files = 'ios/RNSentry.{h,mm}'
s.source_files = 'ios/**/*.{h,mm}'
s.public_header_files = 'ios/RNSentry.h'

# This guard prevent to install the dependencies when we run `pod install` in the old architecture.
Expand Down
44 changes: 44 additions & 0 deletions RNSentryPrivate.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'json'
version = JSON.parse(File.read('package.json'))["version"]

folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'

Pod::Spec.new do |s|
s.name = 'RNSentryPrivate'
s.version = version
s.license = 'MIT'
s.summary = 'RNSentry Private Library'
s.author = 'Sentry'
s.homepage = "https://github.com/getsentry/sentry-react-native"
s.source = { :git => 'https://github.com/getsentry/sentry-react-native.git', :tag => "#{s.version}"}

s.description = <<-DESC
Not for public use.
Common APIs for internal Sentry usage.
DESC

s.preserve_paths = '*.js'

s.dependency 'React-Core'

s.ios.deployment_target = "12.4"
s.osx.deployment_target = "10.10"
s.tvos.deployment_target = "12.4"

s.source_files = 'ios/Private/**/*.{h,mm}'

# This guard prevent to install the dependencies when we run `pod install` in the old architecture.
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
s.pod_target_xcconfig = {
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
}

s.dependency "React-Codegen"
s.dependency "RCT-Folly"
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"
end
end
13 changes: 13 additions & 0 deletions ios/Private/SentryOptions+RNOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#import "SentryOptions.h"

@interface SentryOptions (RNOptions)

/**
* Init SentryOptions.
* @param options React Native Options dictionary
* @return SentryOptions
*/
- (_Nullable instancetype)initWithRNOptions:(NSDictionary<NSString *, id> *_Nonnull)options
didFailWithError:(NSError *_Nullable *_Nullable)error;

@end
210 changes: 210 additions & 0 deletions ios/Private/SentryOptions+RNOptions.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#import "SentryOptions.h"
#import "SentryDsn.h"
#import "SentryLog.h"
#import "SentryMeta.h"
#import "SentrySdkInfo.h"
#import "SentryOptions+RNOptions.h"

@implementation SentryOptions (RNOptions)


- (_Nullable instancetype)initWithRNOptions:(NSDictionary<NSString *, id> *)options
didFailWithError:(NSError *_Nullable *_Nullable)error
{
if (self = [self init]) {
if (![self validateOptions:options didFailWithError:error]) {
[SentryLog
logWithMessage:[NSString stringWithFormat:@"Failed to initialize: %@", *error]
andLevel:kSentryLevelError];
return nil;
}
}
return self;
}

/**
* Populates all `SentryOptions` values from `options` dict using fallbacks/defaults if needed.
*/
- (BOOL)validateOptions:(NSDictionary<NSString *, id> *)options
didFailWithError:(NSError *_Nullable *_Nullable)error
{
__weak __block SentryOptions* _self = self;

NSPredicate *isNSString = [NSPredicate predicateWithBlock:^BOOL(
id object, NSDictionary *bindings) { return [object isKindOfClass:[NSString class]]; }];

[self setBool:options[@"debug"] block:^(BOOL value) { _self.debug = value; }];

NSString *dsn = @"";
if (nil != options[@"dsn"] && [options[@"dsn"] isKindOfClass:[NSString class]]) {
dsn = options[@"dsn"];
}

self.parsedDsn = [[SentryDsn alloc] initWithString:dsn didFailWithError:error];

if ([options[@"release"] isKindOfClass:[NSString class]]) {
self.releaseName = options[@"release"];
}

if ([options[@"environment"] isKindOfClass:[NSString class]]) {
self.environment = options[@"environment"];
}

if ([options[@"dist"] isKindOfClass:[NSString class]]) {
self.dist = options[@"dist"];
}

[self setBool:options[@"enabled"] block:^(BOOL value) { _self.enabled = value; }];

[self setBool:options[@"enableCrashHandler"]
block:^(BOOL value) { _self.enableCrashHandler = value; }];

if ([options[@"maxBreadcrumbs"] isKindOfClass:[NSNumber class]]) {
self.maxBreadcrumbs = [options[@"maxBreadcrumbs"] unsignedIntValue];
}

[self setBool:options[@"enableNetworkBreadcrumbs"]
block:^(BOOL value) { _self.enableNetworkBreadcrumbs = value; }];

if ([options[@"maxCacheItems"] isKindOfClass:[NSNumber class]]) {
self.maxCacheItems = [options[@"maxCacheItems"] unsignedIntValue];
}

if ([options[@"integrations"] isKindOfClass:[NSArray class]]) {
self.integrations = [options[@"integrations"] filteredArrayUsingPredicate:isNSString];
}

if ([options[@"sampleRate"] isKindOfClass:[NSNumber class]]) {
self.sampleRate = options[@"sampleRate"];
}

[self setBool:options[@"enableAutoSessionTracking"]
block:^(BOOL value) { _self.enableAutoSessionTracking = value; }];

[self setBool:options[@"enableOutOfMemoryTracking"]
block:^(BOOL value) { _self.enableOutOfMemoryTracking = value; }];

if ([options[@"sessionTrackingIntervalMillis"] isKindOfClass:[NSNumber class]]) {
self.sessionTrackingIntervalMillis =
[options[@"sessionTrackingIntervalMillis"] unsignedIntValue];
}

[self setBool:options[@"attachStacktrace"]
block:^(BOOL value) { _self.attachStacktrace = value; }];

[self setBool:options[@"stitchAsyncCode"]
block:^(BOOL value) { _self.stitchAsyncCode = value; }];

if ([options[@"maxAttachmentSize"] isKindOfClass:[NSNumber class]]) {
self.maxAttachmentSize = [options[@"maxAttachmentSize"] unsignedIntValue];
}

[self setBool:options[@"sendDefaultPii"]
block:^(BOOL value) { _self.sendDefaultPii = value; }];

[self setBool:options[@"enableAutoPerformanceTracking"]
block:^(BOOL value) { _self.enableAutoPerformanceTracing = value; }];

[self setBool:options[@"enableCaptureFailedRequests"]
block:^(BOOL value) { _self.enableCaptureFailedRequests = value; }];

#if SENTRY_HAS_UIKIT
[self setBool:options[@"enableUIViewControllerTracking"]
block:^(BOOL value) { _self.enableUIViewControllerTracing = value; }];

[self setBool:options[@"attachScreenshot"]
block:^(BOOL value) { _self.attachScreenshot = value; }];

[self setBool:options[@"attachViewHierarchy"]
block:^(BOOL value) { _self.attachViewHierarchy = value; }];

[self setBool:options[@"enableUserInteractionTracing"]
block:^(BOOL value) { _self.enableUserInteractionTracing = value; }];

if ([options[@"idleTimeout"] isKindOfClass:[NSNumber class]]) {
self.idleTimeout = [options[@"idleTimeout"] doubleValue];
}

[self setBool:options[@"enablePreWarmedAppStartTracking"]
block:^(BOOL value) { _self.enablePreWarmedAppStartTracing = value; }];
#endif

[self setBool:options[@"enableAppHangTracking"]
block:^(BOOL value) { _self.enableAppHangTracking = value; }];

if ([options[@"appHangTimeoutInterval"] isKindOfClass:[NSNumber class]]) {
self.appHangTimeoutInterval = [options[@"appHangTimeoutInterval"] doubleValue];
}

[self setBool:options[@"enableNetworkTracking"]
block:^(BOOL value) { _self.enableNetworkTracking = value; }];

[self setBool:options[@"enableFileIOTracing"]
block:^(BOOL value) { _self.enableFileIOTracing = value; }];

if ([options[@"tracesSampleRate"] isKindOfClass:[NSNumber class]]) {
self.tracesSampleRate = options[@"tracesSampleRate"];
}

if ([options[@"urlSessionDelegate"] conformsToProtocol:@protocol(NSURLSessionDelegate)]) {
self.urlSessionDelegate = options[@"urlSessionDelegate"];
}

[self setBool:options[@"enableSwizzling"]
block:^(BOOL value) { _self.enableSwizzling = value; }];

[self setBool:options[@"enableCoreDataTracking"]
block:^(BOOL value) { _self.enableCoreDataTracing = value; }];

#if SENTRY_TARGET_PROFILING_SUPPORTED
if ([options[@"profilesSampleRate"] isKindOfClass:[NSNumber class]]) {
self.profilesSampleRate = options[@"profilesSampleRate"];
}
#endif

[self setBool:options[@"sendClientReports"]
block:^(BOOL value) { _self.sendClientReports = value; }];

[self setBool:options[@"enableAutoBreadcrumbTracking"]
block:^(BOOL value) { _self.enableAutoBreadcrumbTracking = value; }];

if ([options[@"tracePropagationTargets"] isKindOfClass:[NSArray class]]) {
self.tracePropagationTargets = options[@"tracePropagationTargets"];
}

if ([options[@"failedRequestStatusCodes"] isKindOfClass:[NSArray class]]) {
self.failedRequestStatusCodes = options[@"failedRequestStatusCodes"];
}

if ([options[@"failedRequestTargets"] isKindOfClass:[NSArray class]]) {
self.failedRequestTargets = options[@"failedRequestTargets"];
}

// SentrySdkInfo already expects a dictionary with {"sdk": {"name": ..., "value": ...}}
// so we're passing the whole options object.
// Note: we should remove this code once the hybrid SDKs move over to the new
// PrivateSentrySDKOnly setter functions.
if ([options[@"sdk"] isKindOfClass:[NSDictionary class]]) {
SentrySdkInfo *defaults = [[SentrySdkInfo alloc] initWithName:SentryMeta.sdkName
andVersion:SentryMeta.versionString];
SentrySdkInfo *sdkInfo = [[SentrySdkInfo alloc] initWithDict:options orDefaults:defaults];
SentryMeta.versionString = sdkInfo.version;
SentryMeta.sdkName = sdkInfo.name;
}

if (nil != error && nil != *error) {
return NO;
} else {
return YES;
}
}

- (void)setBool:(id)value block:(void (^)(BOOL))block
{
// Entries in the dictionary can be NSNull. Especially, on React-Native, this can happen.
if (value != nil && ![value isEqual:[NSNull null]]) {
block([value boolValue]);
}
}

@end
5 changes: 3 additions & 2 deletions ios/RNSentry.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import <Sentry/Sentry.h>
#import <Sentry/PrivateSentrySDKOnly.h>
#import <Sentry/SentryScreenFrames.h>
#import "SentryOptions+RNOptions.h"

// Thanks to this guard, we won't import this header when we build for the old architecture.
#ifdef RCT_NEW_ARCH_ENABLED
Expand Down Expand Up @@ -73,7 +74,7 @@ + (BOOL)requiresMainQueueSetup {
[mutableOptions removeObjectForKey:@"tracesSampleRate"];
[mutableOptions removeObjectForKey:@"tracesSampler"];

SentryOptions *sentryOptions = [[SentryOptions alloc] initWithDict:mutableOptions didFailWithError:&error];
SentryOptions *sentryOptions = [[SentryOptions alloc] initWithRNOptions:options didFailWithError:&error];
if (error) {
reject(@"SentryReactNative", error.localizedDescription, error);
return;
Expand All @@ -99,7 +100,7 @@ + (BOOL)requiresMainQueueSetup {
#endif
}

[SentrySDK startWithOptionsObject:sentryOptions];
[SentrySDK startWithOptions:sentryOptions];

#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
BOOL appIsActive = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
Expand Down
1 change: 1 addition & 0 deletions sample/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ target 'sample' do
target 'sampleTests' do
inherit! :complete
# Pods for testing
pod 'RNSentryPrivate', :path => '../../RNSentryPrivate.podspec'
end

post_install do |installer|
Expand Down
Loading

0 comments on commit 738ca30

Please sign in to comment.