Skip to content

Commit da19c35

Browse files
authored
feat(sdk): setup publishing to maven central repository (#18)
relates to STACKITSDK-207
1 parent 11cd42e commit da19c35

File tree

10 files changed

+171
-65
lines changed

10 files changed

+171
-65
lines changed

.github/workflows/ci.yaml

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: CI
1+
name: CI/CD
22

33
on:
44
pull_request:
@@ -7,7 +7,7 @@ on:
77
branches: ["main"]
88

99
jobs:
10-
main:
10+
ci:
1111
name: CI
1212
runs-on: ubuntu-latest
1313
strategy:
@@ -36,3 +36,25 @@ jobs:
3636
- name: Publish to local maven repo
3737
run: make install
3838

39+
cd:
40+
name: CD
41+
runs-on: ubuntu-latest
42+
if: ${{ github.ref_name == 'main' }}
43+
needs: [ci]
44+
steps:
45+
- name: Checkout
46+
uses: actions/checkout@v5
47+
with:
48+
fetch-depth: 0
49+
50+
- name: Create git tags and publish to Maven Central
51+
env:
52+
GPG_SIGNING_KEY: "${{ secrets.GPG_SIGNING_KEY }}"
53+
GPG_SIGNING_PASSWORD: "${{ secrets.GPG_SIGNING_PASSWORD }}"
54+
ORG_GRADLE_PROJECT_mavenCentralUsername: "${{ secrets.MAVEN_CENTRAL_USERNAME }}"
55+
ORG_GRADLE_PROJECT_mavenCentralPassword: "${{ secrets.MAVEN_CENTRAL_PASSWORD }}"
56+
run: |
57+
git config --global user.name "SDK Releaser Bot"
58+
git config --global user.email "[email protected]"
59+
./scripts/publish.sh
60+

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## Release (2025-MM-DD)
2+
- `core`: [v0.1.0](core/CHANGELOG.md#v010)
3+
- Initial onboarding of STACKIT Java SDK core lib
4+
- `iaas`: [v0.1.0](services/iaas/CHANGELOG.md#v010)
5+
- Initial onboarding of STACKIT Java SDK for IaaS service
6+
- `resourcemanger`: [v0.1.0](services/resourcemanager/CHANGELOG.md#v010)
7+
- Initial onboarding of STACKIT Java SDK for Resourcemanager service
8+

build.gradle

Lines changed: 96 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
plugins {
22
id 'java'
3-
id 'maven-publish'
3+
id 'signing'
44
id 'idea'
55
id 'eclipse'
66

77
id 'com.diffplug.spotless' version '6.21.0'
8-
}
98

9+
/* We have to use this 3rd party plugin for publishing to MavenCentral because as of AUG-2025 there is no official
10+
* plugin which supports publishing to MavenCentral Portal. */
11+
id "com.vanniktech.maven.publish.base" version "0.34.0"
12+
}
1013

1114
allprojects {
1215
apply plugin: 'com.diffplug.spotless'
@@ -63,86 +66,118 @@ allprojects {
6366
}
6467
}
6568

69+
def configureMavenCentralPublishing(Project project) {
70+
project.plugins.withId('com.vanniktech.maven.publish.base') {
71+
project.mavenPublishing {
72+
publishToMavenCentral(true) // publish automatically after upload to Maven Central
73+
}
74+
}
75+
}
76+
6677
subprojects {
6778
apply plugin: 'java'
68-
apply plugin: 'maven-publish'
6979
apply plugin: 'idea'
7080
apply plugin: 'eclipse'
7181

72-
group = 'cloud.stackit'
73-
74-
afterEvaluate { project ->
75-
// only apply to service sub-projects and core
76-
if (project.path.startsWith(':services:') || project.name == "core" ) {
77-
// override the version of each service with the ones obtained from the VERSION files
78-
def versionFile = project.file("VERSION")
79-
if (versionFile.exists()) {
80-
try {
81-
version = versionFile.text.trim()
82-
} catch (IOException e) {
83-
version = 'SNAPSHOT'
84-
logger.error("Could not read VERSION file for project '${project.path}': ${e.message}")
85-
}
86-
} else {
82+
group = 'cloud.stackit.sdk'
83+
84+
// only apply to service sub-projects and core
85+
if (project.path.startsWith(':services:') || project.name == "core" ) {
86+
apply plugin: 'signing'
87+
apply plugin: 'com.vanniktech.maven.publish.base'
88+
89+
// override the version of each service with the ones obtained from the VERSION files
90+
def versionFile = project.file("VERSION")
91+
if (versionFile.exists()) {
92+
try {
93+
version = versionFile.text.trim()
94+
} catch (IOException e) {
8795
version = 'SNAPSHOT'
88-
logger.warn("VERSION file not found in project '${project.path}'. Skipping version setting.")
96+
logger.error("Could not read VERSION file for project '${project.path}': ${e.message}")
8997
}
98+
} else {
99+
version = 'SNAPSHOT'
100+
logger.warn("VERSION file not found in project '${project.path}'. Skipping version setting.")
101+
}
90102

103+
java {
104+
withSourcesJar()
105+
withJavadocJar()
106+
}
91107

92-
publishing {
93-
publications {
94-
maven(MavenPublication) {
95-
artifactId = "stackit-sdk-${project.name}"
96-
from components.java
97-
98-
pom {
99-
name.set(project.name)
100-
description.set("STACKIT Java SDK for the ${project.name} service")
101-
url.set("https://github.com/stackitcloud/stackit-sdk-java/tree/main/services/${rootProject.name}")
102-
licenses {
103-
license {
104-
name.set("Apache License, Version 2.0")
105-
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
106-
}
107-
}
108-
developers {
109-
developer {
110-
id.set("stackitcloud") // TODO: not clear which value must be placed here, check this when setting up publishment to Maven Central
111-
name.set("STACKIT Developer Tools")
112-
email.set("[email protected]")
113-
}
108+
// don't fail on missing javadoc strings
109+
tasks.withType(Javadoc).configureEach {
110+
options.addStringOption('Xdoclint:none', '-quiet')
111+
}
112+
113+
publishing {
114+
publications {
115+
mavenJava(MavenPublication) {
116+
artifactId = "${project.name}"
117+
from components.java
118+
119+
pom {
120+
name.set(project.name)
121+
description.set("STACKIT Java SDK for the ${project.name} service")
122+
url.set("https://github.com/stackitcloud/${rootProject.name}/tree/main/services/${project.name}")
123+
licenses {
124+
license {
125+
name.set("Apache License, Version 2.0")
126+
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
114127
}
115-
scm {
116-
connection.set("scm:git:git://github.com/stackitcloud/${rootProject.name}.git")
117-
developerConnection.set("scm:git:ssh://github.com/stackitcloud/${rootProject.name}.git")
118-
url.set("https://github.com/stackitcloud/${rootProject.name}")
128+
}
129+
developers {
130+
developer {
131+
id.set("stackitcloud")
132+
name.set("STACKIT Developer Tools")
133+
email.set("[email protected]")
119134
}
120135
}
136+
scm {
137+
connection.set("scm:git:git://github.com/stackitcloud/${rootProject.name}.git")
138+
developerConnection.set("scm:git:ssh://github.com/stackitcloud/${rootProject.name}.git")
139+
url.set("https://github.com/stackitcloud/${rootProject.name}")
140+
}
121141
}
122142
}
123-
repositories {
124-
mavenLocal()
125-
}
143+
}
144+
145+
repositories {
146+
mavenLocal()
126147
}
127148
}
128149

129-
// only apply to example sub-projects
130-
if (project.path.startsWith(':examples:')) {
131-
if (!project.hasProperty('mainClassName')) {
132-
logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.")
150+
signing {
151+
required {
152+
// signing is only required if the artifacts are to be published to Maven Central
153+
gradle.taskGraph.hasTask(":services:${project.name}:publishToMavenCentral") || gradle.taskGraph.hasTask(":${project.name}:publishToMavenCentral")
133154
}
134155

135-
tasks.register('execute', JavaExec) {
136-
if (!project.hasProperty('mainClassName')) {
137-
doLast {
138-
logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.")
139-
}
140-
enabled = false // Disable the task if no main class is specified
141-
return
156+
def signingKey = System.getenv("GPG_SIGNING_KEY") ?: findProperty("signingKey")
157+
def signingPassword = System.getenv("GPG_SIGNING_PASSWORD") ?: findProperty("signingPassword")
158+
useInMemoryPgpKeys(signingKey as String, signingPassword as String)
159+
sign publishing.publications.mavenJava
160+
}
161+
162+
configureMavenCentralPublishing(project)
163+
}
164+
165+
// only apply to example sub-projects
166+
if (project.path.startsWith(':examples:')) {
167+
if (!project.hasProperty('mainClassName')) {
168+
logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.")
169+
}
170+
171+
tasks.register('execute', JavaExec) {
172+
if (!project.hasProperty('mainClassName')) {
173+
doLast {
174+
logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.")
142175
}
143-
mainClass = project.mainClassName
144-
classpath = sourceSets.main.runtimeClasspath
176+
enabled = false // Disable the task if no main class is specified
177+
return
145178
}
179+
mainClass = project.mainClassName
180+
classpath = sourceSets.main.runtimeClasspath
146181
}
147182
}
148183

core/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## v0.1.0
2+
- Initial onboarding of STACKIT Java SDK core lib

core/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.1-SNAPSHOT
1+
0.1.0

scripts/publish.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env bash
2+
3+
# This script creates the git tags and publishes the artifacts to Maven Central
4+
5+
# Immediate exit on failure
6+
set -e
7+
8+
# VERSION contains only one single line which contains the version of the service
9+
# in the following format e.g. 0.3.0
10+
11+
# iterate over all services and core by their VERSION files
12+
for file in $(find . -print | sed 's|^./||' | grep -E "(^services/[^/]+/VERSION$|^core/VERSION$)"); do
13+
14+
# Extract the current version and build the expected tag
15+
dirpath=$(dirname "$file")
16+
version_path="$dirpath/VERSION"
17+
gradle_subproject="${dirpath//\//:}" # replace "/" with ":"
18+
version=$(<"$version_path")
19+
expected_tag="$dirpath/v$version"
20+
21+
printf "\n============================================================================================\n\n"
22+
23+
# Check if the tag already exists
24+
if git rev-parse --verify "$expected_tag" &> /dev/null; then
25+
echo "Tag '$expected_tag' already exists. Skipping tag creation and gradle publish..."
26+
else
27+
# Tag doesn't exist. Create a tag and push it.
28+
echo "Tag '$expected_tag' does not exist."
29+
git tag -a $expected_tag -m "Release $version"
30+
git push origin tag $expected_tag
31+
32+
./gradlew "${gradle_subproject}:publishToMavenCentral"
33+
fi
34+
done

services/iaas/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## v0.1.0
2+
- Initial onboarding of STACKIT Java SDK for IaaS service

services/iaas/VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.1.0
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## v0.1.0
2+
- Initial onboarding of STACKIT Java SDK for Resourcemanager service

services/resourcemanager/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.1-SNAPSHOT
1+
0.1.0

0 commit comments

Comments
 (0)