From ba470e3d9ac33c74801e390ce7795fcbcfb80b1f Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Wed, 15 Jul 2026 16:32:44 +0200 Subject: [PATCH] build: Extract shared Android lint config into a build-logic plugin Replace the lint {} block copy-pasted across the Android modules with a single io.sentry.android.lint convention plugin, applied to every Android module except the sample. Adds ignoreTestSources (skips test-source analysis, the dominant lint cost) and checkGeneratedSources to the shared config, and centralizes the OldTargetApi suppression. AGP is a compileOnly dependency of build-logic so each module supplies its own AGP at runtime, keeping the AGP compatibility matrix unaffected. The test/benchmark apps carry pre-existing lint issues, so they get lint baselines rather than blocking the strict config. Co-Authored-By: Claude Opus 4.8 --- build-logic/build.gradle.kts | 2 + .../kotlin/io.sentry.android.lint.gradle.kts | 25 +++ gradle/libs.versions.toml | 4 + sentry-android-core/build.gradle.kts | 9 +- sentry-android-distribution/build.gradle.kts | 1 + sentry-android-fragment/build.gradle.kts | 9 +- .../build.gradle.kts | 11 +- .../build.gradle.kts | 4 + .../lint-baseline.xml | 26 +++ .../sentry-uitest-android/build.gradle.kts | 11 +- .../test-app-plain/build.gradle.kts | 8 +- .../test-app-plain/lint-baseline.xml | 202 ++++++++++++++++++ .../test-app-sentry/build.gradle.kts | 8 +- .../test-app-sentry/lint-baseline.xml | 202 ++++++++++++++++++ .../test-app-size/build.gradle.kts | 1 + sentry-android-navigation/build.gradle.kts | 9 +- sentry-android-ndk/build.gradle.kts | 9 +- sentry-android-replay/build.gradle.kts | 9 +- sentry-android-sqlite/build.gradle.kts | 9 +- sentry-android-timber/build.gradle.kts | 9 +- sentry-android/build.gradle.kts | 1 + sentry-compose/build.gradle.kts | 9 +- sentry-launchdarkly-android/build.gradle.kts | 9 +- 23 files changed, 493 insertions(+), 94 deletions(-) create mode 100644 build-logic/src/main/kotlin/io.sentry.android.lint.gradle.kts create mode 100644 sentry-android-integration-tests/sentry-uitest-android-critical/lint-baseline.xml create mode 100644 sentry-android-integration-tests/test-app-plain/lint-baseline.xml create mode 100644 sentry-android-integration-tests/test-app-sentry/lint-baseline.xml diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index bba758f9b79..b0e36c757d4 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -3,12 +3,14 @@ plugins { } repositories { + google() gradlePluginPortal() } dependencies { implementation(libs.animalsniffer.gradle.plugin) implementation(libs.spotlessLib) + compileOnly(libs.android.gradle.plugin) } gradlePlugin { diff --git a/build-logic/src/main/kotlin/io.sentry.android.lint.gradle.kts b/build-logic/src/main/kotlin/io.sentry.android.lint.gradle.kts new file mode 100644 index 00000000000..88424594ca7 --- /dev/null +++ b/build-logic/src/main/kotlin/io.sentry.android.lint.gradle.kts @@ -0,0 +1,25 @@ +import com.android.build.api.dsl.CommonExtension + +// Shared Android lint configuration for the SDK's library and application modules. +// See Tor Norbye's rationale for checkGeneratedSources/checkDependencies: +// https://groups.google.com/forum/#!msg/lint-dev/JqTI4eQ8GpI/nBfS7xLKBwAJ +pluginManager.withPlugin("com.android.base") { + extensions.configure(CommonExtension::class.java) { + lint { + warningsAsErrors = true + // Avoids false "unused" reports for code used only by generated classes (e.g. ViewBinding). + checkGeneratedSources = true + // Lets `:module:lint` also analyze dependency modules. + checkDependencies = true + // Test sources dominate lint time; skipping them is the main speed-up. + ignoreTestSources = true + + // Suppress OldTargetApi: lint 8.13.1 expects API 37 but we target 36. Only the + // application modules set targetSdk, so this is a no-op for the library modules. + disable += "OldTargetApi" + + // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. + checkReleaseBuilds = false + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1fd275d06f8..f40c64abf49 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,6 +36,9 @@ otelSemanticConventionsAlpha = "1.42.0-alpha" retrofit = "2.9.0" room2 = "2.8.4" room3 = "3.0.0-rc01" +# Keep in sync with Config.AGP in buildSrc (the version modules actually build with). +# Used compile-only by build-logic to configure the Android lint DSL. +agp = "8.13.1" sagp = "6.13.0" sqlite = "2.6.2" sqliteRc = "2.7.0-rc01" # Required by Room3 3.0.0-rc* @@ -77,6 +80,7 @@ sentry = { id = "io.sentry.android.gradle", version.ref = "sagp"} shadow = { id = "com.gradleup.shadow", version = "9.4.1" } [libraries] +android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } animalsniffer-gradle-plugin = { module = "ru.vyarus:gradle-animalsniffer-plugin", version.ref = "animalsniffer" } apache-httpclient = { module = "org.apache.httpcomponents.client5:httpclient5", version = "5.0.4" } apollo2-coroutines = { module = "com.apollographql.apollo:apollo-coroutines-support", version.ref = "apollo" } diff --git a/sentry-android-core/build.gradle.kts b/sentry-android-core/build.gradle.kts index 0388b7de486..7250966c95a 100644 --- a/sentry-android-core/build.gradle.kts +++ b/sentry-android-core/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.kotlin.compose) alias(libs.plugins.errorprone) alias(libs.plugins.gradle.versions) + id("io.sentry.android.lint") } android { @@ -49,14 +50,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } // needed because of Kotlin 1.4.x diff --git a/sentry-android-distribution/build.gradle.kts b/sentry-android-distribution/build.gradle.kts index 2d23bf3ab74..bbc64ccf77c 100644 --- a/sentry-android-distribution/build.gradle.kts +++ b/sentry-android-distribution/build.gradle.kts @@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion plugins { id("com.android.library") alias(libs.plugins.kotlin.android) + id("io.sentry.android.lint") } android { diff --git a/sentry-android-fragment/build.gradle.kts b/sentry-android-fragment/build.gradle.kts index 1bd182d618c..9f27d03314e 100644 --- a/sentry-android-fragment/build.gradle.kts +++ b/sentry-android-fragment/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.gradle.versions) alias(libs.plugins.detekt) + id("io.sentry.android.lint") } android { @@ -37,14 +38,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } androidComponents.beforeVariants { diff --git a/sentry-android-integration-tests/sentry-uitest-android-benchmark/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-benchmark/build.gradle.kts index 459c1653fa9..73f40453c87 100644 --- a/sentry-android-integration-tests/sentry-uitest-android-benchmark/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-uitest-android-benchmark/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.errorprone) alias(libs.plugins.gradle.versions) alias(libs.plugins.detekt) + id("io.sentry.android.lint") } android { @@ -66,16 +67,6 @@ android { kotlin { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } - lint { - warningsAsErrors = true - checkDependencies = true - // Suppress OldTargetApi: lint 8.13.1 expects API 37 but we target 36 - disable += "OldTargetApi" - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - androidComponents.beforeVariants { if (it.buildType == "debug") { it.enable = false diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts index 4b0cd68ca90..2df7ced07ec 100644 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts @@ -4,12 +4,16 @@ plugins { id("com.android.application") alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) + id("io.sentry.android.lint") } android { compileSdk = libs.versions.compileSdk.get().toInt() namespace = "io.sentry.uitest.android.critical" + // Baseline the pre-existing lint issues in this test app; only new issues fail the build. + lint { baseline = file("lint-baseline.xml") } + signingConfigs { getByName("debug") { // Debug config remains unchanged diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/lint-baseline.xml b/sentry-android-integration-tests/sentry-uitest-android-critical/lint-baseline.xml new file mode 100644 index 00000000000..d55ca3b7670 --- /dev/null +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/lint-baseline.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts index 1d725b0b595..cd3ca81b769 100644 --- a/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.errorprone) alias(libs.plugins.gradle.versions) alias(libs.plugins.detekt) + id("io.sentry.android.lint") } android { @@ -64,16 +65,6 @@ android { kotlin { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } - lint { - warningsAsErrors = true - checkDependencies = true - // Suppress OldTargetApi: lint 8.13.1 expects API 37 but we target 36 - disable += "OldTargetApi" - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - androidComponents.beforeVariants { if (it.buildType == "debug") { it.enable = false diff --git a/sentry-android-integration-tests/test-app-plain/build.gradle.kts b/sentry-android-integration-tests/test-app-plain/build.gradle.kts index 9778363ede8..5cac8b3030e 100644 --- a/sentry-android-integration-tests/test-app-plain/build.gradle.kts +++ b/sentry-android-integration-tests/test-app-plain/build.gradle.kts @@ -1,9 +1,15 @@ -plugins { id("com.android.application") } +plugins { + id("com.android.application") + id("io.sentry.android.lint") +} android { compileSdk = libs.versions.compileSdk.get().toInt() namespace = "io.sentry.java.tests.perf.appplain" + // Baseline the pre-existing lint issues in this test app; only new issues fail the build. + lint { baseline = file("lint-baseline.xml") } + defaultConfig { applicationId = "io.sentry.java.tests.perf.appplain" minSdk = libs.versions.minSdk.get().toInt() diff --git a/sentry-android-integration-tests/test-app-plain/lint-baseline.xml b/sentry-android-integration-tests/test-app-plain/lint-baseline.xml new file mode 100644 index 00000000000..60dc4422e54 --- /dev/null +++ b/sentry-android-integration-tests/test-app-plain/lint-baseline.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sentry-android-integration-tests/test-app-sentry/build.gradle.kts b/sentry-android-integration-tests/test-app-sentry/build.gradle.kts index db0cb4a46ab..ac47578f3c4 100644 --- a/sentry-android-integration-tests/test-app-sentry/build.gradle.kts +++ b/sentry-android-integration-tests/test-app-sentry/build.gradle.kts @@ -1,9 +1,15 @@ -plugins { id("com.android.application") } +plugins { + id("com.android.application") + id("io.sentry.android.lint") +} android { compileSdk = libs.versions.compileSdk.get().toInt() namespace = "io.sentry.java.tests.perf.appsentry" + // Baseline the pre-existing lint issues in this test app; only new issues fail the build. + lint { baseline = file("lint-baseline.xml") } + defaultConfig { applicationId = "io.sentry.java.tests.perf.appsentry" minSdk = libs.versions.minSdk.get().toInt() diff --git a/sentry-android-integration-tests/test-app-sentry/lint-baseline.xml b/sentry-android-integration-tests/test-app-sentry/lint-baseline.xml new file mode 100644 index 00000000000..60dc4422e54 --- /dev/null +++ b/sentry-android-integration-tests/test-app-sentry/lint-baseline.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sentry-android-integration-tests/test-app-size/build.gradle.kts b/sentry-android-integration-tests/test-app-size/build.gradle.kts index 20af6dad6ae..342a5141d77 100644 --- a/sentry-android-integration-tests/test-app-size/build.gradle.kts +++ b/sentry-android-integration-tests/test-app-size/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("com.android.application") id("io.sentry.android.gradle") + id("io.sentry.android.lint") } android { diff --git a/sentry-android-navigation/build.gradle.kts b/sentry-android-navigation/build.gradle.kts index eaa204b3860..0b3a83b1fcf 100644 --- a/sentry-android-navigation/build.gradle.kts +++ b/sentry-android-navigation/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.gradle.versions) alias(libs.plugins.detekt) + id("io.sentry.android.lint") } android { @@ -37,14 +38,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } androidComponents.beforeVariants { diff --git a/sentry-android-ndk/build.gradle.kts b/sentry-android-ndk/build.gradle.kts index c2d0a33d823..348516de5a9 100644 --- a/sentry-android-ndk/build.gradle.kts +++ b/sentry-android-ndk/build.gradle.kts @@ -4,6 +4,7 @@ plugins { id("com.android.library") alias(libs.plugins.kotlin.android) alias(libs.plugins.gradle.versions) + id("io.sentry.android.lint") } android { @@ -36,14 +37,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - // needed because of Kotlin 1.4.x configurations.all { resolutionStrategy.force(libs.jetbrains.annotations.get()) } diff --git a/sentry-android-replay/build.gradle.kts b/sentry-android-replay/build.gradle.kts index 8d0f63797aa..3b9b06f4475 100644 --- a/sentry-android-replay/build.gradle.kts +++ b/sentry-android-replay/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) alias(libs.plugins.gradle.versions) + id("io.sentry.android.lint") // TODO: enable it later // alias(libs.plugins.detekt) } @@ -49,14 +50,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } androidComponents.beforeVariants { diff --git a/sentry-android-sqlite/build.gradle.kts b/sentry-android-sqlite/build.gradle.kts index 6e0275b29b8..23b8bc87780 100644 --- a/sentry-android-sqlite/build.gradle.kts +++ b/sentry-android-sqlite/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.gradle.versions) alias(libs.plugins.detekt) + id("io.sentry.android.lint") } android { @@ -37,14 +38,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } // Needed b/c Kotlin 1.4.x would otherwise pull in an older version without the annotations we diff --git a/sentry-android-timber/build.gradle.kts b/sentry-android-timber/build.gradle.kts index d8f8431bef1..f2489a04848 100644 --- a/sentry-android-timber/build.gradle.kts +++ b/sentry-android-timber/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.gradle.versions) alias(libs.plugins.detekt) + id("io.sentry.android.lint") } android { @@ -44,14 +45,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } androidComponents.beforeVariants { diff --git a/sentry-android/build.gradle.kts b/sentry-android/build.gradle.kts index a2d92829b29..c1404170d5c 100644 --- a/sentry-android/build.gradle.kts +++ b/sentry-android/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("com.android.library") alias(libs.plugins.kotlin.android) alias(libs.plugins.gradle.versions) + id("io.sentry.android.lint") } android { diff --git a/sentry-compose/build.gradle.kts b/sentry-compose/build.gradle.kts index c45a431b1b3..a58e1eee846 100644 --- a/sentry-compose/build.gradle.kts +++ b/sentry-compose/build.gradle.kts @@ -9,6 +9,7 @@ plugins { id("com.android.library") alias(libs.plugins.gradle.versions) alias(libs.plugins.detekt) + id("io.sentry.android.lint") alias(libs.plugins.dokka) alias(libs.plugins.dokka.javadoc) `maven-publish` // necessary for publishMavenLocal task to publish correct artifacts @@ -102,14 +103,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } androidComponents.beforeVariants { diff --git a/sentry-launchdarkly-android/build.gradle.kts b/sentry-launchdarkly-android/build.gradle.kts index 427ec473676..7ad018e045b 100644 --- a/sentry-launchdarkly-android/build.gradle.kts +++ b/sentry-launchdarkly-android/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("com.android.library") alias(libs.plugins.kotlin.android) alias(libs.plugins.gradle.versions) + id("io.sentry.android.lint") } android { @@ -37,14 +38,6 @@ android { } } - lint { - warningsAsErrors = true - checkDependencies = true - - // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks. - checkReleaseBuilds = false - } - buildFeatures { buildConfig = true } androidComponents.beforeVariants {