Skip to content

Commit

Permalink
Merge branch 'main' into ci/dart-only-metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
denrase committed Dec 17, 2024
2 parents 7f8b13f + 45d0706 commit b16ca72
Show file tree
Hide file tree
Showing 34 changed files with 460 additions and 182 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @krystofwoldrich @stefanosiano @buenaflor @martinhaintz
* @krystofwoldrich @stefanosiano @buenaflor
4 changes: 2 additions & 2 deletions .github/workflows/flutter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,13 @@ jobs:
if: matrix.target == 'web'
run: |
flutter test --platform chrome --test-randomize-ordering-seed=random --exclude-tags canvasKit
flutter test --platform chrome --test-randomize-ordering-seed=random --tags canvasKit --web-renderer canvaskit
flutter test --platform chrome --test-randomize-ordering-seed=random --tags canvasKit
- name: Test web (WASM)
if: matrix.target == 'web'
run: |
flutter test --platform chrome --wasm --test-randomize-ordering-seed=random --exclude-tags canvasKit
flutter test --platform chrome --wasm --test-randomize-ordering-seed=random --tags canvasKit --web-renderer canvaskit
flutter test --platform chrome --wasm --test-randomize-ordering-seed=random --tags canvasKit
- name: Test VM with coverage
if: matrix.target == 'linux' || matrix.target == 'macos' || matrix.target == 'windows'
Expand Down
60 changes: 30 additions & 30 deletions .github/workflows/flutter_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
- "flutter/**"

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

jobs:
cancel-previous-workflow:
Expand All @@ -25,7 +25,7 @@ jobs:
access_token: ${{ github.token }}

test-android:
runs-on: macos-13
runs-on: ubuntu-latest
timeout-minutes: 30
defaults:
run:
Expand All @@ -38,6 +38,12 @@ jobs:
- name: checkout
uses: actions/checkout@v4

- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- uses: actions/setup-java@v4
with:
distribution: "adopt"
Expand All @@ -56,28 +62,7 @@ jobs:
- name: Gradle cache
uses: gradle/gradle-build-action@ac2d340dc04d9e1113182899e983b5400c17cda1 # [email protected]

- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-31

- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d #[email protected]
with:
working-directory: ./flutter/example
api-level: 31
profile: Nexus 6
arch: x86_64
force-avd-creation: false
avd-name: macOS-avd-x86_64-31
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: echo 'Generated AVD snapshot for caching.'
# TODO: fix emulator caching, in ubuntu-latest emulator won't boot: https://github.com/ReactiveCircus/android-emulator-runner/issues/278

- name: build apk
working-directory: ./flutter/example/android
Expand All @@ -91,8 +76,8 @@ jobs:
profile: Nexus 6
arch: x86_64
force-avd-creation: false
avd-name: macOS-avd-x86_64-31
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
avd-name: avd-x86_64-31
emulator-options: -no-snapshot-save -no-window -accel on -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew testDebugUnitTest

Expand All @@ -104,10 +89,23 @@ jobs:
profile: Nexus 6
arch: x86_64
force-avd-creation: false
avd-name: macOS-avd-x86_64-31
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
avd-name: avd-x86_64-31
emulator-options: -no-snapshot-save -no-window -accel on -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: flutter test integration_test/all.dart --verbose
script: flutter test integration_test/all.dart --dart-define SENTRY_AUTH_TOKEN_E2E=$SENTRY_AUTH_TOKEN_E2E --verbose

- name: launch android emulator & run android integration test in profile mode
uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d #[email protected]
with:
working-directory: ./flutter/example
api-level: 31
profile: Nexus 6
arch: x86_64
force-avd-creation: false
avd-name: avd-x86_64-31
emulator-options: -no-snapshot-save -no-window -accel on -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: flutter drive --driver=integration_test/test_driver/driver.dart --target=integration_test/sentry_widgets_flutter_binding_test.dart --profile -d emulator-5554

cocoa:
name: "${{ matrix.target }} | ${{ matrix.sdk }}"
Expand Down Expand Up @@ -158,7 +156,9 @@ jobs:
- name: run integration test
# Disable flutter integration tests for iOS for now (https://github.com/getsentry/sentry-dart/issues/1605#issuecomment-1695809346)
if: ${{ matrix.target != 'ios' }}
run: flutter test -d "${{ steps.device.outputs.name }}" integration_test/all.dart --verbose
run: |
flutter test -d "${{ steps.device.outputs.name }}" integration_test/all.dart --dart-define SENTRY_AUTH_TOKEN_E2E=$SENTRY_AUTH_TOKEN_E2E --verbose
flutter drive --driver=integration_test/test_driver/driver.dart --target=integration_test/sentry_widgets_flutter_binding_test.dart --profile -d "${{ steps.device.outputs.name }}"
- name: run native test
# We only have the native unit test package in the iOS xcodeproj at the moment.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/testflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff # [email protected]
- run: xcodes select 15.0.1
- uses: ruby/setup-ruby@a2bbe5b1b236842c1cb7dd11e8e3b51e0a616acc # pin@v1.202.0
- uses: ruby/setup-ruby@401c19e14f474b54450cd3905bb8b86e2c8509cf # pin@v1.204.0
with:
ruby-version: '2.7.5'
bundler-cache: true
Expand Down
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# Changelog

## Unreleased

### Deprecate

