Publish to Maven Central via Maven

# Overview

この記事では、GitHubのリポジトリで管理しているJavaソースコードを、Maven Centralを使ってjarファイルのパッケージとして公開する手順を紹介します。
これを行うことで、全世界の人が、IDやパスワードによる認証無しで、無償で利用できるようになります。

ただし、一度公開したライブラリは削除できません。

詳しい説明はこちらのページを参照してください。

https://central.sonatype.org/register/central-portal/

# Maven Central and OSSRH

自分のライブラリを無償で公開できるリポジトリには、Maven CentralとOSSRHがあります。
Maven CentralはOSSRHの次世代バージョンで、OSSRHよりも簡単にライブラリを公開できます。
ここでは、Maven Centralを使う例を示します。

https://central.sonatype.com

# Go to Maven Central

Maven Centralは、GitHubのアカウントを使ってログインできます。
GitHubアカウントでログインすると、namespaceが自動で取得できるメリットがあります。こうすることで、groupIDとして利用できるnamespaceの検証を省略できるので楽です。

```
<groupId>com.example.applications</groupId>　←ここの話
<artifactId>example-application</artifactId>
<version>1.4.7</version>
```

GitHubの場合、このようなnamespaceになります。

io.github.myusername

自分のnamespaceを確認するためには、GitHubアカウントでログインした後、右上のユーザーアカウントメニューから「View Namespaces」を選択すると、namespaceが表示されます。新しく作ることもできますが、認証処理が必要です。

# GPG

公開するパッケージを暗号化するために、GnuPG（https//www.gnupg.org/download/）を使ってパブリックキーを生成します。

手順は簡単で、次のようにコマンドして、説明のとおり進んでいくだけです。

```
gpg --gen-key
```

実行後、e-mailとパスフレーズを入力します。

```
$ gpg --gen-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Central Repo Test
Email address: central@example.com
You selected this USER-ID:
    "Central Repo Test <central@example.com>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 8190C4130ABA0F98 marked as ultimately trusted
gpg: revocation certificate stored as
'/home/mylocaluser/.gnupg/openpgp-revocs.d/CA925CD6C9E8D064FF05B4728190C4130ABA0F98.rev'
public and secret key created and signed.

pub   rsa3072 2021-06-23 [SC] [expires: 2023-06-23]
      CA925CD6C9E8D064FF05B4728190C4130ABA0F98
uid                      Central Repo Test <central@example.com>
sub   rsa3072 2021-06-23 [E] [expires: 2023-06-23]
```

この例では、パブリックキーは、「CA925CD6C9E8D064FF05B4728190C4130ABA0F98」です。
生成できたら、パブリックキーと、途中で入力した自分のメールとパスフレーズをメモしておきます。

そして、キーサーバーへ公開鍵を送信します。
```
gpg --keyserver keyserver.ubuntu.com --send-keys CA925CD6C9E8D064FF05B4728190C4130ABA0F98
```

# Maven Centralへ公開するための認証IDとパスワード（User Token）

自分のjarファイルをCentralへアップロードするために、Central Portalで認証情報（User Token）を取得しておきます。
Central Portal右上のユーザーアカウントメニューの「View Account」から「Generate User Token」でUser Tokenを生成します。usernameとpasswordが表示されるので控えておきます。

Regenerateで更新した場合、その都度、自分のローカル（settings.xml後述）にも反映しなければなりません。

# Maven pom.xml

## 必要な属性情報を記入する

### Project Name, Description and URL

シンプルプロジェクトで作成すると忘れがちですが、これらの情報を自分のプロジェクトに合わせて記載します。
```
<name>Example Application</name>
<description>A application used as an example on how to set up pushing
  its components to the Central Repository.</description>
<url>http://www.example.com/example-application</url>
```

### License Information

ライセンス情報も明記します。
```
<licenses>
  <license>
    <name>The Apache License, Version 2.0</name>
    <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
  </license>
</licenses>
```

### Developer Information

開発者情報も明記します。
```
 <developers>
    <developer>
      <name>Manfred Moser</name>
      <email>manfred@sonatype.com</email>
      <organization>Sonatype</organization>
      <organizationUrl>http://www.sonatype.com</organizationUrl>
    </developer>
</developers>
```

