This is an automated email from the ASF dual-hosted git repository.

uranusjr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new aeedb91536f Add Java SDK publish configuration (#68016)
aeedb91536f is described below

commit aeedb91536fe0f58612c87719ac758c0a04a9231
Author: Tzu-ping Chung <[email protected]>
AuthorDate: Fri Jun 5 12:10:37 2026 +0800

    Add Java SDK publish configuration (#68016)
---
 java-sdk/README.md            | 92 +++++++++++++++++++++++++++++++++++++++++++
 java-sdk/sdk/build.gradle.kts | 88 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 179 insertions(+), 1 deletion(-)

diff --git a/java-sdk/README.md b/java-sdk/README.md
index 61e818db526..e44f40dbefc 100644
--- a/java-sdk/README.md
+++ b/java-sdk/README.md
@@ -81,6 +81,98 @@ This generates both an HTML representation and Javadoc.
   export AIRFLOW_VAR_MY_VARIABLE=123
   ```
 
+## Publishing
+
+The SDK is published to Maven Central via the
+[ASF Nexus staging repository](https://repository.apache.org).
+The full release process follows the
+[ASF Maven publishing 
guide](https://infra.apache.org/publishing-maven-artifacts.html).
+
+### Prerequisites
+
+* An ASF committer account with access to
+  [repository.apache.org](https://repository.apache.org).
+* A GPG key that has been
+  [added to the project KEYS 
file](https://infra.apache.org/release-signing.html)
+  and uploaded to a public key server.
+
+### Bump the version
+
+Edit `gradle.properties` and set the version for this release:
+
+```properties
+sdkVersion=1.0.0
+```
+
+Commit the change and push it to the release branch.
+
+### Verify the POM locally
+
+Before touching any remote repository, publish to your local Maven cache and
+inspect the generated POM:
+
+```bash
+./gradlew :sdk:publishToMavenLocal
+cat ~/.m2/repository/org/apache/airflow/airflow-sdk/*/airflow-sdk-*.pom
+```
+
+Check that the coordinates, description, license, SCM, and organization fields
+look correct.
+
+### Export your signing key
+
+The build expects an ASCII-armored PGP private key.  Export it with:
+
+```bash
+gpg --armor --export-secret-keys <your-key-id>
+```
+
+Copy the full output (including the header and footer) for use in the next 
step.
+
+### Publish to ASF Nexus staging
+
+Store the four credentials in `~/.gradle/gradle.properties` so they are not
+exposed in your shell history:
+
+```properties
+mavenUsername=<your-asf-id>
+mavenPassword=<your-asf-nexus-token>
+signing.key=<ascii-armored-pgp-key>
+signing.password=<key-passphrase>
+```
+
+Then run the publish task:
+
+```bash
+./gradlew :sdk:publish
+```
+
+Alternatively, pass them on the command line (note the single quotes around
+properties whose values contain newlines or special characters):
+
+```bash
+./gradlew :sdk:publish \
+  -PmavenUsername=<your-asf-id> \
+  -PmavenPassword=<your-asf-nexus-token> \
+  -P'signing.key=<ascii-armored-pgp-key>' \
+  -P'signing.password=<key-passphrase>'
+```
+
+### Release
+
+The process from now on should be the same as releasing other Airflow 
components.
+
+### Dry-run against a local repository
+
+To test the full publish flow without touching ASF infrastructure, override the
+repository URL to a local directory (no signing key required since nothing goes
+to Maven Central):
+
+```bash
+./gradlew :sdk:publish -PmavenUrl=file:///tmp/local-maven-repo
+ls /tmp/local-maven-repo/org/apache/airflow/airflow-sdk/
+```
+
 ## Technical Details
 
 The user uses the SDK to implement a Java application that implements task
diff --git a/java-sdk/sdk/build.gradle.kts b/java-sdk/sdk/build.gradle.kts
index a5acd27f9c1..f7917db6d99 100644
--- a/java-sdk/sdk/build.gradle.kts
+++ b/java-sdk/sdk/build.gradle.kts
@@ -24,14 +24,19 @@ buildscript {
 }
 
 val airflowSupervisorSchemaVersion: String by project
+
+val sdkArtifact = "airflow-sdk"
 val sdkVersion: String by project
 
 // Full Maven coordinate: org.apache.airflow:airflow-sdk:<version>
+// artifactId is set explicitly on the MavenPublication below.
 group = "org.apache.airflow"
 version = sdkVersion
-base.archivesName.set("airflow-sdk")
 
 plugins {
+    `java-library`
+    `maven-publish`
+    signing
     kotlin("plugin.serialization") version "2.3.0"
     id("org.jetbrains.dokka") version "2.2.0"
     id("org.jetbrains.dokka-javadoc") version "2.2.0"
@@ -172,6 +177,13 @@ tasks.register<GeneratePointersTask>("generatePointers") {
     targetDirectory = pointersDir
 }
 
+val javadocJar by tasks.registering(Jar::class) {
+    description = "Assembles Javadoc JAR from Dokka output"
+    group = JavaBasePlugin.DOCUMENTATION_GROUP
+    archiveClassifier.set("javadoc")
+    from(tasks.named("dokkaGeneratePublicationJavadoc"))
+}
+
 jsonSchema2Pojo {
     setSource(listOf(pointersDir.get().asFile))
     targetPackage = jsonSchemaPackage
@@ -211,6 +223,11 @@ dokka {
     }
 }
 
+java {
+    withSourcesJar() // Required by Maven Central.
+    // Do NOT call withJavadocJar(); we use Dokka to generate documentation. 
See javadocJar above.
+}
+
 tasks.named("generateJsonSchema2Pojo") {
     dependsOn("generatePointers")
 }
@@ -232,6 +249,7 @@ tasks.matching { it.name.startsWith("dokkaGenerate") 
}.configureEach {
 }
 
 tasks.withType<Jar> {
+    dependsOn("generateJsonSchema2Pojo", "generateDiscriminator")
     manifest {
         attributes(
             "Airflow-Supervisor-Schema-Version" to 
airflowSupervisorSchemaVersion,
@@ -242,3 +260,71 @@ tasks.withType<Jar> {
 tasks.withType<Test> {
     useJUnitPlatform()
 }
+
+private fun getProperty(name: String) = providers.gradleProperty(name).orNull
+
+private fun getProperty(
+    name: String,
+    env: String,
+): String? = getProperty(name) ?: System.getenv(env)
+
+publishing {
+    publications {
+        create<MavenPublication>("mavenJava") {
+            artifactId = sdkArtifact
+            from(components["java"])
+            artifact(javadocJar)
+            pom {
+                name = "Apache Airflow Java SDK"
+                description = "Java SDK for implementing Apache Airflow task 
logic on the JVM."
+                url = "https://airflow.apache.org";
+
+                organization {
+                    name = "The Apache Software Foundation"
+                    url = "https://www.apache.org/";
+                }
+                licenses {
+                    license {
+                        name = "The Apache License, Version 2.0"
+                        url = "https://www.apache.org/licenses/LICENSE-2.0.txt";
+                        distribution = "repo"
+                    }
+                }
+                scm {
+                    connection = 
"scm:git:https://gitbox.apache.org/repos/asf/airflow.git";
+                    developerConnection = 
"scm:git:https://gitbox.apache.org/repos/asf/airflow.git";
+                    url = "https://github.com/apache/airflow";
+                }
+            }
+        }
+    }
+
+    repositories {
+        maven {
+            name = "mavenRepo"
+            url =
+                uri(
+                    getProperty("mavenUrl")
+                        ?: if (sdkVersion.endsWith("-SNAPSHOT")) {
+                            
"https://repository.apache.org/content/repositories/snapshots/";
+                        } else {
+                            
"https://repository.apache.org/service/local/staging/deploy/maven2/";
+                        },
+                )
+            getProperty("mavenUsername", "ASF_NEXUS_USERNAME").let { user ->
+                credentials {
+                    username = user
+                    password = getProperty("mavenPassword", 
"ASF_NEXUS_PASSWORD")
+                }
+            }
+        }
+    }
+}
+
+signing {
+    getProperty("signing.key", "SIGNING_KEY").let { secretKey ->
+        val password = getProperty("signing.password", "SIGNING_PASSWORD")
+        useInMemoryPgpKeys(secretKey, password)
+        sign(publishing.publications["mavenJava"])
+    }
+}

Reply via email to