diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..a4dce4c --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,4 @@ +template: | + ## What's Changed + + $CHANGES diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9272c0..d417a9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: branches: [ main ] push: branches: [ main ] + tags: [ v* ] permissions: contents: write # auto-merge requirement @@ -43,6 +44,14 @@ jobs: name: test-results-java-${{ matrix.java }} path: '**/build/test-results/test/TEST-*.xml' + - name: Prepare release notes + if: github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/') + uses: release-drafter/release-drafter@v7 + with: + config-name: release-drafter.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + spring-compat: name: "Spring Boot ${{ matrix.spring-boot }}" runs-on: ubuntu-24.04 @@ -86,6 +95,48 @@ jobs: - name: Test okapi-kafka run: ./gradlew :okapi-kafka:test -PkafkaVersion=${{ matrix.kafka }} + publish: + name: Publish to Maven Central + needs: [build, spring-compat, kafka-compat] + runs-on: ubuntu-24.04 + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v')) + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: 21 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@39e147cb9de83bb9910b8ef8bd7fff0ee20fcd6f # v6.0.1 + + - name: Publish to Maven Central + run: ./gradlew publishAndReleaseToMavenCentral + env: + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.PGP_SECRET }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.PGP_PASSPHRASE }} + + - name: Extract version from tag + run: | + version=${GITHUB_REF/refs\/tags\/v/} + echo "VERSION=$version" >> $GITHUB_ENV + + - name: Publish release notes + uses: release-drafter/release-drafter@v7 + with: + config-name: release-drafter.yml + publish: true + name: "v${{ env.VERSION }}" + tag: "v${{ env.VERSION }}" + version: "v${{ env.VERSION }}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + auto-merge-dependabot: # only for PRs by dependabot[bot] if: github.event.pull_request.user.login == 'dependabot[bot]' diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index bb7c265..d732213 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -9,4 +9,5 @@ kotlin { dependencies { implementation(libs.kotlinGradlePlugin) implementation(libs.ktlintGradlePlugin) + implementation(libs.vanniktechPublishPlugin) } diff --git a/buildSrc/src/main/kotlin/publish.gradle.kts b/buildSrc/src/main/kotlin/publish.gradle.kts new file mode 100644 index 0000000..697d4b4 --- /dev/null +++ b/buildSrc/src/main/kotlin/publish.gradle.kts @@ -0,0 +1,34 @@ +package buildsrc.convention + +plugins { + id("com.vanniktech.maven.publish") +} + +mavenPublishing { + publishToMavenCentral() + signAllPublications() + + pom { + name.set(project.name) + description.set(provider { project.description ?: "Transactional outbox pattern for Kotlin/JVM" }) + url.set("https://github.com/softwaremill/okapi") + licenses { + license { + name.set("Apache-2.0") + url.set("https://www.apache.org/licenses/LICENSE-2.0") + } + } + developers { + developer { + id.set("softwaremill") + name.set("SoftwareMill") + url.set("https://softwaremill.com") + } + } + scm { + connection.set("scm:git:git://github.com/softwaremill/okapi.git") + developerConnection.set("scm:git:ssh://github.com/softwaremill/okapi.git") + url.set("https://github.com/softwaremill/okapi") + } + } +} diff --git a/gradle.properties b/gradle.properties index b06a80a..71997d2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,3 +5,6 @@ org.gradle.caching=true # (Note that some plugins may not yet be compatible with the configuration cache.) # https://docs.gradle.org/current/userguide/configuration_cache.html org.gradle.configuration-cache=true + +GROUP=com.softwaremill.okapi +VERSION_NAME=0.1.0 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bacaf95..28dc9e3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,6 +11,7 @@ mysql = "9.6.0" kafkaClients = "4.2.0" spring = "7.0.6" springBoot = "4.0.5" +vanniktechPublish = "0.36.0" wiremock = "3.13.2" slf4j = "2.0.17" assertj = "3.27.7" @@ -18,6 +19,7 @@ assertj = "3.27.7" [libraries] kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } ktlintGradlePlugin = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlint" } +vanniktechPublishPlugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "vanniktechPublish" } kotestRunnerJunit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" } kotestAssertionsCore = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } exposedCore = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" } diff --git a/okapi-bom/build.gradle.kts b/okapi-bom/build.gradle.kts index 6522ebb..588ba56 100644 --- a/okapi-bom/build.gradle.kts +++ b/okapi-bom/build.gradle.kts @@ -1,7 +1,10 @@ plugins { `java-platform` + id("buildsrc.convention.publish") } +description = "BOM for consistent versioning of Okapi modules" + dependencies { constraints { api(project(":okapi-core")) diff --git a/okapi-core/build.gradle.kts b/okapi-core/build.gradle.kts index 34f5112..a2fee38 100644 --- a/okapi-core/build.gradle.kts +++ b/okapi-core/build.gradle.kts @@ -1,7 +1,10 @@ plugins { id("buildsrc.convention.kotlin-jvm") + id("buildsrc.convention.publish") } +description = "Core outbox abstractions and processing engine" + dependencies { implementation(libs.slf4jApi) testImplementation(libs.kotestRunnerJunit5) diff --git a/okapi-http/build.gradle.kts b/okapi-http/build.gradle.kts index f483d89..17c8143 100644 --- a/okapi-http/build.gradle.kts +++ b/okapi-http/build.gradle.kts @@ -1,7 +1,10 @@ plugins { id("buildsrc.convention.kotlin-jvm") + id("buildsrc.convention.publish") } +description = "HTTP message delivery for outbox entries" + dependencies { implementation(project(":okapi-core")) implementation(libs.jacksonModuleKotlin) diff --git a/okapi-kafka/build.gradle.kts b/okapi-kafka/build.gradle.kts index a9eafd0..3318514 100644 --- a/okapi-kafka/build.gradle.kts +++ b/okapi-kafka/build.gradle.kts @@ -1,7 +1,10 @@ plugins { id("buildsrc.convention.kotlin-jvm") + id("buildsrc.convention.publish") } +description = "Apache Kafka message delivery" + dependencies { implementation(project(":okapi-core")) implementation(libs.jacksonModuleKotlin) diff --git a/okapi-mysql/build.gradle.kts b/okapi-mysql/build.gradle.kts index e8626ed..1ba1d75 100644 --- a/okapi-mysql/build.gradle.kts +++ b/okapi-mysql/build.gradle.kts @@ -1,7 +1,10 @@ plugins { id("buildsrc.convention.kotlin-jvm") + id("buildsrc.convention.publish") } +description = "MySQL outbox store using Exposed" + dependencies { implementation(project(":okapi-core")) diff --git a/okapi-postgres/build.gradle.kts b/okapi-postgres/build.gradle.kts index a32c088..ac12d31 100644 --- a/okapi-postgres/build.gradle.kts +++ b/okapi-postgres/build.gradle.kts @@ -1,7 +1,10 @@ plugins { id("buildsrc.convention.kotlin-jvm") + id("buildsrc.convention.publish") } +description = "PostgreSQL outbox store using Exposed" + dependencies { implementation(project(":okapi-core")) diff --git a/okapi-spring-boot/build.gradle.kts b/okapi-spring-boot/build.gradle.kts index 78e229a..851dc72 100644 --- a/okapi-spring-boot/build.gradle.kts +++ b/okapi-spring-boot/build.gradle.kts @@ -1,7 +1,10 @@ plugins { id("buildsrc.convention.kotlin-jvm") + id("buildsrc.convention.publish") } +description = "Spring Boot autoconfiguration for Okapi" + dependencies { implementation(project(":okapi-core"))