MavenでGitHub PackagesへJARをデプロイする

[同じ内容をZennにも投稿しました。](https://zenn.dev/backpaper0/articles/deploy-jar-to-gh-packages-by-maven)

---

## 概要

GitHub PackagesへJARをデプロイする方法を書きます。

基本的なことは次の公式ドキュメントに書かれています。

- [GitHub Packagesで利用するために Apache Maven を設定する](https://docs.github.com/ja/free-pro-team@latest/packages/using-github-packages-with-your-projects-ecosystem/configuring-apache-maven-for-use-with-github-packages)

公式ドキュメントの内容と重なる部分もありますが、ローカルから手動でJARをデプロイする方法とデプロイしたJARを使う方法、それからGitHub Actionsでデプロイする方法を書きます。

## とりあえずローカルから手動でデプロイする

手順は次の通りです。

1. Personal access tokenを作る
2. `~/.m2/settings.xml`へデプロイ先となるMavenリポジトリの認証情報を書く
3. `pom.xml`へデプロイ先となるMavenリポジトリ情報を書く
4. デプロイする

### 1. Personal access tokenを作る

https://github.com/settings/tokens からPersonal access tokenを作ります。
デプロイしたいので、`write:packages`スコープにチェックしてください。

### 2. `~/.m2/settings.xml`へデプロイ先となるMavenリポジトリの認証情報を書く

`username`要素にはGitHubのアカウント名を、`password`要素には先ほど作ったPersonal access tokenを記載します（ここではユーザー名は`backpaper0`とします）。

```xml
<server>
    <id>github</id>
    <username>backpaper0</username>
    <password>※ここにPersonal access tokenを書く</password>
</server>
```

`~/.m2/settings.xml`が無い場合は作成してください。
Mavenの`conf`ディレクトリにあるものをコピーすると良いです。
Mavenのホームディレクトリは`mvn --version`すればわかります（どこにあるかわかっていなかった、、、）。

また、Personal access tokenを平文で書きたくない場合は`mvn -ep`で暗号化できます。
詳しくは[Maven – Password Encryption](https://maven.apache.org/guides/mini/guide-encryption.html)を参照ください。

### 3. `pom.xml`へデプロイ先となるMavenリポジトリ情報を書く

MavenリポジトリのURLはユーザー名、Gitリポジトリ名によって変わります。
ここではユーザー名は`backpaper0`、Gitリポジトリ名は`demo`とします（GitHubには`demo`というGitリポジトリを作成していることとします）。

```xml
<distributionManagement>
    <repository>
        <id>github</id>
        <name>GitHub OWNER Apache Maven Packages</name>
        <url>https://maven.pkg.github.com/backpaper0/demo</url>
    </repository>
</distributionManagement>
```

### 4. デプロイする

`mvn`コマンドでデプロイできます。

```bash
mvn deploy
```

### ソースコードとJavadocもデプロイする

ちなみに、`pom.xml`に次のように`maven-source-plugin`と`maven-javadoc-plugin`の設定をすればソースコードのJARとJavadocのJARもデプロイできます。

```xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
```

## デプロイしたJARを使用する

手順は次の通りです。

1. `pom.xml`へMavenリポジトリ情報を書く
2. `dependency`を追加する

ちなみに、認証は必要なのでPersonal access tokenと`~/.m2/settings.xml`の準備をしていない場合はしておいてください。
なお、デプロイするのではなく参照するだけならPersonal access tokenのスコープは`read:packages`で大丈夫です。

### 1. `pom.xml`へMavenリポジトリ情報を書く

Mavenリポジトリの情報はデプロイの際に書いたものと同じです。
`SNAPSHOT`バージョンも使用する場合は`snapshots`要素内の`enabled`要素へ`true`を書いておきましょう。

```xml
<repositories>
    <repository>
        <id>github</id>
        <name>GitHub OWNER Apache Maven Packages</name>
        <url>https://maven.pkg.github.com/backpaper0/demo</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>
```

### 2. `dependency`を追加する

あとは`pom.xml`へデプロイしたJARの情報を書いた`dependency`要素を追加すると使えます。

```xml
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>demo</artifactId>
        <version>0.1-SNAPSHOT</version>
    </dependency>
</dependencies>
```

## GitHub Actionsでデプロイする

手順は次の通りです。

1. 専用の`settings.xml`を用意する
2. ワークフローのYAMLを書く

### 1. 専用の`settings.xml`を用意する

GitHub Actionsでデプロイする場合、ローカルの`~/.m2/settings.xml`は使えないため`settings.xml`もGitリポジトリへ追加します。

Personal access tokenを書くわけにはいかないので、環境変数から読み取るようにします。
ここでは環境変数`GITHUB_TOKEN`とします。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>github</id>
            <username>backpaper0</username>
            <password>${env.GITHUB_TOKEN}</password>
        </server>
    </servers>
</settings>
```

### 2. ワークフローのYAMLを書く

GitHub Actionsで次のコマンドを実行するとデプロイできます。

```bash
GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} mvn -B -s settings.xml deploy
```

ポイントは次の通りです。

- Personal access tokenを`secrets`コンテキストから読み取って環境変数`GITHUB_TOKEN`へセットする（`settings.xml`へ渡すため）
- `-s`でGitリポジトリへ追加した`settings.xml`を使用する

`secrets.GITHUB_TOKEN`について詳しくは[ワークフローで認証する](https://docs.github.com/ja/free-pro-team@latest/actions/reference/authentication-in-a-workflow)を参照してください。

YAMLファイル全体は次のようになります。

```yaml
name: Java CI with Maven

on:
  push:
    branches: [ master ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 11

      - name: Cache local Maven repository
        uses: actions/cache@v2
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
            ${{ runner.os }}-maven-

      - name: Release Maven package
        run: GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} mvn -B -s settings.xml deploy
```

以上です。