- Manual TTID ([#2477](https://github.com/getsentry/sentry-dart/pull/2477))

### Improvements

- Check `SentryTracer` type in TTFD tracker ([#2508](https://github.com/getsentry/sentry-dart/pull/2508))

### Enhancements

- Warning (in a debug build) if a potentially sensitive widget is not masked or unmasked explicitly ([#2375](https://github.com/getsentry/sentry-dart/pull/2375))

### Dependencies

- Bump Native SDK from v0.7.15 to v0.7.16 ([#2465](https://github.com/getsentry/sentry-dart/pull/2465))
- [changelog](https://github.com/getsentry/sentry-native/blob/master/CHANGELOG.md#0716)
- [diff](https://github.com/getsentry/sentry-native/compare/0.7.15...0.7.16)
- Bump Android SDK from v7.18.1 to v7.19.0 ([#2488](https://github.com/getsentry/sentry-dart/pull/2488))
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7190)
- [diff](https://github.com/getsentry/sentry-java/compare/7.18.1...7.19.0)

## 8.11.1

### Improvements

- Check for type before casting in TTID ([#2497](https://github.com/getsentry/sentry-dart/pull/2497))

### Fixes

- SentryWidgetsFlutterBinding initializing even if a binding already exists ([#2494](https://github.com/getsentry/sentry-dart/pull/2494))

## 8.12.0-beta.1

### Features
Expand Down
2 changes: 1 addition & 1 deletion dart/lib/src/sentry_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ class SentryOptions {
/// On io platforms without native SDKs (dart, linux, windows), this will use
/// an 'IOClient' with inner 'HTTPClient' for http communication.
/// A http proxy will be set in returned for 'HttpClient.findProxy' in the
/// form 'PROXY <your_host>:<your_port>'.
/// form 'PROXY your_host:your_port'.
/// When setting 'user' and 'pass', the 'HttpClient.addProxyCredentials'
/// method will be called with empty 'realm'.
///
Expand Down
2 changes: 1 addition & 1 deletion flutter/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ android {
}

dependencies {
api 'io.sentry:sentry-android:7.18.1'
api 'io.sentry:sentry-android:7.19.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"

// Required -- JUnit 4 framework
Expand Down
139 changes: 76 additions & 63 deletions flutter/example/integration_test/integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart';
import 'package:integration_test/integration_test.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:sentry_flutter_example/main.dart';

import 'utils.dart';

void main() {
// const org = 'sentry-sdks';
// const slug = 'sentry-flutter';
// const authToken = String.fromEnvironment('SENTRY_AUTH_TOKEN');
const org = 'sentry-sdks';
const slug = 'sentry-flutter';
const authToken = String.fromEnvironment('SENTRY_AUTH_TOKEN_E2E');
const fakeDsn = 'https://[email protected]/1234567';

TestWidgetsFlutterBinding.ensureInitialized();
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

tearDown(() async {
await Sentry.close();
Expand Down Expand Up @@ -98,7 +101,7 @@ void main() {

// ignore: deprecated_member_use_from_same_package
// ignore: deprecated_member_use
final associatedEventId = await Sentry.captureMessage("Associated");
final associatedEventId = await Sentry.captureMessage('Associated');
final feedback = SentryFeedback(
message: 'message',
contactEmail: '[email protected]',
Expand Down Expand Up @@ -162,66 +165,76 @@ void main() {
await transaction.finish();
});

// group('e2e', () {
// var output = find.byKey(const Key('output'));
// late Fixture fixture;
//
// setUp(() {
// fixture = Fixture();
// });
//
// testWidgets('captureException', (tester) async {
// await setupSentryAndApp(tester,
// dsn: exampleDsn, beforeSendCallback: fixture.beforeSend);
//
// await tester.tap(find.text('captureException'));
// await tester.pumpAndSettle();
//
// final text = output.evaluate().single.widget as Text;
// final id = text.data!;
//
// final uri = Uri.parse(
// 'https://sentry.io/api/0/projects/$org/$slug/events/$id/',
// );
// expect(authToken, isNotEmpty);
//
// final event = await fixture.poll(uri, authToken);
// expect(event, isNotNull);
//
// final sentEvent = fixture.sentEvent;
// expect(sentEvent, isNotNull);
//
// final tags = event!["tags"] as List<dynamic>;
//
// expect(sentEvent!.eventId.toString(), event["id"]);
// expect("_Exception: Exception: captureException", event["title"]);
// expect(sentEvent.release, event["release"]["version"]);
// expect(
// 2,
// (tags.firstWhere((e) => e["value"] == sentEvent.environment) as Map)
// .length);
// expect(sentEvent.fingerprint, event["fingerprint"] ?? []);
// expect(
// 2,
// (tags.firstWhere((e) => e["value"] == SentryLevel.error.name) as Map)
// .length);
// expect(sentEvent.logger, event["logger"]);
//
// final dist = tags.firstWhere((element) => element['key'] == 'dist');
// expect('1', dist['value']);
//
// final environment =
// tags.firstWhere((element) => element['key'] == 'environment');
// expect('integration', environment['value']);
// });
// });
group('e2e', () {
var output = find.byKey(const Key('output'));
late Fixture fixture;

setUp(() {
fixture = Fixture();
});

testWidgets('captureException', (tester) async {
late Uri uri;

await restoreFlutterOnErrorAfter(() async {
await setupSentryAndApp(tester,
dsn: exampleDsn, beforeSendCallback: fixture.beforeSend);

await tester.tap(find.text('captureException'));
await tester.pumpAndSettle();

final text = output.evaluate().single.widget as Text;
final id = text.data!;

uri = Uri.parse(
'https://sentry.io/api/0/projects/$org/$slug/events/$id/',
);
});

expect(authToken, isNotEmpty);

final event = await fixture.poll(uri, authToken);
expect(event, isNotNull);

final sentEvents = fixture.sentEvents
.where((el) => el!.eventId.toString() == event!['id']);
expect(
sentEvents.length, 1); // one button click should only send one error
final sentEvent = sentEvents.first;

final tags = event!['tags'] as List<dynamic>;

print('event id: ${event['id']}');
print('event title: ${event['title']}');
expect(sentEvent!.eventId.toString(), event['id']);
expect('_Exception: Exception: captureException', event['title']);
expect(sentEvent.release, event['release']['version']);
expect(
2,
(tags.firstWhere((e) => e['value'] == sentEvent.environment) as Map)
.length);
expect(sentEvent.fingerprint, event['fingerprint'] ?? []);
expect(
2,
(tags.firstWhere((e) => e['value'] == SentryLevel.error.name) as Map)
.length);
expect(sentEvent.logger, event['logger']);

final dist = tags.firstWhere((element) => element['key'] == 'dist');
expect('1', dist['value']);

final environment =
tags.firstWhere((element) => element['key'] == 'environment');
expect('integration', environment['value']);
});
});
}

class Fixture {
SentryEvent? sentEvent;
List<SentryEvent?> sentEvents = [];

FutureOr<SentryEvent?> beforeSend(SentryEvent event, Hint hint) async {
sentEvent = event;
sentEvents.add(event);
return event;
}

Expand All @@ -237,16 +250,16 @@ class Fixture {

while (retries < maxRetries) {
try {
print("Trying to fetch $url [try $retries/$maxRetries]");
print('Trying to fetch $url [try $retries/$maxRetries]');
final response = await client.get(
url,
headers: <String, String>{'Authorization': 'Bearer $authToken'},
);
print("Response status code: ${response.statusCode}");
print('Response status code: ${response.statusCode}');
if (response.statusCode == 200) {
return jsonDecode(utf8.decode(response.bodyBytes));
} else if (response.statusCode == 401) {
print("Cannot fetch $url - invalid auth token.");
print('Cannot fetch $url - invalid auth token.');
break;
}
} catch (e) {
Expand Down
Loading

0 comments on commit b16ca72

Please sign in to comment.