mike-neckのブログ

Java or Groovy or Swift or Golang

Sonatype OSSRH へのリリース方法 Gradle 編 最新版-2020-04-08

久々に Maven Central にリリースしようと思って、 gradle と GnuPG などをいじくったので、そのまとめ。


3行でまとめ

  • GnuPG のバージョン 2 を使う
  • GnuPG は secretKeyRing ファイルがなくなっているので、 signing の指定方法が幾分変わっている。 CI からリリースするなら inMemoryPgpKeys を使うのがよい
  • maven プラグインでもいいけど、 maven-publish プラグインのほうがナウでオシャン

GnuPG

現在、何も考えず brew から入手できる GnuPG はバージョン 2 系になっているので、これをそのまま使った。

基本的な操作としては以下のものがある

新しい鍵を作る

$ gpg --gen-key

鍵の一覧を見る

$ gpg --list-keys --keyid-format LONG

この時に表示される pub rsa4096/11AA22BB33CC44DD55EE 2020-04-08 [SC]RSA の次の部分が key id で、送信するときなどにこれを指定する。

公開鍵サーバーに送付する

$ gpg --key-server keys.gnupg.net --send-keys 11AA22BB33CC44DD55EE

秘密鍵を armored ASCII 形式で表示する

$ gpg --export-secret-keys --armor mail-address@example.com

これは秘密鍵を表示することが目的ではなく、後ほど使う時に 環境変数に貼り付けておくために出力する。なので、 Mac でやっている場合は gpg --export-secret-keys --armor foo@example.com | pbcopy のようにクリップボードにとったりする

signing

GnuPG(version 2) で鍵を作成した後に、 鍵が置いてあるディレクトリーを見てみると次のようになっている

$ ls ~/.gnupg/
S.gpg-agent  S.gpg-agent.browser  S.gpg-agent.extra  S.gpg-agent.ssh  openpgp-revocs.d  private-keys-v1.d  pubring.kbx  pubring.kbx~  trustdb.gpg

バージョン 1 の頃にあった secring.pgp という プライベートキーを格納してあるファイルがなくなっている。

これについては、 Gradle のドキュメントにあるように次のコマンドで対応できるらしい。

$ gpg --keyring secring.gpg --export-secret-keys > ~/.gnupg/secring.gpg

だが、これ以上に便利な(特に CI などで) API ができていた。

docs.gradle.org

In-Memory PGP Key で、 armored ASCII 形式のプライベートキーとパスワードを CI のシークレットに登録しておいて、 CI 実行時に環境変数から取得するという方法である。

val privateKey: String? by project
val pgpPassword: String? by project

signing {
  useInMemoryPgpKeys(privateKey, pgpPassword)
  sign(publishing.publications["library"])
}

プロパティ privateKey には armored ASCII 形式のプライベートキーを入れておき、 pgpPassword にパスワードを設定しておく。

例えば Github Actions のシークレットに、この2つの値を入れておき、 ステップの環境変数として、これらを取り出せるようにする。

env:
  ORG_GRADLE_PROJECT_privateKey: ${{ secrets.PGP_ARMORED_PRIVATE_KEY }}
  ORG_GRADLE_PROJECT_pgpPassword: ${{ secrets.PGP_PASS_PHREASE }}

これで GnuPG 2 で作成した鍵を CI などで利用できるようになる

maven-publish プラグイン

ここ最近までは Maven Central へのリリースには maven プラグインがデフォルトのように使われてきたと思われる。しかし、このプラグインは古くて柔軟性もなかったにもかかわらず、 maven-publish がうまく sign できないのかなんなのかで今日まで生きながらえてきた(そのおかげで、まだ生きている)し、 sonatype の案内でも maven プラグインの方法のみが紹介されている。

しかし、 maven-publish プラグインでも signing ができるようになっていたので、もうこっちをメインに使ったほうがよいだろう(多分、 maven プラグインはなくなると思っている)。

と言っても、これもドキュメントそのままを書けばよい。

ポイントは、 maven レポジトリーと publish 内容を別個に設定して、これら2つの組み合わせを選択できるというところである。

たとえば、 sonatype OSSRH と Github Packages Repository の両方に同じ内容をリリースしたい場合、

  • maven repository の設定
    • sonatype の設定
    • github packages repository の設定
  • publish 内容の設定
    • library のリリース内容の設定

このような設定を作ると、 publishLibraryPublicationToSonatypeRepository というリリースタスクと publishLibraryPublicationToGithubPackagesRepository というリリースタスクが出来上がる

若干、話が脇道にそれたので戻すと、↓これだけやればよい。

具体的なリリース用の DSL はこちらを参照 :

github.com


その他の手順

その他、初めてリリースする場合などは

  • ドメインの取得(github.com などでやる場合はいらない)
  • sonatype OSSRH プロジェクトの JIRA にライブラリーの sync のサポートを依頼する
  • ドメインの所有権を確認するために TXT レコードを教えてほしいなどの依頼がくるので対応する
  • sync できる準備できたよと知らせを受けた後に Gradle で publish する
  • sonatype のリポジトリーマネージャー に JIRA と同じユーザー名・パスワードでログインできるのでログインする
  • ログイン後、 Staging Repository でリリースした artifact があるか確認して、パッケージを選択して、 Close をクリックする
  • Close 後に各種チェックが行われる
  • 各種チェックでエラーがあったら、パッケージを選択して、Drop をクリックする
  • 各種チェックが通ったら、パッケージを選択して、 Release をクリックする
  • リリース後数分で Maven Central と同期して利用可能になる
  • https://search.maven.org には 1 日くらいかかるらしい