Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add publish gradle scripts #56

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/verify.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ jobs:
min-coverage-changed-files: 60
- name: Coverage verify
run: ./gradlew koverVerify
- name: Publish Maven Central
if: success()
env:
GITHUB_HEAD_REF: ${{ github.head_ref }}
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
GPG_SIGNING_PASSWORD: ${{ secrets.GPG_SIGNING_PASSWORD }}
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
run: ./gradlew snapshotAll printDevSnapshotReleaseNote
detekt:
name: Detekt
runs-on: ubuntu-latest
Expand Down
242 changes: 241 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import io.gitlab.arturbosch.detekt.Detekt
import io.gitlab.arturbosch.detekt.report.ReportMergeTask

group = "io.github.turchenkoalex"
version = "1.0-SNAPSHOT"

plugins {
`java-library`
`maven-publish`
signing
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.kotlinx.serialization) apply false
alias(libs.plugins.detekt)
alias(libs.plugins.kover)
alias(libs.plugins.nebula.release)
alias(libs.plugins.nexus.publish)
}

allprojects {
Expand Down Expand Up @@ -78,3 +82,239 @@ subprojects {
}
}
}

val publishProjects = setOf(
"core",
"cors",
)

val settingsProvider = SettingsProvider()

tasks.withType<Sign> {
doFirst {
settingsProvider.validateGPGSecrets()
}
dependsOn(tasks.getByName("build"))
}

tasks.withType<PublishToMavenRepository> {
doFirst {
settingsProvider.validateSonatypeCredentials()
}
}

val snapshotAllTask = tasks.register("snapshotAll") {
group = "publishing"
}

subprojects {
if (this.name in publishProjects) {
apply(plugin = "java-library")
apply(plugin = "maven-publish")
apply(plugin = "signing")
version = sanitizeVersion()

java {
withJavadocJar()
withSourcesJar()
}

publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])

groupId = "io.github.turchenkoalex"
artifactId = "kotlet-${project.name}"
version = sanitizeVersion()

versionMapping {
usage("java-api") {
fromResolutionOf("runtimeClasspath")
}
usage("java-runtime") {
fromResolutionResult()
}
}

pom {
name.set("kotlet-${project.name}")
description.set("Kotlet ${project.name} library")
url.set("https://github.com/turchenkoalex/kotlet")
licenses {
license {
name.set("Apache License, Version 2.0")
url.set("https://opensource.org/licenses/Apache-2.0")
}
}
developers {
developer {
id.set("turchenkoalex")
name.set("Aleksandr Turchenko")
}
}
scm {
connection.set("scm:git:git://github.com/turchenkoalex/kotlet.git")
developerConnection.set("scm:git:ssh://github.com/turchenkoalex/kotlet.git")
url.set("https://github.com/turchenkoalex/kotlet")
}
}
}
}

repositories {
maven {
setUrl(layout.buildDirectory.dir("staging-deploy"))
}
}
}

signing {
useInMemoryPgpKeys(settingsProvider.gpgSigningKey, settingsProvider.gpgSigningPassword)
sign(publishing.publications["mavenJava"])
}

snapshotAllTask.configure {
dependsOn(tasks.getByName("publishToSonatype"))
}
}
}

tasks.register("printFinalReleaseNote") {
doLast {
printFinalReleaseNote(
groupId = "io.github.turchenkoalex",
artifactId = "kotlet",
sanitizedVersion = project.sanitizeVersion()
)
}
dependsOn(tasks.getByName("final"))
}

tasks.register("printDevSnapshotReleaseNote") {
doLast {
printDevSnapshotReleaseNote(
groupId = "io.github.turchenkoalex",
artifactId = "kotlet",
sanitizedVersion = project.sanitizeVersion()
)
}
dependsOn(snapshotAllTask)
}


