Keep on moving

あんまりまとまってないことを書きますよ

Kotlinで書いたアプリのMaven Central Repository への公開手順(Gradle KotlinDSL 版)

- version
Date 2021.02.13
OpenJDK OpenJDK Runtime Environment Zulu11.43+1017-CA (build 11.0.9.1+1-LTS)
kotlin 1.4.30
gradle 6.8.2

Kotlinで書いたアプリのMaven Central Repository への公開手順(Gradle(KotlinDSL)版)

TL;DR

  • bintrayに公開していたものを移行するのは割と簡単
    • sonatypeへの登録は初回だけちょいと面倒かも(JIRAでissue作ったりが必要)
    • singingの追加
      • pgp keyの登録が必要
    • maven-publish pluginを使っていればアップロード先をbintray -> maven-centralに変える
  • 僕が使っているbuild.gradle.ktsを共有

流れ

こちらのブログが素晴らしく良くまとまっているので参照すると良いと思います。

blog1.mammb.com

  1. sonatype の JIRA で issue を通してリポジトリ作成を依頼
  2. GnuPG で jar を署名できる環境を作成
  3. Gradle プラグインリポジトリへ登録
  4. Repository Manager で Maven Central Repository へリリース

Tips

いくつか捕捉しておくと良さそうなことを書いておきます。

windowsを使っている方向け

windowsで表題の件をやりたい場合はこちらでgpg keyを作成すると良いと思います。 https://www.gpg4win.org/

gnupgmacportsで入れる

sudo port install gnupg2 # XCodeが必要

RSA keys may be between 1024 and 4096 bits long

ここは (3072) [デフォルト]になったみたいです。

すでにbintrayに公開済みのjarをmavencentralに移行

jfrog.com

JVM言語界隈に激震が走ったこの件について。 bintrayにpublishしているものをmaven centralに移行したい方は以下の感じになります

  1. sonatype の JIRA で issue を通してリポジトリ作成を依頼
  2. GnuPG で jar を署名できる環境を作成
  3. Gradle プラグインを変更してリポジトリへ登録
  4. Repository Manager で Maven Central Repository へリリース

build.gradle.ktsの書き換えは以下のような感じになります。

github.com

抜粋すると

plugins {
    ...
    signing // signingを追加. bintrayではこれが必要なかった
}
...
//    repositories {
//        maven {
//            name = "bintray"
//            val bintrayUsername = "masahitojp"
//            val bintrayRepoName = "maven"
//            val bintrayPackageName = "com.github.masahitojp.bqdatamapper4k"
//            setUrl("https://api.bintray.com/content/$bintrayUsername/$bintrayRepoName/$bintrayPackageName/${project.version};publish=0;override=1")
//            credentials {
//                username = project.findProperty("bintray_user") as String?
//                password = project.findProperty("bintray_api_key") as String?
//             }
//    }
    repositories {
        maven {
            name = "MavenCentral"
            val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
            val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
            credentials {
                username = project.findProperty("sonatypeUsername")?.toString() ?: ""
                password = project.findProperty("sonatypePassword")?.toString() ?: ""
            }
        }
    }
// PGP署名(Mavenセントラルリポジトリに公開するのに必要な署名形式)の追加
signing {
    sign(publishing.publications["maven"])
}

私がよく使っているbuild.gradle.ktsGradle(KotlinDSL)

plugins {
    val kotlinVersion = "1.4.30"
    kotlin("jvm") version kotlinVersion
    id("org.jetbrains.dokka") version "1.4.20" // Docにはdokkaを使う(ここは自分の好きなのに入れ替えてよし)
    `maven-publish`
    signing
}

group = 'Your Group Id'
version = 'X.X.X'
val artifactID = "プロジェクト名"

repositories {
    mavenCentral()
    jcenter() // dokka dependency
}

dependencies {

    // Use the Kotlin JDK 8 standard library.
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")


   // 必要ならライブラリがあれば追加

    // Use the Kotlin test library.
    testImplementation("org.jetbrains.kotlin:kotlin-test")

    // Use the Kotlin JUnit integration.
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

// Configure existing Dokka task to output HTML to typical Javadoc directory
tasks.dokkaHtml.configure {
    outputDirectory.set(buildDir.resolve("javadoc"))
}

// Create dokka Jar task from dokka task output
val dokkaJar by tasks.creating(Jar::class) {
    group = JavaBasePlugin.DOCUMENTATION_GROUP
    description = "Assembles Kotlin docs with Dokka"
    archiveClassifier.set("javadoc")
    // dependsOn(dokka) not needed; dependency automatically inferred by from(dokka)
    from(tasks.dokkaHtml)
}

// Create sources Jar from main kotlin sources
val sourcesJar by tasks.creating(Jar::class) {
    description = "Assembles sources JAR"
    archiveClassifier.set("sources")
    from(sourceSets["main"].allSource)
}

artifacts {
    add("archives", sourcesJar)
    add("archives", dokkaJar)
}

val jar by tasks.getting(Jar::class) {
    manifest {
        attributes(
            "Implementation-Title" to project.name,
            "Implementation-Version" to project.version,
            "Implementation-Vendor" to "masahito.me",
            "Built-JDK" to "${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})",
            "Built-Gradle" to gradle.gradleVersion
        )
    }
}

val sonatypeUsername = project.findProperty("sonatypeUsername")?.toString() ?: ""
val sonatypePassword = project.findProperty("sonatypePassword")?.toString() ?: ""

publishing {
    publications {
        create<MavenPublication>("maven") {
            groupId = project.group.toString()
            from(components.findByName("kotlin"))
            artifact(sourcesJar)
            artifact(dokkaJar)
            pom {
                name.set(artifactId)
                description.set("BigQuery datamapper for Kotlin")
                url.set("https://github.com/masahitojp/bqdatamapper4k")
                licenses {
                    license {
                        name.set("Apache License, Version 2.0")
                        url.set("https://opensource.org/licenses/Apache-2.0")
                    }
                }
                developers {
                    developer {
                        id.set("Your ID")
                        name.set("Your name")
                        email.set("Your email address")
                    }
                }
                scm {
                    connection.set("scm:git:git@github.com:XXXXX.git")
                    developerConnection.set("scm:git:ssh://github.com:XXXXX.git")
                    url.set("https://github.com/XXXXX")
                }
            }
        }
    }
    repositories {
        maven {
            name = "MavenCentral"
            val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
            val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
            credentials {
                username = sonatypeUsername
                password = sonatypePassword
            }
        }
    }
}

signing {
    sign(publishing.publications["maven"])
}

まとめ

  • bintrayに公開していたものを移行するのは割と簡単
    • sonatypeへの登録は初回だけちょいと面倒かも(JIRAでissue作ったりが必要)
    • singingの追加
      • pgp keyの登録が必要
    • maven-publish pluginを使っていればアップロード先をbintray -> maven-centralに変える
  • 僕が使っているbuild.gradle.ktsを共有

上記をしました。すでにsonatypeにアカウントを作っていればそんなに大変なことはないと思います。 ちょっと古かったりしますがまとめ直してくれていたりする素敵なかたがたくさんいたので僕は1時間くらいで作業を終えることができました。 先人たちに感謝。