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"])
+ }
+}