Check! Maven のリポジトリにデプロイする仕組みを理解する
Prologue
とあるプロジェクトで、Maven リポジトリへのデプロイに関してメンテナンスする作業を担当することになりまして、こんがらがってきたので記事に起こして整理を試みます🤯
ここでは、成果物を独自リポジトリ、または OSSRH (Central Repository) にデプロイする方法について調べたことを書き留めます。なお、当方は Java を利用した開発経験が乏しいので、間違いのご指摘や、もっといい方法あるよのアドバイスありましたら、コメントいただけるとうれしいです!
リポジトリにデプロイする仕組み (見よう見まね)
まず、Maven のパッケージは、Central Repository によって管理されています。
オープンソースとしてそこに登録するには、Sonatype が管理する OSSRH (Open Source Software Repository Hosting) を利用することができます。この記事でも、 OSSRH を利用する想定です。
OSSRH のリポジトリを経由して Central Repository へデプロイするには、OSSRH のステージングリポジトリにデプロイしたのち、Repository Manager の GUI を利用して公開します。なお、事前にネームスペースの登録やアクセス許可の依頼などが必要です。詳細は下記のガイドをご参考ください。(ここでは、前任者がすでに済ませてくれているので割愛します。)
ここで整理するのは下記です。
- デプロイ先のリポジトリおよび接続情報の指定
- GPG による署名
- デプロイプラグインの設定
pom.xml と settings.xml, settings-security.xml のおさらい
作業当初、これらのファイルのことさえよく理解していなかったので、一応メモしておきます😳
まず、pom.xml は、プロジェクトの設定を記述しておくファイルです。
settings.xml は、プロジェクトに紐づかない設定を記述するもので、 ${maven.home}/conf/settings.xml
または ${user.home}/.m2/settings.xml
に配置します。
settings-security.xml は、暗号化を利用する場合に、暗号化したマスターパスワードを保持しておくファイルです。
下記のようにマスターパスワードを暗号化し、 settings-security.xml に記述します。(サンプルコードで表示されている暗号化された文字列はダミーです。)
mvn --encrypt-master-password <password>
{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}
<settingsSecurity>
<master>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}</master>
</settingsSecurity>
サーバーパスワードを暗号化するには、下記コマンドを実行し、出力された文字列を settings.xml に記述します。(サンプルコードで表示されている暗号化された文字列はダミーです。)
mvn --encrypt-password <password>
{COQLCE6DU6GtcS5P=}
<settings>
...
<servers>
<server>
<id>my.server</id>
<username>foo</username>
<password>{COQLCE6DU6GtcS5P=}</password>
</server>
</servers>
...
</settings>
詳細は下記をご確認ください。
自前の Nexus Repository manager の準備
さて、いきなり OSSRH へのデプロイを試すには不安があるので、自前でリポジトリを建てて練習してみます。
OSSRH は、リポジトリをホストするために Sonatype Nexus Repository Manager を利用しているので、ここでもそれを使います。バージョンは最新版は 3 ですが、OSSRH と併せて 2 を選定します。ここでは構築・設定について詳しく扱いませんが、下記が参考になりました。
Repository manager を立ち上げたら、Maven2 用のリポジトリを追加します。
接続情報は「Summary」タブを開くと参照できます。
リポジトリに接続するための設定
リポジトリへの接続情報を、 pom.xml と settings.xml に記述します。
プロジェクトの pom.xml には <distributionManagement>
ブロックを記述し、リポジトリのURLを指定します。 <repository>
と <snapshotRepository>
の違いは、後者は <version>
の末尾に -SNAPSHOT
が含まれている場合のデプロイ先になります。
そして、 settings.xml に、リポジトリへの認証に利用するユーザー名とパスワードを記述します。<password>
の値は、暗号化したパスワードを指定しましょう。
pom.xml の <distributionManagement>.<repository>.<id>
と settings.xml の <servers>.<server>.<id>
は一致する文字列を記述します。
自前リポジトリの場合
自前リポジトリの場合は、前述のように Repository manager から確認できます。この記事では、この自前リポジトリへデプロイする前提で進めます。
<project>
<groupId>com.example.your-project<groupId>
<artifactId>your-artifact</artifactId>
<version>0.0.1</version>
...
<distributionManagement>
<repository>
<id>your-repository</id>
<url>http://<your server>:8081/nexus/content/repositories/your-repository</url>
</repository>
</distributionManagement>
</project>
<settings>
<servers>
<server>
<id>your-repository</id>
<username>your-username</username>
<password>{encrypted password}</password>
</server>
</servers>
</settings>
- 参考: Servers | Maven – Settings Reference
- 参考: Repository | Maven – POM Reference
- 参考: Maven – Guide to Deployment and Security Settings
OSSRH を対象にする場合
OSSRH を対象にする場合は下記のように記述します。
<project>
...
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</project>
<settings>
<servers>
<server>
<id>ossrh</id>
<username>your-jira-id</username>
<password>{encrypted password}</password>
</server>
</servers>
</settings>
詳細は下記をご参考ください。
GPGによる署名
GPGの署名を行うには、Maven GPG plugin を利用できます。下記を参考に設定します。
なお、GPGキーは事前に作成(またはインポート)しておく必要があります。詳しくはこちらをご確認ください。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<settings>
<servers>
<!-- encrypted private key passphrase -->
<server>
<id>your.keyname</id>
<passphrase>clear or encrypted text</passphrase>
</server>
</servers>
...
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<gpg.keyname>${gpg.keyname}</gpg.keyname>
<gpg.passphraseServerId>${gpg.keyname}</gpg.passphraseServerId>
</properties>
</profile>
</profiles>
</settings>
mvn deploy
中にパスフレーズを入力させる GUI が出てしまう場合の対処
上記の pom.xml サンプルにも記載した下記の部分、これは GPG のバージョンによっては mvn deploy
の実行中にパスフレーズを入力させるGUI入力画面が開いてしまう場合があり、それに対処するものです。
<configuration>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
これは、 GPG 2.1 から仕様が変わり、 settings.xml からパスフレーズを入力させるには、gpg
コマンドの --pinentry-mode
というオプションに loopback
を指定しないとならなくなったための対処です。詳細は下記記事をご参照ください。
Tips: プロパティによって GPG 署名の有無を切り替える
なお、開発時のビルドでは、GPG署名を含める必要はないので、 profile build を使って条件を指定したときのみ含めるようにするとよいようです。下記が参考になります。
Maven のタグを使って、普段は GPG プラグインを実行しないようにしておきます。サインするときだけ、コマンドで
-DperformRelease=true
を渡します。
<profiles>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
デプロイプラグインの設定
デプロイするプラグインは複数あるようで、 nexus-staging-maven-plugin や maven-deploy-plugin が利用できるようです。ここでは、maven-deploy-plugin を利用します。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</build>
コマンドによるデプロイ
ここまで準備ができたら、デプロイしてみましょう!
ターミナルでデプロイコマンドを実行します。
mvn clean deploy
GPG署名を前述の方法で切り替えする方は、下記のようにオプションを指定してください。
mvn clean deploy -DperformRelease=true
無事にビルドが進み、 BUILD SUCCESS
が表示されれば成功です!🎉
[INFO] --- maven-deploy-plugin:2.8.2:deploy (default-deploy) @ your-artifact ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:17 min
[INFO] Finished at: 2020-12-01T05:52:12Z
[INFO] ------------------------------------------------------------------------
Epilogue
この内容は、もともとある自動化のコードをもとに担当を引き継いだので、正解があるから何とかなるだろーって思ったらなかなか大変でしたw
苦戦したのは GPG 署名… どうしてもパスフレーズのダイアログが表示されて悩みあぐねてやっと解法を見つけた次第です。今動いている環境では、GPGのバージョンが古いかどこかでよしなにされているのかも… 後ほど余力があれば調べてみようと思います。
ということで、本当はこれを GitHub Actions のワークフローに仕立てたいので、それはまた別の記事にしたためます!お楽しみに!🙌
Discussion