Skip to content

Commit 0d800c3

Browse files
committed
build: Move from the binary-compatibility-validator plugin to KGP ABI validation
1 parent 4d96804 commit 0d800c3

61 files changed

Lines changed: 125 additions & 61 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.cursor/rules/api.mdc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: Public API surface, binary compatibility, and common classes to mod
66

77
## API Compatibility
88

9-
Public API is tracked via `.api` files generated by the [Binary Compatibility Validator](https://github.com/Kotlin/binary-compatibility-validator) Gradle plugin. Each module has its own file at `<module>/api/<module>.api`.
9+
Public API is tracked via `.api` files generated by the [ABI validation](https://kotlinlang.org/docs/gradle-binary-compatibility-validation.html) built into the Kotlin Gradle plugin. Each module has its own file at `<module>/api/<module>.api`.
1010

1111
- **Never edit `.api` files manually.** Run `./gradlew apiDump` to regenerate them.
1212
- `./gradlew check` validates current code against `.api` files and fails on unintended changes.

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ or
7676

7777
# Binary compatibility validation
7878

79-
To prevent breaking ABI changes and exposing things we should not, we make use of https://github.com/Kotlin/binary-compatibility-validator. If your change intended to introduce a new public method/property or modify the existing one you can overwrite the API declarations to make CI happy as follows (overwrites them from scratch):
79+
To prevent breaking ABI changes and exposing things we should not, we make use of https://kotlinlang.org/docs/gradle-binary-compatibility-validation.html. If your change intended to introduce a new public method/property or modify the existing one you can overwrite the API declarations to make CI happy as follows (overwrites them from scratch):
8080

8181
```shell
8282
make api

‎build-logic/build.gradle.kts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ gradlePlugin {
1515
id = "io.sentry.jdk-target"
1616
implementationClass = "io.sentry.gradle.JdkTargetConvention"
1717
}
18+
register("sentryApiValidation") {
19+
id = "io.sentry.api-validation"
20+
implementationClass = "io.sentry.gradle.SentryApiValidationPlugin"
21+
}
1822
register("sentryAnimalSniffer") {
1923
id = "io.sentry.animalsniffer"
2024
implementationClass = "io.sentry.gradle.SentryAnimalSnifferPlugin"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.sentry.gradle
2+
3+
import org.gradle.api.provider.SetProperty
4+
5+
/** Configuration for the `io.sentry.api-validation` convention plugin. */
6+
abstract class ApiValidationExtension {
7+
/**
8+
* Packages that are public to the JVM but not part of the SDK's API, and so are left out of the
9+
* dump. Subpackages are left out too.
10+
*/
11+
abstract val ignoredPackages: SetProperty<String>
12+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package io.sentry.gradle
2+
3+
import org.gradle.api.GradleException
4+
import org.gradle.api.Plugin
5+
import org.gradle.api.Project
6+
import org.gradle.api.plugins.ExtensionAware
7+
import org.gradle.kotlin.dsl.create
8+
import org.jetbrains.kotlin.gradle.dsl.abi.AbiValidationExtension
9+
import org.jetbrains.kotlin.gradle.dsl.abi.AbiValidationMultiplatformExtension
10+
import org.jetbrains.kotlin.gradle.dsl.abi.AbiValidationVariantSpec
11+
import org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation
12+
13+
private val KOTLIN_PLUGIN_IDS =
14+
listOf(
15+
"org.jetbrains.kotlin.jvm",
16+
"org.jetbrains.kotlin.android",
17+
"org.jetbrains.kotlin.multiplatform",
18+
)
19+
20+
/**
21+
* Checks the public ABI of a module against the dump checked into its `api` directory, using the
22+
* Kotlin Gradle plugin's own ABI validation. Adds `checkKotlinAbi`, which `check` depends on, and
23+
* `updateKotlinAbi`, which rewrites the dump.
24+
*/
25+
@OptIn(ExperimentalAbiValidation::class)
26+
class SentryApiValidationPlugin : Plugin<Project> {
27+
override fun apply(project: Project) {
28+
val extension = project.extensions.create<ApiValidationExtension>("sentryApiValidation")
29+
30+
// The abiValidation extension only exists once a Kotlin plugin has been applied, and a module
31+
// may list this plugin before that one.
32+
KOTLIN_PLUGIN_IDS.forEach {
33+
project.pluginManager.withPlugin(it) { enable(project, extension) }
34+
}
35+
36+
// Aliases for backwards compat with the old binary-compatibility-validator plugin.
37+
project.tasks.register("apiDump") { dependsOn("updateKotlinAbi") }
38+
project.tasks.register("apiCheck") { dependsOn("checkKotlinAbi") }
39+
}
40+
41+
private fun enable(project: Project, extension: ApiValidationExtension) {
42+
val kotlin = project.extensions.getByName("kotlin") as ExtensionAware
43+
val spec: AbiValidationVariantSpec =
44+
when (val abi = kotlin.extensions.getByName("abiValidation")) {
45+
is AbiValidationMultiplatformExtension -> abi.also { it.enabled.set(true) }
46+
is AbiValidationExtension -> abi.also { it.enabled.set(true) }
47+
else -> throw GradleException("Unexpected abiValidation extension: ${abi.javaClass.name}")
48+
}
49+
// Lazy, because the module configures the extension after this plugin has been applied.
50+
val ignored = extension.ignoredPackages.map { packages -> packages.map { "$it.**" } }
51+
spec.filters { exclude { byNames.addAll(ignored) } }
52+
}
53+
}

‎build.gradle.kts‎

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ plugins {
1111
alias(libs.plugins.spotless) apply false
1212
alias(libs.plugins.detekt)
1313
`maven-publish`
14-
alias(libs.plugins.binary.compatibility.validator)
1514
alias(libs.plugins.vanniktech.maven.publish) apply false
1615
alias(libs.plugins.kotlin.android) apply false
1716
alias(libs.plugins.kotlin.multiplatform) apply false
@@ -47,52 +46,6 @@ buildscript {
4746
}
4847
}
4948

50-
apiValidation {
51-
ignoredPackages.addAll(
52-
setOf(
53-
"io.sentry.android.core.internal"
54-
)
55-
)
56-
ignoredProjects.addAll(
57-
listOf(
58-
"sentry-samples-android",
59-
"sentry-samples-console",
60-
"sentry-samples-console-opentelemetry-noagent",
61-
"sentry-samples-jul",
62-
"sentry-samples-log4j2",
63-
"sentry-samples-logback",
64-
"sentry-samples-openfeign",
65-
"sentry-samples-servlet",
66-
"sentry-samples-spring",
67-
"sentry-samples-spring-jakarta",
68-
"sentry-samples-spring-7",
69-
"sentry-samples-spring-boot",
70-
"sentry-samples-spring-boot-opentelemetry",
71-
"sentry-samples-spring-boot-opentelemetry-noagent",
72-
"sentry-samples-spring-boot-jakarta",
73-
"sentry-samples-spring-boot-jakarta-log4j2",
74-
"sentry-samples-spring-boot-jakarta-opentelemetry",
75-
"sentry-samples-spring-boot-jakarta-opentelemetry-noagent",
76-
"sentry-samples-spring-boot-webflux",
77-
"sentry-samples-spring-boot-webflux-jakarta",
78-
"sentry-samples-spring-boot-4",
79-
"sentry-samples-spring-boot-4-log4j2",
80-
"sentry-samples-spring-boot-4-opentelemetry",
81-
"sentry-samples-spring-boot-4-opentelemetry-noagent",
82-
"sentry-samples-spring-boot-4-otlp",
83-
"sentry-samples-spring-boot-4-webflux",
84-
"sentry-samples-ktor-client",
85-
"sentry-uitest-android",
86-
"sentry-uitest-android-critical",
87-
"test-app-size",
88-
"sentry-samples-netflix-dgs",
89-
"sentry-samples-console-otlp",
90-
"sentry-test-support",
91-
"sentry-system-test-support"
92-
)
93-
)
94-
}
95-
9649
allprojects {
9750
group = Config.Sentry.group
9851
version = providers.gradleProperty(Config.Sentry.versionNameProp).get()

‎gradle/libs.versions.toml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
6666
buildconfig = { id = "com.github.gmazzo.buildconfig", version = "5.6.5" }
6767
dokka = { id = "org.jetbrains.dokka", version = "2.0.0" }
6868
dokka-javadoc = { id = "org.jetbrains.dokka-javadoc", version = "2.0.0" }
69-
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.13.0" }
7069
errorprone = { id = "net.ltgt.errorprone", version = "5.1.1" }
7170
gradle-versions = { id = "com.github.ben-manes.versions", version = "0.42.0" }
7271
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }

‎sentry-android-core/build.gradle.kts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ plugins {
88
alias(libs.plugins.kotlin.compose)
99
alias(libs.plugins.errorprone)
1010
alias(libs.plugins.gradle.versions)
11+
id("io.sentry.api-validation")
1112
}
1213

1314
android {
@@ -135,3 +136,5 @@ dependencies {
135136
testRuntimeOnly(libs.androidx.fragment.ktx)
136137
testRuntimeOnly(libs.timber)
137138
}
139+
140+
sentryApiValidation { ignoredPackages.add("io.sentry.android.core.internal") }

‎sentry-android-distribution/build.gradle.kts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ plugins {
55
id("com.android.library")
66
alias(libs.plugins.kotlin.android)
77
alias(libs.plugins.detekt)
8+
id("io.sentry.api-validation")
89
}
910

1011
android {

‎sentry-android-fragment/build.gradle.kts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugins {
77
alias(libs.plugins.kotlin.android)
88
alias(libs.plugins.gradle.versions)
99
alias(libs.plugins.detekt)
10+
id("io.sentry.api-validation")
1011
}
1112

1213
android {

0 commit comments

Comments
 (0)