nexusPublishing {
repositories {
sonatype {
useStaging.set(!project.isSnapshotVersion())
packageGroup.set("io.github.turchenkoalex")
username.set(settingsProvider.sonatypeUsername)
password.set(settingsProvider.sonatypePassword)
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}

// We want to change SNAPSHOT versions format from:
// <major>.<minor>.<patch>-dev.#+<branchname>.<hash> (local branch)
// <major>.<minor>.<patch>-dev.#+<hash> (github pull request)
// to:
// <major>.<minor>.<patch>-dev+<branchname>-SNAPSHOT
fun Project.sanitizeVersion(): String {
val version = version.toString()
return if (project.isSnapshotVersion()) {
val githubHeadRef = settingsProvider.githubHeadRef
if (githubHeadRef != null) {
// github pull request
version
.replace(Regex("-dev\\.\\d+\\+[a-f0-9]+$"), "-dev+$githubHeadRef-SNAPSHOT")
} else {
// local branch
version
.replace(Regex("-dev\\.\\d+\\+"), "-dev+")
.replace(Regex("\\.[a-f0-9]+$"), "-SNAPSHOT")
}
} else {
version
}
}

fun Project.isSnapshotVersion() = version.toString().contains("-dev.")

fun printFinalReleaseNote(groupId: String, artifactId: String, sanitizedVersion: String) {
println()
println("========================================================")
println()
println("New RELEASE artifact version were published:")
println(" groupId: $groupId")
println(" artifactId: $artifactId")
println(" version: $sanitizedVersion")
println()
println("Discover on Maven Central:")
println(" https://repo1.maven.org/maven2/${groupId.replace('.', '/')}/$artifactId/")
println()
println("Edit or delete artifacts on OSS Nexus Repository Manager:")
println(" https://oss.sonatype.org/#nexus-search;gav~$groupId~~~~")
println()
println("Control staging repositories on OSS Nexus Repository Manager:")
println(" https://oss.sonatype.org/#stagingRepositories")
println()
println("========================================================")
println()
}

fun printDevSnapshotReleaseNote(groupId: String, artifactId: String, sanitizedVersion: String) {
println()
println("========================================================")
println()
println("New developer SNAPSHOT artifact version were published:")
println(" groupId: $groupId")
println(" artifactId: $artifactId")
println(" version: $sanitizedVersion")
println()
println("Discover on Maven Central:")
println(" https://s01.oss.sonatype.org/content/repositories/snapshots/${groupId.replace('.', '/')}/$artifactId/")
println()
println("Edit or delete artifacts on OSS Nexus Repository Manager:")
println(" https://s01.oss.sonatype.org/#nexus-search;gav~$groupId~~~~")
println()
println("========================================================")
println()
}

class SettingsProvider {

val gpgSigningKey: String?
get() = System.getenv(GPG_SIGNING_KEY_PROPERTY)

val gpgSigningPassword: String?
get() = System.getenv(GPG_SIGNING_PASSWORD_PROPERTY)

val sonatypeUsername: String?
get() = System.getenv(SONATYPE_USERNAME_PROPERTY)

val sonatypePassword: String?
get() = System.getenv(SONATYPE_PASSWORD_PROPERTY)

val githubHeadRef: String?
get() = System.getenv(GITHUB_HEAD_REF_PROPERTY)

fun validateGPGSecrets() = require(
value = !gpgSigningKey.isNullOrBlank() && !gpgSigningPassword.isNullOrBlank(),
lazyMessage = { "Both $GPG_SIGNING_KEY_PROPERTY and $GPG_SIGNING_PASSWORD_PROPERTY environment variables must not be empty" }
)

fun validateSonatypeCredentials() = require(
value = !sonatypeUsername.isNullOrBlank() && !sonatypePassword.isNullOrBlank(),
lazyMessage = { "Both $SONATYPE_USERNAME_PROPERTY and $SONATYPE_PASSWORD_PROPERTY environment variables must not be empty" }
)

private companion object {
private const val GPG_SIGNING_KEY_PROPERTY = "GPG_SIGNING_KEY"
private const val GPG_SIGNING_PASSWORD_PROPERTY = "GPG_SIGNING_PASSWORD"
private const val SONATYPE_USERNAME_PROPERTY = "SONATYPE_USERNAME"
private const val SONATYPE_PASSWORD_PROPERTY = "SONATYPE_PASSWORD"
private const val GITHUB_HEAD_REF_PROPERTY = "GITHUB_HEAD_REF"
}
}
5 changes: 5 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ auth0-jwt = "4.4.0"
detekt = "1.23.7"
jakarta = "6.1.0"
jetty = "12.0.16"
jreleaser = "1.15.0"
kotlin = "2.1.0"
kotlinx-serialization = "1.8.0"
kover = "0.9.1"
mockk = "1.13.16"
nebula = "19.0.10"
nexus = "1.3.0"
opentelemetry = "1.46.0"
opentelemetry-instrumentation-api = "2.11.0"
opentelemetry-semconv = "1.29.0-alpha"
Expand All @@ -19,6 +22,8 @@ jmh = { id = "me.champeau.jmh", version = "0.7.2" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
nebula-release = { id = "com.netflix.nebula.release", version.ref = "nebula" }
nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus" }

[libraries]

Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading