diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 585deb9..fea84a8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,4 +1,4 @@ -name: CI +name: CI/CD on: pull_request: @@ -7,7 +7,7 @@ on: branches: ["main"] jobs: - main: + ci: name: CI runs-on: ubuntu-latest strategy: @@ -36,3 +36,25 @@ jobs: - name: Publish to local maven repo run: make install + cd: + name: CD + runs-on: ubuntu-latest + if: ${{ github.ref_name == 'main' }} + needs: [ci] + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Create git tags and publish to Maven Central + env: + GPG_SIGNING_KEY: "${{ secrets.GPG_SIGNING_KEY }}" + GPG_SIGNING_PASSWORD: "${{ secrets.GPG_SIGNING_PASSWORD }}" + ORG_GRADLE_PROJECT_mavenCentralUsername: "${{ secrets.MAVEN_CENTRAL_USERNAME }}" + ORG_GRADLE_PROJECT_mavenCentralPassword: "${{ secrets.MAVEN_CENTRAL_PASSWORD }}" + run: | + git config --global user.name "SDK Releaser Bot" + git config --global user.email "noreply@stackit.de" + ./scripts/publish.sh + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c18cded --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +## Release (2025-MM-DD) +- `core`: [v0.1.0](core/CHANGELOG.md#v010) + - Initial onboarding of STACKIT Java SDK core lib +- `iaas`: [v0.1.0](services/iaas/CHANGELOG.md#v010) + - Initial onboarding of STACKIT Java SDK for IaaS service +- `resourcemanger`: [v0.1.0](services/resourcemanager/CHANGELOG.md#v010) + - Initial onboarding of STACKIT Java SDK for Resourcemanager service + diff --git a/build.gradle b/build.gradle index bef7e1c..f4d6b3f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,15 @@ plugins { id 'java' - id 'maven-publish' + id 'signing' id 'idea' id 'eclipse' id 'com.diffplug.spotless' version '6.21.0' -} + /* We have to use this 3rd party plugin for publishing to MavenCentral because as of AUG-2025 there is no official + * plugin which supports publishing to MavenCentral Portal. */ + id "com.vanniktech.maven.publish.base" version "0.34.0" +} allprojects { apply plugin: 'com.diffplug.spotless' @@ -63,86 +66,118 @@ allprojects { } } +def configureMavenCentralPublishing(Project project) { + project.plugins.withId('com.vanniktech.maven.publish.base') { + project.mavenPublishing { + publishToMavenCentral(true) // publish automatically after upload to Maven Central + } + } +} + subprojects { apply plugin: 'java' - apply plugin: 'maven-publish' apply plugin: 'idea' apply plugin: 'eclipse' - group = 'cloud.stackit' - - afterEvaluate { project -> - // only apply to service sub-projects and core - if (project.path.startsWith(':services:') || project.name == "core" ) { - // override the version of each service with the ones obtained from the VERSION files - def versionFile = project.file("VERSION") - if (versionFile.exists()) { - try { - version = versionFile.text.trim() - } catch (IOException e) { - version = 'SNAPSHOT' - logger.error("Could not read VERSION file for project '${project.path}': ${e.message}") - } - } else { + group = 'cloud.stackit.sdk' + + // only apply to service sub-projects and core + if (project.path.startsWith(':services:') || project.name == "core" ) { + apply plugin: 'signing' + apply plugin: 'com.vanniktech.maven.publish.base' + + // override the version of each service with the ones obtained from the VERSION files + def versionFile = project.file("VERSION") + if (versionFile.exists()) { + try { + version = versionFile.text.trim() + } catch (IOException e) { version = 'SNAPSHOT' - logger.warn("VERSION file not found in project '${project.path}'. Skipping version setting.") + logger.error("Could not read VERSION file for project '${project.path}': ${e.message}") } + } else { + version = 'SNAPSHOT' + logger.warn("VERSION file not found in project '${project.path}'. Skipping version setting.") + } + java { + withSourcesJar() + withJavadocJar() + } - publishing { - publications { - maven(MavenPublication) { - artifactId = "stackit-sdk-${project.name}" - from components.java - - pom { - name.set(project.name) - description.set("STACKIT Java SDK for the ${project.name} service") - url.set("https://github.com/stackitcloud/stackit-sdk-java/tree/main/services/${rootProject.name}") - licenses { - license { - name.set("Apache License, Version 2.0") - url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") - } - } - developers { - developer { - id.set("stackitcloud") // TODO: not clear which value must be placed here, check this when setting up publishment to Maven Central - name.set("STACKIT Developer Tools") - email.set("developer-tools@stackit.cloud") - } + // don't fail on missing javadoc strings + tasks.withType(Javadoc).configureEach { + options.addStringOption('Xdoclint:none', '-quiet') + } + + publishing { + publications { + mavenJava(MavenPublication) { + artifactId = "${project.name}" + from components.java + + pom { + name.set(project.name) + description.set("STACKIT Java SDK for the ${project.name} service") + url.set("https://github.com/stackitcloud/${rootProject.name}/tree/main/services/${project.name}") + licenses { + license { + name.set("Apache License, Version 2.0") + url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") } - scm { - connection.set("scm:git:git://github.com/stackitcloud/${rootProject.name}.git") - developerConnection.set("scm:git:ssh://github.com/stackitcloud/${rootProject.name}.git") - url.set("https://github.com/stackitcloud/${rootProject.name}") + } + developers { + developer { + id.set("stackitcloud") + name.set("STACKIT Developer Tools") + email.set("developer-tools@stackit.cloud") } } + scm { + connection.set("scm:git:git://github.com/stackitcloud/${rootProject.name}.git") + developerConnection.set("scm:git:ssh://github.com/stackitcloud/${rootProject.name}.git") + url.set("https://github.com/stackitcloud/${rootProject.name}") + } } } - repositories { - mavenLocal() - } + } + + repositories { + mavenLocal() } } - // only apply to example sub-projects - if (project.path.startsWith(':examples:')) { - if (!project.hasProperty('mainClassName')) { - logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.") + signing { + required { + // signing is only required if the artifacts are to be published to Maven Central + gradle.taskGraph.hasTask(":services:${project.name}:publishToMavenCentral") || gradle.taskGraph.hasTask(":${project.name}:publishToMavenCentral") } - tasks.register('execute', JavaExec) { - if (!project.hasProperty('mainClassName')) { - doLast { - logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.") - } - enabled = false // Disable the task if no main class is specified - return + def signingKey = System.getenv("GPG_SIGNING_KEY") ?: findProperty("signingKey") + def signingPassword = System.getenv("GPG_SIGNING_PASSWORD") ?: findProperty("signingPassword") + useInMemoryPgpKeys(signingKey as String, signingPassword as String) + sign publishing.publications.mavenJava + } + + configureMavenCentralPublishing(project) + } + + // only apply to example sub-projects + if (project.path.startsWith(':examples:')) { + if (!project.hasProperty('mainClassName')) { + logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.") + } + + tasks.register('execute', JavaExec) { + if (!project.hasProperty('mainClassName')) { + doLast { + logger.warn("'mainClassName' property not defined for subproject '${project.path}'. Skipping execution of this task.") } - mainClass = project.mainClassName - classpath = sourceSets.main.runtimeClasspath + enabled = false // Disable the task if no main class is specified + return } + mainClass = project.mainClassName + classpath = sourceSets.main.runtimeClasspath } } diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md new file mode 100644 index 0000000..5b294a0 --- /dev/null +++ b/core/CHANGELOG.md @@ -0,0 +1,2 @@ +## v0.1.0 +- Initial onboarding of STACKIT Java SDK core lib diff --git a/core/VERSION b/core/VERSION index cfefe08..6e8bf73 100644 --- a/core/VERSION +++ b/core/VERSION @@ -1 +1 @@ -0.0.1-SNAPSHOT +0.1.0 diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100755 index 0000000..45dd918 --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# This script creates the git tags and publishes the artifacts to Maven Central + +# Immediate exit on failure +set -e + +# VERSION contains only one single line which contains the version of the service +# in the following format e.g. 0.3.0 + +# iterate over all services and core by their VERSION files +for file in $(find . -print | sed 's|^./||' | grep -E "(^services/[^/]+/VERSION$|^core/VERSION$)"); do + + # Extract the current version and build the expected tag + dirpath=$(dirname "$file") + version_path="$dirpath/VERSION" + gradle_subproject="${dirpath//\//:}" # replace "/" with ":" + version=$(<"$version_path") + expected_tag="$dirpath/v$version" + + printf "\n============================================================================================\n\n" + + # Check if the tag already exists + if git rev-parse --verify "$expected_tag" &> /dev/null; then + echo "Tag '$expected_tag' already exists. Skipping tag creation and gradle publish..." + else + # Tag doesn't exist. Create a tag and push it. + echo "Tag '$expected_tag' does not exist." + git tag -a $expected_tag -m "Release $version" + git push origin tag $expected_tag + + ./gradlew "${gradle_subproject}:publishToMavenCentral" + fi +done diff --git a/services/iaas/CHANGELOG.md b/services/iaas/CHANGELOG.md new file mode 100644 index 0000000..4892bff --- /dev/null +++ b/services/iaas/CHANGELOG.md @@ -0,0 +1,2 @@ +## v0.1.0 +- Initial onboarding of STACKIT Java SDK for IaaS service diff --git a/services/iaas/VERSION b/services/iaas/VERSION new file mode 100644 index 0000000..6e8bf73 --- /dev/null +++ b/services/iaas/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/services/resourcemanager/CHANGELOG.md b/services/resourcemanager/CHANGELOG.md new file mode 100644 index 0000000..e43ed7a --- /dev/null +++ b/services/resourcemanager/CHANGELOG.md @@ -0,0 +1,2 @@ +## v0.1.0 +- Initial onboarding of STACKIT Java SDK for Resourcemanager service diff --git a/services/resourcemanager/VERSION b/services/resourcemanager/VERSION index cfefe08..6e8bf73 100644 --- a/services/resourcemanager/VERSION +++ b/services/resourcemanager/VERSION @@ -1 +1 @@ -0.0.1-SNAPSHOT +0.1.0