diff --git a/.gitignore b/.gitignore index e2c273a..7b0f010 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ build/ *.keystore # Generated i18n resources (regenerated from i18n/*.json at build) app/src/main/res/values*/strings.xml + +# Sentry auth token (mapping upload) — secret, never commit +sentry.properties diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3c506b7..c3cb013 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -9,6 +9,7 @@ plugins { // kapt is already on the classpath via the Kotlin Gradle plugin — apply it // without a version (declaring one conflicts: "already on the classpath"). id("org.jetbrains.kotlin.kapt") + alias(libs.plugins.sentry) } // --------------------------------------------------------------------------- @@ -243,6 +244,28 @@ androidComponents { } } +// --------------------------------------------------------------------------- +// Sentry — crash reporting + ProGuard/R8 mapping upload (so release stack traces +// deobfuscate). The DSN is a public ingest endpoint and lives in source; the AUTH +// TOKEN (used only to UPLOAD mappings) is a secret and is read from the env or a +// git-ignored sentry.properties — never committed. Mapping upload is skipped (with +// a warning, not a failure) when no auth token is present, so CI/contributor builds +// without the secret still succeed. +// --------------------------------------------------------------------------- +sentry { + org.set("fabiodalez") + projectName.set("android") + authToken.set(System.getenv("SENTRY_AUTH_TOKEN")) + // Upload R8 mapping files so crash stack traces are readable in Sentry. + includeProguardMapping.set(true) + autoUploadProguardMapping.set(!System.getenv("SENTRY_AUTH_TOKEN").isNullOrBlank()) + // We call SentryAndroid.init() ourselves in PinakesApplication, so let the SDK's + // auto-install add the dependency but keep our explicit init in control. + autoInstallation { enabled.set(true) } + // Don't phone home build telemetry from this repo's builds. + telemetry.set(false) +} + dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ec19b12..d0e133a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,11 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Pinakes"> + + + + + options.dsn = + "https://a51e7537271cdf25767251d18d2e4ffa@o4511654498926592.ingest.de.sentry.io/4511654504300624" + options.environment = if (BuildConfig.DEBUG) "debug" else "production" + options.release = "${BuildConfig.APPLICATION_ID}@${BuildConfig.VERSION_NAME}+${BuildConfig.VERSION_CODE}" + options.isDebug = false + options.isSendDefaultPii = false // no IP / user data attached by default + options.tracesSampleRate = 0.0 // crash reporting only — no performance tracing + } + services = ServiceLocator(this) // Refresh the cached catalog every time the app comes to the foreground, so the diff --git a/build.gradle.kts b/build.gradle.kts index 132ad8d..09375a1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,4 +3,5 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.compose) apply false alias(libs.plugins.kotlin.serialization) apply false + alias(libs.plugins.sentry) apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a0add25..24c31da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,6 +17,7 @@ appcompat = "1.7.0" media3 = "1.4.1" room = "2.6.1" work = "2.9.1" +sentry = "4.14.1" junit = "4.13.2" coroutinesTest = "1.8.1" robolectric = "4.13" @@ -63,3 +64,4 @@ android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +sentry = { id = "io.sentry.android.gradle", version.ref = "sentry" }