何があったの?
Gradleを利用して自作したJavaライブラリをGitHub Packagesを使って公開しようとした所いくつか罠にはまりました。今回はハマってしまった罠とその対処法を紹介します。今回の問題にあたってGitHubさんのサポートを利用しましたがGitHubさんのサポートは最高でした。
環境
経緯
ExtendedFunctionLibraryという自作ライブラリを公開しようと思ってリポジトリをどこにしようかなーって調べてたらGitHub Packagesの存在を知りました。GitHub Packagesは作成したソフトウェアパッケージを公開出来るサービスなのですが、なんとGradleプロジェクトを公開して他のプロジェクトから依存出来るらしいのです。普通Bintray等を使うのですがリポジトリを用意する手間って中々大変なんですよね。GitHub PackagesならGitHubとの連携もスムーズ、これは便利だ!てことで勉強を始めたら実際にライブラリを公開するまでにいくつもの罠にハマりました。
罠1: GitHub Packages Disabled
対策: アカウントの支払情報を設定する
これ、めちゃくちゃ困りました。ドキュメントのGitHub Packagesの支払いについてを確認すると
Github PackagesはGitHub Free (中略)で利用できます。
GitHub Packagesの利用は、パブリックパッケージについては無料です。
等明示されています。確認してみたところ私のアカウントはGitHub Free, 作ろうとしているのは無料のパブリックパッケージだったので利用できるはずなのに、実際はGithub Packages自体が無効化されていました。 下記の画像はGitHub プロフィールのPackagesタブですが、ここにGitHub Packages Disabled等と表示されている場合はアカウントの支払情報が登録されていない可能性があります。未設定の場合はSetting -> Billingと進み支払情報を登録しましょう。
罠2: certificate for <maven.pkg.github.com> doesn't match any of the subject alternative names: [*.registry.github.com, registry.github.com]
対策: Gradleで利用するJDKのバージョンを上げる
これは実際にGitHub Packagesにパッケージをアップロードする際に発生したエラーです。これは自力では解決できなかったのでGitHub Supportにメールを送りました。maven.pkg.github.comと言うのはGitHub PackagesにMavenパッケージをアップロードする際にアクセスするドメインになります。エラー文は「これのSSL証明書が代替名と一致しない」と言っています。私は詳しくないのですが、SSL証明書と言うのはクライアント-サーバ間でHTTPS通信を行う(つまりSSL接続を行う)際に必要になるものなのですが、これが古くて新しい物と一致しないため通信が出来ないとの事でした。
この問題についてはGitHub サポートさんより「Gradleで利用するJDKのバージョンを上げてはどうか」と言っていただきました。当時自分がGradleを利用するために使っていたJDKのバージョンは11でしたがこれを14まで上げました。結果このエラーは発生しなくなりました。以下手順を書いておきます
手順1. Gradleで利用するJDKのバージョンアップ
IDEAにて
File
->Settings
->Build, Execution
->Deployment
->Build Tools
->Gradle
と進み、Gradle JVMを14に設定。JVMが無い場合はダウンロードしてきてください。
手順2. Gradleのバージョンアップ
gradle-wrapper.propertiesのdistributionUrlを以下のように書き換える
distributionUrl=https\://services.gradle.org/distributions/gradle-<6.3以上のリリース>-bin.zip
GradleのリリースノートよりGradleでJDK14がサポートされているのは6.3以降との事です。6.3以降を指定してください。私は執筆時点で最新の6.6.1を指定しています。
手順3. build.gradleでプロジェクトのソースファイル、クラスファイルのバージョンを指定
これは必須では無いのですが、Gradleが利用するJVMのバージョンとプロジェクトのバージョンが違う場合に必要になります。ご自身の開発環境に合わせて設定して問題ありません。私は現在Java11で開発してますので次のように設定しました。
ext { javaVersion = JavaVersion.VERSION_11 } java { setSourceCompatibility javaVersion setTargetCompatibility javaVersion }
罠3: Received status code 422 from server: Unprocessable Entity
対策: build.gradleだけでなくsetting.gradleのrootProject.nameを確認する
これはアップロードしようとしている物が何らかの形で不正であるときに発生するHTTPレスポンスです。問題は何がどう不正なのか全く分からない事です。Gradle経由でGitHub Packagesを利用する場合はmaven-publishプラグインを利用してbuild.gradleで設定することになるのですが、今回実はbuild.gradleと直接は無関係な場所が原因でした。それが対策に書かれているsetting.gradleです。
setting.gradleは主にマルチプロジェクト等を設定するときに利用するのですが、ルートプロジェクトのみの場合であってもプロジェクト名を指定するために利用します。実際にプロジェクト名を指定しているのがrootProject.nameプロパティです。maven-publishプラグインを利用する場合配布するJarのデフォルトのartifactIdがrootProject.nameになります。ところでMaven公式ドキュメントによればartifactIdとは配布されるJarファイルからversionを除いたものであり、小文字で変な記号を使ってはいけません(原文ほぼ直訳)。私のライブラリの名前はExtendedFunctionLibraryなのでプロジェクト名をこれにしていたのですが、そのせいでartifactIdに大文字が入り、無効な名前になってしまっていたみたいでした。きちんとMavenのドキュメントを読んでいればわかる事でしたね。こんなの気づくわけねぇだろ。一つ言い訳をするなら私はMavenを使った事が無く、この事を全く知りませんでした…。GradleのドキュメントではMavenを利用することについては書かれているのですがMavenの内容については既知であるのが前提のような説明になっています。きちんと勉強しないとダメですね。以下にMaven周りの設定のチェックリストを残しておきます。
- repositoriesのURLは適切か
- https://maven.pkg.github.com/小文字ユーザー名/リポジトリ名(大文字可)
- リポジトリの認証情報は適切か
credentials { username = project.findProperty "github.username" password = project.findProperty "github.password" }
- artifactIdは適切か
アップロード出来たーーー!!!って消せないんだけど?
>パッケージに依存しているかもしれないプロジェクトが壊れることを避けるために、パブリックなパッケージ全体、あるいはパブリックなパッケージの特定バージョンを削除する事はできません。
— RayStark a.k.a. ロジニキ (@RayStark77) October 13, 2020
^q^https://t.co/NRlU0Ir0zp
ドキュメントはちゃんと読もう。
最後に
如何でしたでしょうか。わかってしまえば簡単な事なんですけどこれらが全部同時に来たので何が問題なのか紐解くのがとても大変でしたw
最後に協力してくださった方々にこの場を借りてお礼申し上げます。手厚く対応してくださったGitHub Supportの皆様、ツイッターで嘆く私に協力してくれた皆様、本当にありがとうございました。
この記事が誰かの役に立てばいいなぁ。