mavenレポジトリをnexusに移設するメモ(nexusのレポジトリ構成)

# 概要
自社javaパッケージのデプロイ先を[nexus repository manager](https://www.sonatype.com/nexus-repository-oss)に移設することにしたのでその過程で調べたことをまとめる。

# やりたいこと
* 自社パッケージのデプロイ(release/snapshot問わず)
* サードパーティパッケージのキャッシング
    * いつの間にかダウンロードできなくなることだけは避けたい

# ストレージの設定
nexusではレポジトリのストレージを個別に分けることができる。
今回はmaven-reposというblob storeを作成してこれを共通して使用することにした。
もしmavenが不要になった場合はmavenレポジトリとこのストレージだけ削除すればOK。

# レポジトリの種類
(これはmaven以外のレポジトリも共通)
nexusのレポジトリにはhosted、proxy、groupの3パターンが存在する。

* hosted
    * パッケージをアップロードするためのレポジトリ
    * 自社製パッケージのアップロードはここに対して行う
* proxy
    * 外部レポジトリのプロキシとして挙動するレポジトリ
    * maven central等のサードパーティのレポジトリはこれを介してアクセスできる
    * キャッシュ期間の設定は[こちら](https://support.sonatype.com/hc/en-us/articles/115010182627-Understanding-Caching-Configuration)を参照
        * あくまでキャッシュなのでキャッシュを無効化されると消えてしまうことに注意
* group
    * 複数のレポジトリを束ねて1つのレポジトリのように取り扱うことができる
    * 前述のhosted、proxyをまとめて1つのURLでアクセスできるようにするために使用する

# レポジトリ構成
移設するにあたって以下のようにレポジトリを作成した。

## maven-central
名前の通りmaven-centralに存在するライブラリを取得するためのproxyレポジトリ。
サードパーティのsnapshotを使用することはほぼ無いため、
キャッシュ期間は無期限(Maximum component age=-1)とした。

## maven-releases
自社ライブラリのreleaseバージョンをデプロイするhostedレポジトリ。
Version policyをReleaseに設定することで、snapshotバージョンをデプロイできないように設定した。
基本的に一度デプロイした後の再デプロイは許容しないためDeployment policyはDisable redeployとした。
必要がある場合はnexusの画面上からパッケージを削除することとする。

## maven-snapshots
自社ライブラリのsnapshotバージョンをデプロイするhostedレポジトリ。
Version policyをSnapshotにすることで、releaseバージョンをデプロイできないように設定した。
こちらは何度も再デプロイするのでDeployment policyはAllow redeployとした。

## maven-repos
パッケージのダウンロード先となるgroupレポジトリ。
maven-central、maven-releases、maven-snapshotsをメンバーとした。
こうすることで以下を全て取得することができる。

* サードパーティライブラリ
* 自社ライブラリのsnapshotバージョン
* 自社ライブラリのreleaseバージョン

今後、例えばjbossレポジトリのパッケージを使用するということがあれば、
proxyレポジトリを追加してmaven-reposに登録するだけでpom.xmlの修正は不要となる。
また、snapshotが肥大化した場合はsnapshotレポジトリを削除して再作成すればsnapshotのみ削除可能。

# アカウント設定
mavenへのデプロイだけができる「maven-admin」アカウントを作成し以下の権限を持つロールを付与した。
(名前はmaven-deployとかに変えるかも)

* nx-repository-view-maven2-maven-release-*
* nx-repository-view-maven2-maven-snapshot-*

nx-repository-admin-*-*-*はレポジトリ自体を作成したり設定したりするための権限なので、
こちらを付与してもデプロイすることはできない。
https://stackoverflow.com/questions/40966763/what-are-the-minimal-set-of-privileges-required-to-deploy-artifacts-to-nexus-3

# 既存パッケージの移設
全てのjar/pomをダウンロードしたうえで、maven-deploy-pluginの機能で移設する。

## jarとpomがセットである場合
```shell
mvn deploy:deploy-file -Dfile=<アップロードするjarのパス> -Durl=<アップロード先mavenレポジトリのURL> -DrepositoryId=<アップロード先レポジトリのID> -DpomFile=<アップロードするjarに対応するpomのパス>
```

## pomのみがある場合
```shell
mvn deploy:deploy-file -Dfile=<アップロードするpomのパス> -Durl=<アップロード先mavenレポジトリのURL> -DrepositoryId=<アップロード先レポジトリのID> -DgroupId=<アップロードするpomのgroupId> -DartifactId=<アップロードするpomのartifactId> -Dversion=<アップロードするpomのversion>
```
pomもアップロードすることができるが、groupId、artifactId、versionを個別に指定してあげる必要があり、
pomFileでアップロードするpomを指定してもfileパラメータがjarとして判定されてしまうためエラーとなる。
参考URL: https://stackoverflow.com/questions/6137441/how-can-i-deploy-only-the-pom-file-to-my-snapshot-repository-in-maven?answertab=votes#tab-top


# Tips
## デプロイ時にアカウント認証を通す
$HOME/.m2/settings.xmlに以下の内容を記載する。

```xml
<settings>
  <servers>
    <server>
      <id>${snapshotレポジトリのID}</id>
      <username>${ログインユーザー}</username>
      <password>${ログインユーザーのパスワード}</password>
    </server>
    <server>
      <id>${releaseレポジトリのID}</id>
      <username>${ログインユーザー}</username>
      <password>${ログインユーザーのパスワード}</password>
    </server>
  </servers>
</settings>
```

レポジトリのIDはpom.xmlのdistributionManagementに記載しているレポジトリのIDと対応する。

```xml
  <distributionManagement>
    <snapshotRepository>
      <id>${snapshotレポジトリのID}</id>
      <url>${snapshotレポジトリのURL}</url>
    </snapshotRepository>
    <repository>
      <id>${releaseレポジトリのID}</id>
      <url>${releaseレポジトリのURL}</url>
    </repository>
  </distributionManagement>
```
なお、snapshotレポジトリを分けないのであれば、snapshotRepositoryタグを省けばよい。

## ssl証明書をjavaに登録する
powershellでの作業例

```powershell
keytool.exe "-J-Djava.net.useSystemProxies=true" -printcert -rfc -sslserver <nexusのホスト名>:443  | Out-File -FilePath cert.pem -Encoding ASCII
keytool.exe -importcert -file cert.pem -alias nexus -storepass changeit -keystore '<JAVA_HOME>\jre\lib\security\cacerts'
```
[参考URL](https://blog.jdriven.com/2017/10/maven-connect-nexus-https/)

## mavenのローカルキャッシュを削除してパッケージする
```shell
mvn dependency:purge-local-repository clean package
```
[参考URL](https://community.atlassian.com/t5/Bamboo-questions/How-do-we-purge-clean-the-Maven-repositories/qaq-p/411756)

# 参考リンク
http://codeheaven.io/using-nexus-3-as-your-repository-part-1-maven-artifacts/

# こちらにも公開してます
http://melvins-nest.com/dev/2018/08/26/maven%E3%83%AC%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92nexus%E3%81%AB%E7%A7%BB%E8%A8%AD%E3%81%99%E3%82%8B%E3%83%A1%E3%83%A2nexus%E3%81%AE%E3%83%AC%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E6%A7%8B/