-
Notifications
You must be signed in to change notification settings - Fork 15.3k
KAFKA-20032: KIP-1265 Automatic detection of internal API usage #21337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ashwinpankaj
wants to merge
42
commits into
apache:trunk
Choose a base branch
from
ashwinpankaj:ashwinpankaj/KIP-1265
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+9,478
−44
Open
Changes from 34 commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
05ad69d
[KAFKA-20032] KIP-1265 Mechanism for automatic detection of internal …
ashwinpankaj cf91154
Fix typo
ashwinpankaj c874c97
[KAFKA-20032] KIP-1265 review follow-ups: audience annotation, ASM sc…
ashwinpankaj 2eebaa3
[KAFKA-20032] KIP-1265: annotate clients + escape hatch + SOLID refactor
ashwinpankaj ec9576e
[KAFKA-20032] KIP-1265: annotate :tools:tools-api with @InterfaceAudi…
ashwinpankaj 9fb8f35
[KAFKA-20032] KIP-1265: annotate :storage:storage-api + add reference…
ashwinpankaj 2343458
[KAFKA-20032] KIP-1265: annotate :group-coordinator:group-coordinator…
ashwinpankaj e56e309
[KAFKA-20032] KIP-1265: annotate connect/ docsJar modules with @Inter…
ashwinpankaj a60a161
[KAFKA-20032] KIP-1265: annotate streams/ docsJar modules + chain-wal…
ashwinpankaj f7f00e9
MINOR: spotless cleanup after KIP-1265 annotations
ashwinpankaj c8f7d3e
[KAFKA-20032] KIP-1265 buildSrc hardening: validator refactor, plugin…
ashwinpankaj f61f7ff
MINOR: drop spotless plugin and dead validateKafkaPlugins task from b…
ashwinpankaj 23d195d
[KAFKA-20032] KIP-1265: wire javadocJarPath to the javadocJar task's …
ashwinpankaj aab8a15
[KAFKA-20032] KIP-1265: annotate group-coordinator-api streams types …
ashwinpankaj 37db831
[KAFKA-20032] KIP-1265: ship the internal-API-checker plugin artifact…
ashwinpankaj 4ea9476
MINOR: KIP-1265 docs — call out the Kafka version requirement for the…
ashwinpankaj 0f57a05
[KAFKA-20032] KIP-1265: react to JavaPlugin instead of afterEvaluate;…
ashwinpankaj 60b985e
MINOR: KIP-1265 — commit the missing checkstyle/import-control-builds…
ashwinpankaj ed2101e
Merge branch 'trunk' into ashwinpankaj/KIP-1265
ashwinpankaj 6735f8f
[KAFKA-20032] KIP-1265 review follow-ups: formatting + plugin publishing
ashwinpankaj 54f34ad
[KAFKA-20032] KIP-1265: fix three review-blocking checker bugs
ashwinpankaj 7a84a5d
[KAFKA-20032] KIP-1265: remove dead checker config knobs
ashwinpankaj d7fa2c9
[KAFKA-20032] KIP-1265: fix misleading 'Project JAR file not found' d…
ashwinpankaj f7b2814
[KAFKA-20032] KIP-1265: declare Kafka dep jars as a task input
ashwinpankaj 1e23715
[KAFKA-20032] KIP-1265: template plugin.xml so versions can't drift
ashwinpankaj ec39d76
[KAFKA-20032] KIP-1265: cover the consumer Gradle path in Kafka CI
ashwinpankaj 40ad86d
[KAFKA-20032] KIP-1265: minor / quality cleanups in the checker
ashwinpankaj 9a2390d
[KAFKA-20032] KIP-1265: collapse duplicate DTO + enclosing-chain walks
ashwinpankaj b54d21d
[KAFKA-20032] KIP-1265: drop JSON report, rename publicapi -> apicheck
ashwinpankaj 88f5443
[KAFKA-20032] KIP-1265: suppress forced MemberData leak on sticky ass…
ashwinpankaj 107ea3b
Merge branch 'apache:trunk' into ashwinpankaj/KIP-1265
ashwinpankaj 0967a42
[KAFKA-20032] KIP-1265: suppress field-cascade leaks surfaced by the …
ashwinpankaj 67593b1
Merge remote-tracking branch 'origin/trunk' into ashwinpankaj/KIP-1265
ashwinpankaj 4073b18
[KAFKA-20032] KIP-1265: annotate StreamsGroupTopologyDescription admi…
ashwinpankaj d04158c
[KAFKA-20032] KIP-1265: review responses (generic signatures, Maven s…
ashwinpankaj 8cc8593
[KAFKA-20032] KIP-1265: extract checker out of buildSrc into a 3-modu…
ashwinpankaj 3724641
Merge branch 'trunk' into ashwinpankaj/KIP-1265
ashwinpankaj 4fdbe5f
[KAFKA-20032] KIP-1265 polish: ASM doc, @Target, defensive copies, re…
ashwinpankaj 83c7818
[KAFKA-20032] KIP-1265 polish: unify enclosing-chain walks (Bug #5) +…
ashwinpankaj a9cfa3e
[KAFKA-20032] KIP-1265 polish: supertype cascade, skip-property gate,…
ashwinpankaj 9875211
[KAFKA-20032] KIP-1265 polish: drop stale buildSrc framing, lift coll…
ashwinpankaj b50d478
[KAFKA-20032] KIP-1265: revert inadvertent blank-line-only changes to…
ashwinpankaj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| # Kafka API-checker plugins (buildSrc) | ||
|
|
||
| This module builds the KIP-1265 API-checker plugins from a single source tree: | ||
|
|
||
| | Plugin / Mojo | ID / artifactId | Audience | | ||
| |---|---|---| | ||
| | `KafkaPublicApiCheckerPlugin` | `org.apache.kafka.public-api-checker` (Gradle) | Internal — applied to Kafka's own build to validate that `@InterfaceAudience.Public` types only expose other public types, and that javadoc inclusion matches the audience annotations. | | ||
| | `KafkaInternalApiCheckerPlugin` | `org.apache.kafka.internal-api-checker` (Gradle) | External — published for plugin/connector/Streams-app developers to detect references from their bytecode to non-`@Public` Kafka classes. | | ||
| | `KafkaInternalApiCheckerMojo` | `org.apache.kafka:kafka-internal-api-checker-maven-plugin` | External — Maven equivalent of the Gradle internal-API checker. | | ||
|
|
||
| All three share the bytecode scanner and reporting code under `org.apache.kafka.apicheck`. ASM (9.6) does the scanning; nothing in the checker classloads scanned bytecode. | ||
|
|
||
| End-user documentation (Gradle/Maven snippets, `@SuppressKafkaInternalApiUsage`, audience-inheritance rules) lives at [`docs/apis/internal-api-checker.md`](../docs/apis/internal-api-checker.md). The notes below cover building, testing, and publishing the plugins themselves. | ||
|
|
||
| ## Build | ||
|
|
||
| ```bash | ||
| ./gradlew :buildSrc:build | ||
| ``` | ||
|
|
||
| Produces both Gradle plugin jars, the Maven plugin jar (with `META-INF/maven/plugin.xml`), and runs the unit tests. | ||
|
|
||
| ## Test | ||
|
|
||
| ```bash | ||
| ./gradlew :buildSrc:test | ||
| ``` | ||
|
|
||
| Includes a Gradle TestKit end-to-end test that applies the published `org.apache.kafka.internal-api-checker` plugin to a synthetic consumer project. | ||
|
|
||
| ## Publish | ||
|
|
||
| Both publications inherit the release version from `-PkafkaPluginsVersion` and stage to the URL passed via `-PmavenUrl` (with `-PmavenUsername` / `-PmavenPassword` for credentials). With no overrides the version is `1.0.0-SNAPSHOT` and the publish URL is empty (so `publish` is a no-op suitable for local smoke-testing of the artifact layout). | ||
|
|
||
| ```bash | ||
| # Stage to ASF Nexus alongside the rest of an AK release | ||
| ./gradlew :buildSrc:publish \ | ||
| -PkafkaPluginsVersion=$KAFKA_VERSION \ | ||
| -PmavenUrl=$ASF_NEXUS_STAGING_URL \ | ||
| -PmavenUsername=$NEXUS_USER \ | ||
| -PmavenPassword=$NEXUS_PASS | ||
|
|
||
| # Local smoke-test | ||
| ./gradlew :buildSrc:publish -PmavenUrl=file:///tmp/local-repo | ||
| ``` | ||
|
|
||
| The publish task produces three artifacts: | ||
|
|
||
| - `org.apache.kafka:kafka-internal-api-checker-maven-plugin:$KAFKA_VERSION` — Maven plugin (packaging `maven-plugin`). | ||
| - `org.apache.kafka.internal-api-checker:org.apache.kafka.internal-api-checker.gradle.plugin:$KAFKA_VERSION` — Gradle plugin marker that resolves `kafkaInternalApiChecker` to the implementation jar. | ||
| - `org.apache.kafka:buildSrc:$KAFKA_VERSION` — the implementation jar that backs the Gradle plugin marker. (`pluginMaven` publication; the jar name comes from this module's directory.) | ||
|
|
||
| Gradle Plugin Portal publishing is not wired here; the internal-API-checker is distributed through the same Maven coordinates as the rest of Kafka so existing AK consumers don't need a second repository. | ||
|
|
||
| ## Layout | ||
|
|
||
| ``` | ||
| buildSrc/ | ||
| ├── build.gradle | ||
| ├── src/main/java/org/apache/kafka/ | ||
| │ ├── gradle/ | ||
| │ │ ├── KafkaInternalApiCheckerPlugin.java # External Gradle plugin | ||
| │ │ ├── KafkaInternalApiCheckerTask.java | ||
| │ │ ├── KafkaInternalApiCheckerExtension.java | ||
| │ │ ├── KafkaPublicApiCheckerPlugin.java # Kafka-internal Gradle plugin | ||
| │ │ ├── KafkaPublicApiCheckerTask.java | ||
| │ │ └── KafkaPublicApiCheckerExtension.java | ||
| │ ├── maven/ | ||
| │ │ └── KafkaInternalApiCheckerMojo.java # External Maven mojo | ||
| │ └── apicheck/ # Shared scanner / validator / reporter | ||
| │ ├── ApiSurface.java | ||
| │ ├── ApiSurfaceScanner.java | ||
| │ ├── CascadeValidator.java | ||
| │ ├── JavadocConsistencyValidator.java | ||
| │ ├── PluginDeveloperApiUsageScanner.java | ||
| │ ├── PublicApiChecker.java | ||
| │ └── ViolationReporter.java | ||
| └── src/main/resources/META-INF/maven/org.apache.kafka/ | ||
| └── kafka-internal-api-checker-maven-plugin/plugin.xml | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,244 @@ | ||
| plugins { | ||
| id 'java-gradle-plugin' | ||
| id 'maven-publish' | ||
| id 'java-library' | ||
| id 'checkstyle' | ||
| id 'signing' | ||
| } | ||
|
|
||
| group = 'org.apache.kafka' | ||
| // Default the checker plugin version to the root project's version (read directly from the | ||
| // repo-root gradle.properties because buildSrc is a separate Gradle build and does not | ||
| // inherit the root project's `version` property). release.py bumps gradle.properties via | ||
| // the `updateVersion` task, so the plugin artifacts ship under the same dotted version as | ||
| // the rest of Kafka. `-PkafkaPluginsVersion=...` overrides for one-off out-of-band publishes. | ||
| def rootGradleProps = new Properties() | ||
| def rootGradlePropsFile = file('../gradle.properties') | ||
| if (rootGradlePropsFile.exists()) { | ||
| rootGradlePropsFile.withInputStream { rootGradleProps.load(it) } | ||
| } | ||
| def projectVersion = rootGradleProps.getProperty('version') | ||
| version = project.findProperty('kafkaPluginsVersion') ?: (projectVersion ?: '1.0.0-SNAPSHOT') | ||
|
|
||
| repositories { | ||
| gradlePluginPortal() | ||
| mavenCentral() | ||
| } | ||
|
|
||
| java { | ||
| sourceCompatibility = JavaVersion.VERSION_11 | ||
| targetCompatibility = JavaVersion.VERSION_11 | ||
| // Maven Central requires sources and javadoc jars alongside the main artifact. | ||
| withSourcesJar() | ||
| withJavadocJar() | ||
| } | ||
|
|
||
| // Single source of truth for the Maven dependency versions. Both the dependency block below | ||
| // and the hand-maintained plugin.xml descriptor need to agree on these; processResources | ||
| // templates the descriptor at build time so they can never drift. | ||
| def mavenApiVersion = '3.9.4' | ||
| def mavenPluginAnnotationsVersion = '3.9.0' | ||
|
|
||
| dependencies { | ||
| // For bytecode scanning (used by the internal-API-usage checker) | ||
| implementation 'org.ow2.asm:asm:9.6' | ||
|
|
||
| // For Maven plugin functionality | ||
| implementation "org.apache.maven:maven-plugin-api:${mavenApiVersion}" | ||
| implementation "org.apache.maven:maven-core:${mavenApiVersion}" | ||
| implementation "org.apache.maven:maven-artifact:${mavenApiVersion}" | ||
| implementation "org.apache.maven.plugin-tools:maven-plugin-annotations:${mavenPluginAnnotationsVersion}" | ||
|
|
||
| // For testing | ||
| testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' | ||
| testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.2' | ||
| testImplementation 'org.junit.platform:junit-platform-launcher:1.9.2' | ||
| testImplementation 'org.mockito:mockito-core:5.3.1' | ||
| testImplementation gradleTestKit() | ||
| } | ||
|
|
||
| // Template plugin.xml from src/main/resources so its <version> and Maven dep versions are | ||
| // computed from the same source as the published artifact / dependency block above. Using | ||
| // Ant's @token@ delimiter rather than Groovy's `${...}` so Maven's runtime substitutions | ||
| // (e.g. ${project.build.directory}) inside plugin.xml are left untouched. | ||
| processResources { | ||
| filesMatching('META-INF/maven/plugin.xml') { | ||
| filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [ | ||
| version: project.version.toString(), | ||
| mavenApiVersion: mavenApiVersion, | ||
| mavenPluginAnnotationsVersion: mavenPluginAnnotationsVersion, | ||
| ]) | ||
| } | ||
| } | ||
|
|
||
| gradlePlugin { | ||
| plugins { | ||
| kafkaPublicApiChecker { | ||
| id = 'org.apache.kafka.public-api-checker' | ||
| implementationClass = 'org.apache.kafka.gradle.KafkaPublicApiCheckerPlugin' | ||
| displayName = 'Kafka Public API Checker' | ||
| description = 'Internal plugin for checking public API consistency in Kafka codebase' | ||
| } | ||
|
|
||
| kafkaInternalApiChecker { | ||
| id = 'org.apache.kafka.internal-api-checker' | ||
| implementationClass = 'org.apache.kafka.gradle.KafkaInternalApiCheckerPlugin' | ||
| displayName = 'Kafka Internal API Checker' | ||
| description = 'Plugin for external projects to check they don\'t use internal Kafka APIs' | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Configure publishing for both Gradle and Maven plugins | ||
| publishing { | ||
| // Mirrors the root project's publishing.repositories block so the buildSrc artifacts | ||
| // (kafka-internal-api-checker Gradle plugin + kafka-internal-api-checker-maven-plugin Maven | ||
| // plugin) land in the same ASF Nexus / staging repo as the rest of the release. Local | ||
| // smoke-tests can override with -PmavenUrl=file:///tmp/local-repo . | ||
| repositories { | ||
| maven { | ||
| url = project.hasProperty('mavenUrl') ? project.mavenUrl : '' | ||
| credentials { | ||
| username = project.hasProperty('mavenUsername') ? project.mavenUsername : '' | ||
| password = project.hasProperty('mavenPassword') ? project.mavenPassword : '' | ||
| } | ||
| } | ||
| } | ||
| publications { | ||
| // Maven plugin (separate from Gradle plugin publication) | ||
| mavenPlugin(MavenPublication) { | ||
| group = 'org.apache.kafka' | ||
| artifactId = 'kafka-internal-api-checker-maven-plugin' | ||
| version = project.version | ||
|
|
||
| from components.java | ||
|
|
||
| pom { | ||
| name = 'Apache Kafka Internal API Checker Maven Plugin' | ||
| description = 'Maven plugin to check that external projects don\'t use internal Kafka APIs' | ||
| url = 'https://kafka.apache.org' | ||
| packaging = 'maven-plugin' | ||
|
|
||
| licenses { | ||
| license { | ||
| name = 'The Apache License, Version 2.0' | ||
| url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' | ||
| } | ||
| } | ||
|
|
||
| developers { | ||
| developer { | ||
| id = 'apache-kafka' | ||
| name = 'Apache Kafka Team' | ||
| email = 'dev@kafka.apache.org' | ||
| } | ||
| } | ||
|
|
||
| scm { | ||
| connection = 'scm:git:https://github.com/apache/kafka.git' | ||
| developerConnection = 'scm:git:https://github.com/apache/kafka.git' | ||
| url = 'https://github.com/apache/kafka' | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // The `java-gradle-plugin` plugin auto-generates one Maven publication per declared | ||
| // plugin (the marker poms) plus a `pluginMaven` publication that holds the implementation | ||
| // jar both markers point to. Rename the implementation jar away from the buildSrc | ||
| // directory name so it has a sensible Maven coordinate. | ||
| afterEvaluate { | ||
| publications.matching { it.name == 'pluginMaven' }.configureEach { | ||
| artifactId = 'kafka-internal-api-checker-gradle-plugin' | ||
| } | ||
| publications.matching { it.name.endsWith('PluginMarkerMaven') }.configureEach { | ||
| pom { | ||
| name = 'Apache Kafka Gradle Plugins' | ||
| description = 'Gradle plugins for Apache Kafka public API validation' | ||
| url = 'https://kafka.apache.org' | ||
|
|
||
| licenses { | ||
| license { | ||
| name = 'The Apache License, Version 2.0' | ||
| url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' | ||
| } | ||
| } | ||
|
|
||
| developers { | ||
| developer { | ||
| id = 'apache-kafka' | ||
| name = 'Apache Kafka Team' | ||
| email = 'dev@kafka.apache.org' | ||
| } | ||
| } | ||
|
|
||
| scm { | ||
| connection = 'scm:git:https://github.com/apache/kafka.git' | ||
| developerConnection = 'scm:git:https://github.com/apache/kafka.git' | ||
| url = 'https://github.com/apache/kafka' | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Also configure the main plugin publication | ||
| publications.matching { it.name == 'pluginMaven' }.configureEach { | ||
| pom { | ||
| name = 'Apache Kafka Gradle Plugins' | ||
| description = 'Gradle plugins for Apache Kafka public API validation' | ||
| url = 'https://kafka.apache.org' | ||
|
|
||
| licenses { | ||
| license { | ||
| name = 'The Apache License, Version 2.0' | ||
| url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' | ||
| } | ||
| } | ||
|
|
||
| developers { | ||
| developer { | ||
| id = 'apache-kafka' | ||
| name = 'Apache Kafka Team' | ||
| email = 'dev@kafka.apache.org' | ||
| } | ||
| } | ||
|
|
||
| scm { | ||
| connection = 'scm:git:https://github.com/apache/kafka.git' | ||
| developerConnection = 'scm:git:https://github.com/apache/kafka.git' | ||
| url = 'https://github.com/apache/kafka' | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // GPG-sign the published artifacts on real releases (i.e. when the version is not a SNAPSHOT | ||
| // and -PskipSigning is not set), matching the policy in the root build.gradle. ASF Nexus | ||
| // rejects unsigned artifacts on the staging repo, so this is required for `release.py stage`. | ||
| def skipSigning = project.hasProperty('skipSigning') && skipSigning.toBoolean() | ||
| def shouldSign = !skipSigning && !version.toString().endsWith('SNAPSHOT') | ||
| if (shouldSign) { | ||
| signing { | ||
| sign publishing.publications | ||
| } | ||
| } | ||
|
|
||
| test { | ||
| useJUnitPlatform() | ||
| } | ||
|
|
||
| checkstyle { | ||
| toolVersion = '12.3.1' | ||
| configDirectory = file("$rootDir/../checkstyle") | ||
| configProperties = [importControlFile: 'import-control-buildsrc.xml'] | ||
| } | ||
|
|
||
| tasks.named('checkstyleMain').configure { | ||
| group = 'Verification' | ||
| description = 'Run checkstyle on all main Java sources' | ||
| } | ||
|
|
||
| tasks.named('checkstyleTest').configure { | ||
| group = 'Verification' | ||
| description = 'Run checkstyle on all test Java sources' | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use the id as
kafka-internal-api-checker-gradle-plugin'which will be similar tokafka-internal-api-checker-maven-plugin