diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 610285da55..1533c105e7 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -17,7 +17,8 @@ jobs: user_secret: ${{ secrets.ANYTYPE_USER_SECRET }} amplitude_secret: ${{ secrets.ANYTYPE_AMPLITUDE_SECRET }} amplitude_secret_debug: ${{ secrets.ANYTYPE_AMPLITUDE_DEBUG_SECRET }} - run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug + sentry_dsn_secret: ${{ secrets.ANYTYPE_SENTRY_DSN_SECRET }} + run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug $sentry_dsn_secret - name: Compile android test sources run: make compile_android_test_sources diff --git a/.github/workflows/nightly-debug-builds.yml b/.github/workflows/nightly-debug-builds.yml index 870e5dc73b..bce232a9f8 100644 --- a/.github/workflows/nightly-debug-builds.yml +++ b/.github/workflows/nightly-debug-builds.yml @@ -14,7 +14,8 @@ jobs: user_secret: ${{ secrets.ANYTYPE_USER_SECRET }} amplitude_secret: ${{ secrets.ANYTYPE_AMPLITUDE_SECRET }} amplitude_secret_debug: ${{ secrets.ANYTYPE_AMPLITUDE_DEBUG_SECRET }} - run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug + sentry_dsn_secret: ${{ secrets.ANYTYPE_SENTRY_DSN_SECRET }} + run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug $sentry_dsn_secret - name: Enable dated version for nightly debug builds run: make enable_dated_version_name diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ae15d63343..d4b61a1be7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,8 @@ jobs: user_secret: ${{ secrets.ANYTYPE_USER_SECRET }} amplitude_secret: ${{ secrets.ANYTYPE_AMPLITUDE_SECRET }} amplitude_secret_debug: ${{ secrets.ANYTYPE_AMPLITUDE_DEBUG_SECRET }} - run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug + sentry_dsn_secret: ${{ secrets.ANYTYPE_SENTRY_DSN_SECRET }} + run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug $sentry_dsn_secret - name: Decrypt secrets run: ./scripts/release/decrypt-secrets.sh diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 1ec383daf4..960c030d5e 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -14,7 +14,8 @@ jobs: user_secret: ${{ secrets.ANYTYPE_USER_SECRET }} amplitude_secret: ${{ secrets.ANYTYPE_AMPLITUDE_SECRET }} amplitude_secret_debug: ${{ secrets.ANYTYPE_AMPLITUDE_DEBUG_SECRET }} - run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug + sentry_dsn_secret: ${{ secrets.ANYTYPE_SENTRY_DSN_SECRET }} + run: ./middleware2.sh $token_secret $user_secret $amplitude_secret $amplitude_secret_debug $sentry_dsn_secret - name: Run unit tests. Full mode. run: ./gradlew build test -Dpre-dex=false -q \ No newline at end of file diff --git a/README.md b/README.md index e927325a80..deea333926 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Your Github ID (starting with '#' character) can be found [here](https://caius.g ``` amplitude.debug="AMPLITUDE_DEBUG_KEY" amplitude.release="AMPLITUDE_RELEASE_KEY" +sentry_dsn="SENTRY_DSN_KEY" ``` Then build project. diff --git a/app/build.gradle b/app/build.gradle index c8ffe2474c..f4d04daac1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,6 +39,7 @@ android { buildConfigField "boolean", "LOG_DASHBOARD_REDUCER", localProperties.getProperty("LOG_DASHBOARD_REDUCER", "false") buildConfigField "boolean", "LOG_EDITOR_VIEWMODEL_EVENTS", localProperties.getProperty("LOG_EDITOR_VIEWMODEL_EVENTS", "false") buildConfigField "boolean", "LOG_EDITOR_CONTROL_PANEL", localProperties.getProperty("LOG_EDITOR_CONTROL_PANEL", "false") + resValue "string", "SENTRY_DSN", config.sentryApiKey } packagingOptions { @@ -146,6 +147,7 @@ dependencies { implementation project(':library-syntax-highlighter') implementation project(':analytics') implementation project(':ui-settings') + implementation project(':crash-reporting') //Compile time dependencies kapt libs.daggerCompiler diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c42e93db24..1b074b2b70 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -74,6 +74,11 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> + + + \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/app/AndroidApplication.kt b/app/src/main/java/com/anytypeio/anytype/app/AndroidApplication.kt index f6323e37fc..1360159eb2 100644 --- a/app/src/main/java/com/anytypeio/anytype/app/AndroidApplication.kt +++ b/app/src/main/java/com/anytypeio/anytype/app/AndroidApplication.kt @@ -7,6 +7,7 @@ import androidx.emoji.text.FontRequestEmojiCompatConfig import com.amplitude.api.Amplitude import com.anytypeio.anytype.BuildConfig import com.anytypeio.anytype.R +import com.anytypeio.anytype.SentryCrashReporter import com.anytypeio.anytype.analytics.tracker.AmplitudeTracker import com.anytypeio.anytype.core_utils.tools.CrashlyticsTree import com.anytypeio.anytype.di.common.ComponentDependenciesProvider @@ -31,6 +32,9 @@ class AndroidApplication : Application(), HasComponentDependencies { @Inject lateinit var discoveryManager: MDNSProvider + @Inject + lateinit var crashReporter: SentryCrashReporter + @Inject override lateinit var dependencies: ComponentDependenciesProvider protected set diff --git a/app/src/main/java/com/anytypeio/anytype/di/main/CrashReportingModule.kt b/app/src/main/java/com/anytypeio/anytype/di/main/CrashReportingModule.kt new file mode 100644 index 0000000000..018501ad1d --- /dev/null +++ b/app/src/main/java/com/anytypeio/anytype/di/main/CrashReportingModule.kt @@ -0,0 +1,21 @@ +package com.anytypeio.anytype.di.main + +import android.content.Context +import com.anytypeio.anytype.SentryCrashReporter +import com.anytypeio.anytype.core_utils.tools.AppInfo +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +@Module +object CrashReportingModule { + + @JvmStatic + @Provides + @Singleton + fun provideCrashReporter( + context: Context, + appInfo: AppInfo + ): SentryCrashReporter = SentryCrashReporter(context, appInfo) + +} \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/di/main/MainComponent.kt b/app/src/main/java/com/anytypeio/anytype/di/main/MainComponent.kt index dba99e7a3b..b5bb2f4520 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/main/MainComponent.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/main/MainComponent.kt @@ -57,7 +57,8 @@ import javax.inject.Singleton ClipboardModule::class, AnalyticsModule::class, LocalNetworkProviderModule::class, - SubscriptionsModule::class + SubscriptionsModule::class, + CrashReportingModule::class ] ) interface MainComponent : diff --git a/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt b/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt index 2e3cbe42d6..a7a02eb350 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt @@ -3,8 +3,11 @@ package com.anytypeio.anytype.di.main import android.content.Context import android.content.SharedPreferences import androidx.preference.PreferenceManager +import com.anytypeio.anytype.BuildConfig import com.anytypeio.anytype.app.TogglePrefs import com.anytypeio.anytype.app.DefaultFeatureToggles +import com.anytypeio.anytype.core_utils.tools.AppInfo +import com.anytypeio.anytype.core_utils.tools.DefaultAppInfo import com.anytypeio.anytype.core_utils.tools.DefaultUrlValidator import com.anytypeio.anytype.core_utils.tools.FeatureToggles import com.anytypeio.anytype.core_utils.tools.UrlValidator @@ -33,6 +36,11 @@ object UtilModule { context: Context ): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + @JvmStatic + @Provides + @Singleton + fun provideAppInfo(): AppInfo = DefaultAppInfo(BuildConfig.VERSION_NAME) + @Module interface Bindings { diff --git a/build.gradle b/build.gradle index 0079a0cc22..08eb775fbc 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,12 @@ buildscript { def githubPropertiesFile = file("$rootDir${File.separator}github.properties") githubProperties.load(new FileInputStream(githubPropertiesFile)) + def apiKeysProperties = new Properties() + def apiKeysPropertiesFile = file("$rootDir${File.separator}apikeys.properties") + apiKeysProperties.load(new FileInputStream(apiKeysPropertiesFile)) + + ext.sentryApiKey = apiKeysProperties["sentry_dsn"] + repositories { mavenLocal() google() diff --git a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/AppInfo.kt b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/AppInfo.kt new file mode 100644 index 0000000000..e6a52a3c48 --- /dev/null +++ b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/tools/AppInfo.kt @@ -0,0 +1,23 @@ +package com.anytypeio.anytype.core_utils.tools + +import com.anytypeio.anytype.core_utils.BuildConfig +import javax.inject.Inject + +interface AppInfo { + val sentryEnvironment: SentryEnvironment + val versionName: String +} + +class DefaultAppInfo @Inject constructor( + versionNameValue: String +): AppInfo { + + override val sentryEnvironment = if (BuildConfig.DEBUG) SentryEnvironment.DEV else SentryEnvironment.PROD + + override val versionName: String = versionNameValue + +} + +enum class SentryEnvironment(val value: String) { + DEV("development"), PROD("production") +} \ No newline at end of file diff --git a/crash-reporting/build.gradle b/crash-reporting/build.gradle new file mode 100644 index 0000000000..3c680d7e84 --- /dev/null +++ b/crash-reporting/build.gradle @@ -0,0 +1,25 @@ +plugins { + id "com.android.library" + id "kotlin-android" + id "io.sentry.android.gradle" version "3.4.2" +} + +android { + sentry { + includeProguardMapping = true + autoUploadProguardMapping = true + experimentalGuardsquareSupport = false + uploadNativeSymbols = false + includeNativeSources = false + autoInstallation { + enabled = true + sentryVersion = libs.versions.sentryVersion + } + includeDependenciesReport = true + } +} + +dependencies { + implementation libs.sentry + implementation project(path: ':core-utils') +} \ No newline at end of file diff --git a/crash-reporting/src/main/AndroidManifest.xml b/crash-reporting/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..367c72637a --- /dev/null +++ b/crash-reporting/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/crash-reporting/src/main/java/com/anytypeio/anytype/SentryCrashReporter.kt b/crash-reporting/src/main/java/com/anytypeio/anytype/SentryCrashReporter.kt new file mode 100644 index 0000000000..0d774c6cab --- /dev/null +++ b/crash-reporting/src/main/java/com/anytypeio/anytype/SentryCrashReporter.kt @@ -0,0 +1,20 @@ +package com.anytypeio.anytype + +import android.content.Context +import com.anytypeio.anytype.core_utils.tools.AppInfo +import io.sentry.android.core.SentryAndroid +import io.sentry.android.core.SentryAndroidOptions + +class SentryCrashReporter( + context: Context, + appInfo: AppInfo +) { + + init { + SentryAndroid.init(context) { options: SentryAndroidOptions -> + options.release = appInfo.versionName + options.environment = appInfo.sentryEnvironment.value + } + } + +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b05d35fee5..a032418c2c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,6 +62,7 @@ roomVersion = '2.4.3' amplitudeVersion = '2.36.1' okhttpVersion = '4.2.2' coilComposeVersion = '2.2.2' +sentryVersion = '5.0.1' [libraries] middleware = { module = "io.anytype:android-mw", version.ref = "middlewareVersion" } @@ -156,6 +157,7 @@ annotations = { module = "androidx.room:room-compiler", version.ref = "roomVersi roomTesting = { module = "androidx.room:room-testing", version.ref = "roomVersion" } amplitude = { module = "com.amplitude:android-sdk", version.ref = "amplitudeVersion" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttpVersion" } +sentry = { module = "io.sentry:sentry-android", version.ref = "sentryVersion" } [bundles] diff --git a/middleware2.sh b/middleware2.sh index 302ddfd594..92f236fb58 100755 --- a/middleware2.sh +++ b/middleware2.sh @@ -4,11 +4,13 @@ TOKEN=$1 USER=$2 AMPLITUDE_RELEASE_KEY=$3 AMPLITUDE_DEBUG_KEY=$4 +SENTRY_DSN=$5 GITHUB_USER_PROPERTY="gpr.usr" GITHUB_KEY_PROPERTY="gpr.key" AMPLITUDE_DEBUG_PROPERTY="amplitude.debug" AMPLITUDE_RELEASE_PROPERTY="amplitude.release" +SENTRY_DSN_PROPERTY="sentry_dsn" if [ "$TOKEN" = "" ]; then echo "ERROR: token is empty" @@ -30,6 +32,11 @@ if [ "$AMPLITUDE_DEBUG_KEY" = "" ]; then exit 1 fi; +if [ "$SENTRY_DSN" = ""]; then + echo "ERROR: sentry_dsn is empty" + exit 1 +fi; + rm -rf github.properties touch github.properties @@ -40,4 +47,5 @@ rm -rf apikeys.properties touch apikeys.properties echo "$AMPLITUDE_DEBUG_PROPERTY=\"$AMPLITUDE_DEBUG_KEY\"" >> apikeys.properties -echo "$AMPLITUDE_RELEASE_PROPERTY=\"$AMPLITUDE_RELEASE_KEY\"" >> apikeys.properties \ No newline at end of file +echo "$AMPLITUDE_RELEASE_PROPERTY=\"$AMPLITUDE_RELEASE_KEY\"" >> apikeys.properties +echo "$SENTRY_DSN_PROPERTY=\"$SENTRY_DSN\"" >> apikeys.properties \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index fb531d4b8d..ab562671bf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -55,4 +55,5 @@ include ':app', ':test:core-models-stub', ':libs' -include ':ui-settings' \ No newline at end of file +include ':ui-settings' +include ':crash-reporting' \ No newline at end of file