Skip to content

Commit a4b04eb

Browse files
committed
Move from bcv plugin to KGP api validation
1 parent f8f3432 commit a4b04eb

61 files changed

Lines changed: 127 additions & 62 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

‎Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ checkFormat:
3232

3333
# Binary compatibility validator
3434
api:
35-
./gradlew apiDump
35+
./gradlew updateKotlinAbi
3636

3737
# Assemble release and Android test apk of the uitest-android module
3838
assembleUiTestRelease:

‎build-logic/build.gradle.kts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ gradlePlugin {
1717
id = "io.sentry.jdk-target"
1818
implementationClass = "io.sentry.gradle.JdkTargetConvention"
1919
}
20+
register("sentryApiValidation") {
21+
id = "io.sentry.api-validation"
22+
implementationClass = "io.sentry.gradle.SentryApiValidationPlugin"
23+
}
2024
register("sentryDetekt") {
2125
id = "io.sentry.detekt"
2226
implementationClass = "io.sentry.gradle.SentryDetektPlugin"
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
@@ -6,7 +6,6 @@ plugins {
66
alias(libs.plugins.spotless) apply false
77
alias(libs.plugins.detekt)
88
`maven-publish`
9-
alias(libs.plugins.binary.compatibility.validator)
109
alias(libs.plugins.kotlin.android) apply false
1110
alias(libs.plugins.kotlin.multiplatform) apply false
1211
alias(libs.plugins.kotlin.jvm) apply false
@@ -41,52 +40,6 @@ buildscript {
4140
}
4241
}
4342

44-
apiValidation {
45-
ignoredPackages.addAll(
46-
setOf(
47-
"io.sentry.android.core.internal"
48-
)
49-
)
50-
ignoredProjects.addAll(
51-
listOf(
52-
"sentry-samples-android",
53-
"sentry-samples-console",
54-
"sentry-samples-console-opentelemetry-noagent",
55-
"sentry-samples-jul",
56-
"sentry-samples-log4j2",
57-
"sentry-samples-logback",
58-
"sentry-samples-openfeign",
59-
"sentry-samples-servlet",
60-
"sentry-samples-spring",
61-
"sentry-samples-spring-jakarta",
62-
"sentry-samples-spring-7",
63-
"sentry-samples-spring-boot",
64-
"sentry-samples-spring-boot-opentelemetry",
65-
"sentry-samples-spring-boot-opentelemetry-noagent",
66-
"sentry-samples-spring-boot-jakarta",
67-
"sentry-samples-spring-boot-jakarta-log4j2",
68-
"sentry-samples-spring-boot-jakarta-opentelemetry",
69-
"sentry-samples-spring-boot-jakarta-opentelemetry-noagent",
70-
"sentry-samples-spring-boot-webflux",
71-
"sentry-samples-spring-boot-webflux-jakarta",
72-
"sentry-samples-spring-boot-4",
73-
"sentry-samples-spring-boot-4-log4j2",
74-
"sentry-samples-spring-boot-4-opentelemetry",
75-
"sentry-samples-spring-boot-4-opentelemetry-noagent",
76-
"sentry-samples-spring-boot-4-otlp",
77-
"sentry-samples-spring-boot-4-webflux",
78-
"sentry-samples-ktor-client",
79-
"sentry-uitest-android",
80-
"sentry-uitest-android-critical",
81-
"test-app-size",
82-
"sentry-samples-netflix-dgs",
83-
"sentry-samples-console-otlp",
84-
"sentry-test-support",
85-
"sentry-system-test-support"
86-
)
87-
)
88-
}
89-
9043
allprojects {
9144
group = Config.Sentry.group
9245
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
@@ -69,7 +69,6 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
6969
buildconfig = { id = "com.github.gmazzo.buildconfig", version = "5.6.5" }
7070
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
7171
dokka-javadoc = { id = "org.jetbrains.dokka-javadoc", version.ref = "dokka" }
72-
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.13.0" }
7372
errorprone = { id = "net.ltgt.errorprone", version = "5.1.1" }
7473
gradle-versions = { id = "com.github.ben-manes.versions", version = "0.42.0" }
7574
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ plugins {
1010
alias(libs.plugins.gradle.versions)
1111
id("io.sentry.spotless")
1212
id("io.sentry.jdk-target")
13+
id("io.sentry.api-validation")
1314
id("io.sentry.publish")
1415
}
1516

@@ -138,3 +139,7 @@ dependencies {
138139
testRuntimeOnly(libs.androidx.fragment.ktx)
139140
testRuntimeOnly(libs.timber)
140141
}
142+
143+
sentryApiValidation {
144+
ignoredPackages.add("io.sentry.android.core.internal")
145+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugins {
77
id("io.sentry.detekt")
88
id("io.sentry.spotless")
99
id("io.sentry.jdk-target")
10+
id("io.sentry.api-validation")
1011
id("io.sentry.publish")
1112
}
1213

0 commit comments

Comments
 (0)