### SCM Information

source control systemのための情報を記載します。
ホストしているものによって変わりますが、GitHubではこのような感じになります。
```
<scm>
  <connection>scm:git:git://github.com/simpligility/ossrh-demo.git</connection>
  <developerConnection>scm:git:ssh://github.com:simpligility/ossrh-demo.git</developerConnection>
  <url>http://github.com/simpligility/ossrh-demo/tree/master</url>
</scm>
```
## プラグイン追加

pom.xmlに、buildのためのプラグインを追加します。

### central-publishing-maven-plugin

centralへpublishするためのプラグインです。

```
<build>
    <plugins>
        <plugin>
          <groupId>org.sonatype.central</groupId>
          <artifactId>central-publishing-maven-plugin</artifactId>
          <version>0.3.0</version>
          <extensions>true</extensions>
          <configuration>
            <publishingServerId>central</publishingServerId>
            <tokenAuth>true</tokenAuth>
          </configuration>
        </plugin>
    <plugins>
</build>
```

### maven-source-plugin

ソースコードを含めるためのプラグインです。centralへpublishするためには、ソースコードを含める必要があります。
```
<plugin>
    <artifactId>maven-source-plugin</artifactId>
	<version>3.3.0</version>
	<executions>
    	<execution>
    		<id>attach-sources</id>
			<phase>package</phase>
			<goals><goal>jar</goal></goals> 
		</execution>
	</executions>
</plugin>
```

### maven-javadoc-plugin

javadocを含めるためのプラグインです。centralへpublishするためには、javadocを含める必要があります。
```
<plugin>
    <artifactId>maven-javadoc-plugin</artifactId>
	<version>3.3.0</version>
	<configuration>
        <additionalOptions>
        	<!-- skip strict check java doc-->
            <additionalOption>-Xdoclint:none</additionalOption>
        </additionalOptions>
    </configuration>
	<executions> 
		<execution> 
		    <id>attach-javadocs</id>
		    <phase>package</phase>
		    <goals><goal>jar</goal></goals> 
		</execution> 
	</executions> 
</plugin>
```

### maven-gpg-plugin

deploy時に作成されたjar, source, javadoc, pomを暗号化するためのプラグインです。

```
<!-- gpg sign -->
<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>
    			<keyname><!-- your gpg public key --></keyname>
    			<passphraseServerId><!-- your gpg public key --></passphraseServerId>
			</configuration>
		</execution>
	</executions>
</plugin>
```

distributionManagementタグは不要です。

# settings.xml

これはMavenのユーザー情報を記録するためのXMLです。非公開情報を管理します。
リポジトリにはアップロードしない、秘匿性の高いファイルです。
*/user/.m2/settings.xmlに作成します（ない場合は）。

```
<settings>
  <servers>
    <server>
      <id>central</id>
      <username><!-- your token username --></username>
      <password><!-- your token password --></password>
    </server>
  </servers>
  <profiles>
	  <profile>
		<id>central</id>
			<activation>
		   		<activeByDefault>true</activeByDefault>
			</activation>
			<properties>
		   		<gpg.executable>gpg</gpg.executable>
		   		<gpg.passphrase><!-- your gpg passphrase --></gpg.passphrase>
			</properties>
	  </profile>
  </profiles>
</settings>
```

# deploy

gitプロジェクトフォルダへ移動して、mvn clean deployコマンドを実行します。
実行後、自動的にCentral PortalのDeploymentsページに反映されます。

# After deploy

Central PortalのDeploymentsページを確認して、よければPublishします。Publish後は削除できません。Publish前にDropした場合は、取り消せます。
すでに同じバージョンのパッケージをPublishしようとすると、Already existsエラーによりdeployが失敗します。

# Central Portal以外の方法

GitHub Packagesを使ってホストされているライブラリもまた、mavenプロジェクトへインストールできます。ただし、このライブラリを他者と共有したいときは、読み込みのみ可能なUserTokenを作成・共有して、その他の利用者にsettings.xmlを編集してもう必要があります。
(自分のライブラリを使う際は、pomのrepositoryタグに自分のリポジトリを追加する必要あり)

https://docs.github.com/ja/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry