This is an automated email from the ASF dual-hosted git repository.
chia7712 pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git
The following commit(s) were added to refs/heads/trunk by this push:
new 62206cfc546 KAFKA-20085 Replace verbose version instructions with
updateVersion task (#21340)
62206cfc546 is described below
commit 62206cfc5461629818a34723fee7817b369a6f7e
Author: Parker Chang <[email protected]>
AuthorDate: Thu Jan 29 01:48:58 2026 +0800
KAFKA-20085 Replace verbose version instructions with updateVersion task
(#21340)
## Description
Replaces verbose manual version instructions with a new Gradle task
`updateVersion` and introduces a verification task
`verifyVersionConsistency` to enforce version consistency.
**Features**
1. **Automated Verification (`check` lifecycle):**
The `verifyVersionConsistency` task is hooked into `./gradlew check`.
If `gradle.properties` is updated but dependent files are not, the build
will **fail** with a descriptive error prompting the user to run
`updateVersion`.
2. **Automated Update (`updateVersion` task):**
* **Sync Mode:** `./gradlew updateVersion`
(Syncs the current version from `gradle.properties` to all dependent
files)
* **Update Mode:** `./gradlew updateVersion -PnewVersion=4.3.0-SNAPSHOT`
(Updates `gradle.properties` first, then syncs to all dependent files)
**Affected Files**
* `gradle.properties` (only if `-PnewVersion` is used)
* `committer-tools/kafka-merge-pr.py`
* `tests/kafkatest/version.py`
* `tests/kafkatest/__init__.py`
* `streams/quickstart/pom.xml`
* `streams/quickstart/java/pom.xml`
*
`streams/quickstart/java/src/main/resources/archetype-resources/pom.xml`
## Verification
### Scenario 1: Verification Guardrail (The "Linting" flow)
*Simulating a Release Manager manually updating `gradle.properties` but
forgetting others.*
1. Manually modify `gradle.properties` to a new version.
2. Run `./gradlew check` (or just the verification task).
**Result: Build Fails (Expected)**
```text
> Task :verifyVersionConsistency FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':verifyVersionConsistency'.
> Found inconsistent versions in the following files:
committer-tools/kafka-merge-pr.py
tests/kafkatest/version.py
...
Please run './gradlew updateVersion -PnewVersion=...' to fix them.
```
### Scenario 2: Happy Path (Update Task)
1. Run `./gradlew updateVersion -PnewVersion="4.2.0-SNAPSHOT"`
```text
> Task :updateVersion
Updated gradle.properties to version 4.2.0-SNAPSHOT
Updated committer-tools/kafka-merge-pr.py
Updated tests/kafkatest/version.py
Updated tests/kafkatest/__init__.py
Updated streams/quickstart/pom.xml
Updated streams/quickstart/java/pom.xml
Updated
streams/quickstart/java/src/main/resources/archetype-resources/pom.xml
BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
```
2. Run `./gradlew check` again.
**Result: Build Passes**
```text
> Task :verifyVersionConsistency
All versions are consistent with gradle.properties.
BUILD SUCCESSFUL
```
### Scenario 3: Error Handling
1. `./gradlew updateVersion -PnewVersion="invalid-version"`
```text
> Task :updateVersion FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':updateVersion'.
> Invalid version format: 'invalid-version'. Expected format: X.Y.Z or
X.Y.Z-SNAPSHOT
```
Reviewers: PoAn Yang <[email protected]>, Chia-Ping Tsai
<[email protected]>
---
build.gradle | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
gradle.properties | 8 ---
2 files changed, 143 insertions(+), 8 deletions(-)
diff --git a/build.gradle b/build.gradle
index 0306e203d94..73bf31153a7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3989,3 +3989,146 @@ task aggregatedJavadoc(type: Javadoc, dependsOn:
compileJava) {
includes = projectsWithJavadoc.collectMany { it.javadoc.getIncludes() }
excludes = projectsWithJavadoc.collectMany { it.javadoc.getExcludes() }
}
+
+
+
+// Helper to get version targets and expected patterns
+ext.getVersionTargets = { rawVersion ->
+ // Python Package Version (PEP 440): 4.3.0.dev0
+ def pythonVersion = rawVersion.contains("SNAPSHOT") ?
+ rawVersion.replace("-SNAPSHOT", ".dev0") :
+ rawVersion
+
+ def baseVersion = rawVersion.replace("-SNAPSHOT", "")
+
+ return [
+ // 1. kafka-merge-pr.py
+ [
+ path: "committer-tools/kafka-merge-pr.py",
+ // Regex: match DEFAULT_FIX_VERSION =
os.environ.get("DEFAULT_FIX_VERSION", "...")
+ pattern:
/DEFAULT_FIX_VERSION\s*=\s*os\.environ\.get\("DEFAULT_FIX_VERSION",\s*".*?"\)/,
+ replace: "DEFAULT_FIX_VERSION =
os.environ.get(\"DEFAULT_FIX_VERSION\", \"${baseVersion}\")"
+ ],
+ // 2. version.py
+ [
+ path: "tests/kafkatest/version.py",
+ pattern: /DEV_VERSION\s*=\s*KafkaVersion\(".*"\)/,
+ replace: "DEV_VERSION = KafkaVersion(\"${rawVersion}\")"
+ ],
+ // 3. __init__.py
+ [
+ path: "tests/kafkatest/__init__.py",
+ pattern: /__version__\s*=\s*'.*'/,
+ replace: "__version__ = '${pythonVersion}'"
+ ],
+ // 4. Maven POMs
+ [
+ path: "streams/quickstart/pom.xml",
+ pattern:
/(?s)(<artifactId>streams-quickstart<\/artifactId>.*?<version>)([^<]+)(<\/version>)/,
+ replace: { "\$1${rawVersion}\$3" }
+ ],
+ [
+ path: "streams/quickstart/java/pom.xml",
+ pattern:
/(?s)(<artifactId>streams-quickstart<\/artifactId>.*?<version>)([^<]+)(<\/version>)/,
+ replace: { "\$1${rawVersion}\$3" }
+ ],
+ [
+ path:
"streams/quickstart/java/src/main/resources/archetype-resources/pom.xml",
+ pattern: /(<kafka\.version>)([^<]+)(<\/kafka\.version>)/,
+ replace: { "\$1${rawVersion}\$3" }
+ ]
+ ]
+}
+
+def updateVersionTask = tasks.register('updateVersion') {
+ group = "Release"
+ description = "Syncs python, pom, and script versions with
gradle.properties. Fails if files or patterns are missing. Use
-PnewVersion=X.Y.Z to set a new version."
+
+ doLast {
+ def rawVersion
+ if (project.hasProperty('newVersion')) {
+ rawVersion = newVersion
+ if (!rawVersion.matches(/^[0-9]+\.[0-9]+\.[0-9]+(-SNAPSHOT)?$/)) {
+ throw new GradleException("Invalid version format: '${rawVersion}'.
Expected format: X.Y.Z or X.Y.Z-SNAPSHOT")
+ }
+ // Update gradle.properties
+ def gradlePropsFile = file("${project.rootDir}/gradle.properties")
+ if (gradlePropsFile.exists()) {
+ def propsContent = gradlePropsFile.text
+ def newPropsContent = propsContent.replaceAll(/(?m)^version\s*=.*/,
"version=${rawVersion}")
+ if (propsContent != newPropsContent) {
+ gradlePropsFile.text = newPropsContent
+ println "Updated gradle.properties to version ${rawVersion}"
+ }
+ }
+ } else {
+ rawVersion = project.version.toString()
+ }
+
+ def targets = getVersionTargets(rawVersion)
+
+ targets.each { item ->
+ def f = file("${project.rootDir}/${item.path}")
+
+ // Check 1: file must exist
+ if (!f.exists()) {
+ throw new GradleException("File not found: ${item.path}")
+ }
+
+ def content = f.text
+ // Check 2: regex must match
+ def matcher = (content =~ item.pattern)
+ if (!matcher.find()) {
+ throw new GradleException("Pattern not found in
${item.path}.\nExpected pattern: ${item.pattern}")
+ }
+
+ def replacementStr = item.replace instanceof Closure ?
item.replace.call() : item.replace
+
+ def newContent = content.replaceAll(item.pattern, replacementStr)
+
+ if (content != newContent) {
+ f.text = newContent
+ println "Updated ${item.path}"
+ }
+ }
+ }
+}
+
+def verifyVersionConsistencyTask = tasks.register('verifyVersionConsistency') {
+ group = "Verification"
+ description = "Verifies that python, pom, and script versions match
gradle.properties."
+
+ doLast {
+ def rawVersion = project.version.toString()
+ def targets = getVersionTargets(rawVersion)
+ def inconsistentFiles = []
+
+ targets.each { item ->
+ def f = file("${project.rootDir}/${item.path}")
+ if (!f.exists()) {
+ throw new GradleException("File not found: ${item.path}")
+ }
+
+ def content = f.text
+ // Check if regex matches current content "as is"
+ // Note: We need to see if the file content *already* matches what we
want it to be.
+ // One way is to simulate the replacement and see if it changes nothing.
+
+ def replacementStr = item.replace instanceof Closure ?
item.replace.call() : item.replace
+ def newContent = content.replaceAll(item.pattern, replacementStr)
+
+ if (content != newContent) {
+ inconsistentFiles.add(item.path)
+ }
+ }
+
+ if (!inconsistentFiles.isEmpty()) {
+ throw new GradleException("Found inconsistent versions in the following
files:\n" +
+ inconsistentFiles.join("\n") +
+ "\n\nPlease run './gradlew updateVersion -PnewVersion=...' to fix
them.")
+ }
+ println "All versions are consistent."
+ }
+}
+
+check.dependsOn verifyVersionConsistencyTask
diff --git a/gradle.properties b/gradle.properties
index c30e1bd2f52..72afec1a567 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -14,14 +14,6 @@
# limitations under the License.
group=org.apache.kafka
-# NOTE: When you change this version number, you should also make sure to
update
-# the version numbers in
-# - tests/kafkatest/__init__.py
-# - tests/kafkatest/version.py (variable DEV_VERSION)
-# - kafka-merge-pr.py
-# - streams/quickstart/pom.xml
-# - streams/quickstart/java/src/main/resources/archetype-resources/pom.xml
-# - streams/quickstart/java/pom.xml
version=4.3.0-SNAPSHOT
scalaVersion=2.13.18
# Adding swaggerVersion in gradle.properties to have a single version in place
for swagger