jCenter (bintray) にアップロードするbuild.gradle

**[Into the Sunset on May 1st: Bintray, JCenter, GoCenter, and ChartCenter](https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/)**
jCenterは閉鎖する（リードオンリーで参照のみ可能）とのことですので、Maven Centralに移行しましょう。

Maven Centralへ移行する方法はこちらを参照
[jCenterで公開していたKotlinライブラリをMaven Centralで公開する](https://qiita.com/ryo_mm2d/items/40df6e292c691366038e)

----

[jCenterでライブラリを公開する方法](https://qiita.com/ryo_mm2d/items/da49cc4677847c20c3fb)という記事で書いたが、Gradleのアップデートなどで使えなくなってしまった。
なので、Gradle 5.5.1 / Android Gradle Plugin 3.4.2 な環境で使える版を再度投稿

# 以前の方法でうまくいかないこと

## (Android) Pluginが使えない
Androidのインストール構成を作るのに com.github.dcendents.android-maven プラグインを使っていた、しかし

> Abandoned. If you are using Kotlin 1.3.30+ and Gradle 5.x, please use https://github.com/sky-uk/gradle-maven-plugin instead.

というわけでGradleの5以上で使えなくなってしまった。つまりAndroid Gradle Plugin 3.4.xでは使えない。

## apiの依存関係が反映されない

Pure Javaの環境であればintall構成を書くだけでよかったが、apiの依存関係がpomファイルに反映されていないことが分かった。

どういうことかというと、以下のような依存関係を書いていたのだが、

```gradle
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    api "net.mm2d:log:0.8.4"

    testImplementation "io.mockk:mockk:1.9.3"
    testImplementation "com.google.truth:truth:1.0"
    testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.2"
    testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}
```

アップロードされたpomファイルを見てみると以下のようになっていた、

```xml
  <dependencies>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib-jdk7</artifactId>
      <version>1.3.41</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>io.mockk</groupId>
      <artifactId>mockk</artifactId>
      <version>1.9.3</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.truth</groupId>
      <artifactId>truth</artifactId>
      <version>1.0</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlinx</groupId>
      <artifactId>kotlinx-coroutines-core</artifactId>
      <version>1.2.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
```

testスコープは置いておいて、apiで記述したライブラリの依存関係が記述されていない。
apiでは依存関係を伝搬させるので、pomファイル的にはcompileスコープで書き出されることを期待していた。

```xml
    <dependency>
      <groupId>net.mm2d</groupId>
      <artifactId>log</artifactId>
      <version>0.8.4</version>
      <scope>compile</scope>
    </dependency>
```

いろいろ調べてみたが、どうもこの辺はうまく扱えず手動で拾ってやる必要があるらしい、uploadArchiveタスクではちゃんと反映されるのに……

# 対応方法

結論から言うと maven-publish を使えばよい、というかbintrayのプラグインのサンプルプロジェクトでもそうしている。
Androidライブラリ、PureJavaライブラリともに同じ方法で対応可能。
これが本来の方法だったんか？ただし、依存関係の情報を詰め込む処理は自前で追加してやる必要がある。

まず、前提として、アップロード部分はコピペでいけるようにパラメータをプロジェクトルートで以下のようにextパラメータを定義している。

```gradle
buildscript {
    def versionMajor = 1
    def versionMinor = 0
    def versionPatch = 0
    ext {
        pj = [
                versions : [
                        name: "${versionMajor}.${versionMinor}.${versionPatch}",
                        code: versionMajor * 10000 + versionMinor * 100 + versionPatch
                ],
                groupId      : "com.example",
                siteUrl      : "https://github.com/example/example",
                githubUrl    : "https://github.com/example/example",
                scmConnection: "scm:git:https://github.com/example/example.git"
        ]
    }
}
```

また、ホームディレクトリの.gradle/gradle.propertiesにて以下のようにbintrayのuse名とアップロード用のkeyを定義しておきます。

```gradle
bintray_user=xxx
bintray_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

publishingタスクを以下のように記述する

```gradle
apply plugin: "maven-publish"

publishing {
    publications {
        bintray(MavenPublication) {
            artifact("$buildDir/libs/${libraryName}-${version}.jar")
            groupId = pj.groupId
            artifactId = libraryName
            version = pj.versions.name

            artifact sourcesJar

            pom.withXml {
                def node = asNode()

                def licenses = node.appendNode("licenses")
                appendLicense(licenses, "The MIT License", "https://opensource.org/licenses/MIT", "repo")

                appendScm(node, pj.scmConnection, pj.githubUrl)

                def dependencies = node.appendNode("dependencies")
                configurations.api.dependencies.each {
                    appendDependency(dependencies, it.group, it.name, it.version, "compile")
                }
                configurations.implementation.dependencies.each {
                    appendDependency(dependencies, it.group, it.name, it.version, "runtime")
                }
            }
        }
    }
}

static def appendLicense(parentNode, name, url, distribution) {
    def node = parentNode.appendNode("license")
    node.appendNode("name", name)
    node.appendNode("url", url)
    node.appendNode("distribution", distribution)
}

static def appendScm(parentNode, connection, url) {
    def node = parentNode.appendNode("scm")
    node.appendNode("connection", connection)
    node.appendNode("url", url)
}

static def appendDependency(parentNode, groupId, artifactId, version, scope) {
    def node = parentNode.appendNode("dependency")
    node.appendNode("groupId", groupId)
    node.appendNode("artifactId", artifactId)
    node.appendNode("version", version)
    node.appendNode("scope", scope)
}
```

`bintray(MavenPublication)` の`bintray`の部分は、後ほど説明するbintrayタスクで指定するための名前なので他の名前でもよいです。
依存関係部分はpomファイルに依存関係を追加するメソッドを作って、gradleの依存関係情報をpomファイルに追加します。
testスコープの依存関係は公開ライブラリでは不要な情報なので追加していません。
apiとimplementationの依存関係をpomファイルに追加する処理が含まれています。
他には、ライセンス情報とかSCMの情報も同様に追加するメソッドを作ってそれで追加しています。

これを上記内容を作った上で、bintrayタスクの中でpublicationsとして上記の構成を指定します。

```gradle
bintray {
    user = project.hasProperty("bintray_user") ? bintray_user : ""
    key = project.hasProperty("bintray_key") ? bintray_key : ""
    publications = ["bintray"]

    pkg {
        repo = "maven"
        name = pj.groupId + "." + libraryName
        licenses = ["MIT"]
        websiteUrl = pj.siteUrl
        vcsUrl = pj.githubUrl + ".git"
        issueTrackerUrl = pj.githubUrl + "/issues"
        publicDownloadNumbers = true
        version {
            name = project.version
        }
    }
}
```

これでOKと思いきや、これではビルドが走らないので以下のように依存関係を追加しておきます。

```gradle
bintrayUpload.dependsOn assemble
```

これでアップロードできるようになります。