GitHub Packages を使いたい

## はじめに

私は [OpenAM コンソーシアム版 OpenAM](https://github.com/openam-jp/openam) を開発していますが、残念ながら現状は OpenAM のコード単体ではビルドできない状態になっています。

```
$ git clone https://github.com/openam-jp/openam.git
$ cd openam
$ mvn clean install
[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM for jp.openam:openam:14.0.0-SNAPSHOT: Could not find artifact jp.openam:forgerock-parent:pom:2.0.7-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 53, column 13
 @ 
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project jp.openam:openam:14.0.0-SNAPSHOT (/home/builduser/source/openam/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for jp.openam:openam:14.0.0-SNAPSHOT: Could not find artifact jp.openam:forgerock-parent:pom:2.0.7-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 53, column 13 -> [Help 2]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
```

OpenAM のビルドには依存している forgerock-XXX 系のライブラリや OpenDJ のライブラリが必要なのです。これらのライブラリ等についても OpenAM コンソーシアムでフォークしていますが、Maven リポジトリで配布していません。そのため、OpenAM のビルドには forgerock-XXX/opendj-XXX を含めたすべての関連コードのビルドが必要です…

というわけで、Maven リポジトリの確保は課題の一つです。そんな中、最近 `GitHub Packages` というパッケージレジストリのサービスが正式にローンチされたようです。Maven リポジトリとしても使えるようなので、実際につかってみることにします。

## GitHub でアクセストークンを取得する

GitHub でリポジトリのページを開き、`commits`、`branches` と並んでいる `packages` をクリックすると、次のコマンドが提示されます。

```
<!-- Just a single step: Deploy using a GitHub token -->
$ mvn deploy -Dregistry=https://maven.pkg.github.com/openam-jp -Dtoken=GH_TOKEN
```

`GH_TOKEN` には GitHub のアクセストークンを指定するようです。
アクセストークンは https://github.com/settings/tokens で発行できます。今回は GitHub Packages 用の以下の scope を有効にしてみました。

| scope | 説明 |
| :-- | :-- |
| write:packages | Upload packages to github package registry |
| read:packages | Download packages from github package registry |
| delete:packages | Delete packages from github package registry |

## リポジトリのフォーク

現段階では OpenAM コンソーシアムの GitHub Packages を直接操作するわけにはいかないので、自分のリポジトリにフォークしておきます。
URL は `https://maven.pkg.github.com/openam-jp` から `https://maven.pkg.github.com/tsujiguchitky` に変わります。


## ソースコードのバージョンから SNAPSHOT を消す

GitHub Packages は SNAPSHOT バージョンに対応していません。

```
Note: GitHub Packages does not support SNAPSHOT versions of Apache Maven. 
Make sure you disable SNAPHOT in your ~/.m2/settings.xml file.
```
この記事を書いている時点(12/20)では OpenAM コンソーシアムの各リポジトリは SNAPSHOT バージョンになっているのでソースコードを調整しておきます。

```
diff --git a/pom.xml b/pom.xml
index 5fd640e..0b6080b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>jp.openam</groupId>
     <artifactId>forgerock-parent</artifactId>
-    <version>2.0.7-SNAPSHOT</version>
+    <version>2.0.7</version>
     <packaging>pom</packaging>
     <name>ForgeRock Parent</name>
     <description>Parent POM for ForgeRock projects. Provides default project build configuration.</description>
```

## デプロイ

OpenAM を除く以下のリポジトリに対して `mvn deploy` を実行します。

* forgerock-parent
* forgerock-bom
* forgerock-build-tools
* forgerock-i18n-framework
* forgerock-guice
* forgerock-guava
* forgerock-ui
* forgerock-commons
* forgerock-persistit
* forgerock-bloomfilter
* opendj-sdk
* opendj

しかし...

```
$ mvn deploy -Dregistry=https://maven.pkg.github.com/tsujiguchitky -Dtoken=XXX
...
[INFO] --- maven-deploy-plugin:2.8.2:deploy (default-deploy) @ forgerock-parent ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:23 min
[INFO] Finished at: 2019-12-20T06:03:31+00:00
[INFO] Final Memory: 17M/370M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy (default-deploy) on project forgerock-parent: Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
```

GitHub のページで指定されたコマンドを実行してもうまくいきません。そもそも `registry` や `token` というオプションはこれまで見たことないのですが...

## Maven の設定ファイル(~/.m2/settings.xml)の準備

困ったので GitHub の公式ドキュメントをのぞいてみます。[Configuring Apache Maven for use with GitHub Packages](https://help.github.com/ja/github/managing-packages-with-github-packages/configuring-apache-maven-for-use-with-github-packages) によると GitHub パッケージレジストリへの認証のために settings.xml を作成する手順になっています。

ということで `~/.m2/settings.xml` を用意します。まずは認証に必要な情報だけ記載しています。

```
<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>USERNAME</username>
      <password>TOKEN</password>
    </server>
  </servers>
</settings>
```



## デプロイ (リベンジ)

`registry` や `token` というオプションを排除して、`altDeploymentRepository` を指定します。値は `id::layout::url` というフォーマットで指定します。`id` は settings.xml の認証情報に一致する `id`、`url` は `https://maven.pkg.github.com/OWNER/REPOSITORY` で指定します。layout は何なんでしょう、とりあえず `default` としました。

```
$ mvn deploy -DaltDeploymentRepository=github::default::https://maven.pkg.github.com/tsujiguchitky/forgerock-parent
...
[INFO] --- maven-deploy-plugin:2.8.2:deploy (default-deploy) @ forgerock-parent ---
[INFO] Using alternate deployment repository github::default::https://maven.pkg.github.com/tsujiguchitky/forgerock-parent
Uploading: https://maven.pkg.github.com/tsujiguchitky/forgerock-parent/jp/openam/forgerock-parent/2.0.7/forgerock-parent-2.0.7.pom
Uploaded: https://maven.pkg.github.com/tsujiguchitky/forgerock-parent/jp/openam/forgerock-parent/2.0.7/forgerock-parent-2.0.7.pom (59 KB at 26.8 KB/sec)
Downloading: https://maven.pkg.github.com/tsujiguchitky/forgerock-parent/jp/openam/forgerock-parent/maven-metadata.xml
Uploading: https://maven.pkg.github.com/tsujiguchitky/forgerock-parent/jp/openam/forgerock-parent/maven-metadata.xml
Uploaded: https://maven.pkg.github.com/tsujiguchitky/forgerock-parent/jp/openam/forgerock-parent/maven-metadata.xml (305 B at 0.4 KB/sec)
Uploading: https://maven.pkg.github.com/tsujiguchitky/forgerock-parent/jp/openam/forgerock-parent/2.0.7/forgerock-parent-2.0.7-site.xml
Uploaded: https://maven.pkg.github.com/tsujiguchitky/forgerock-parent/jp/openam/forgerock-parent/2.0.7/forgerock-parent-2.0.7-site.xml (2 KB at 1.4 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.676 s
[INFO] Finished at: 2019-12-20T06:31:46+00:00
[INFO] Final Memory: 16M/359M
[INFO] ------------------------------------------------------------------------
```

おお、成功した...

成功したリポジトリの GitHub Package を確認すると、確かに表示されています。

![parent-package.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316122/38b88156-a1f6-7e35-ef7f-4e27effdcf35.png)


つづけてほかのリポジトリについてもデプロイを続けます...

## Maven キャッシュを削除する

デプロイ作業で Maven キャッシュが作成されてしまいました。このままでは動作確認ができないので、関連するキャッシュを削除しておきます。

```
$ rm -rf ~/.m2/repository/jp/openam
```

## Maven の設定ファイル(~/.m2/settings.xml)の更新

GitHub Packages を利用するには設定ファイルでリポジトリを指定する必要があります。[GitHub のドキュメント](https://help.github.com/ja/github/managing-packages-with-github-packages/configuring-apache-maven-for-use-with-github-packages)のように GitHub レジストリを指定します。

```
<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">

  <activeProfiles>
    <activeProfile>github-packages</activeProfile>
  </activeProfiles>

  <profiles>
    <profile>
      <id>github-packages</id>
      <repositories>
        <repository>
          <id>central</id>
          <url>https://repo1.maven.org/maven2</url>
          <releases><enabled>true</enabled></releases>
          <snapshots><enabled>false</enabled></snapshots>
        </repository>
        <repository>
          <id>github</id>
          <name>GitHub Packages</name>
          <url>https://maven.pkg.github.com/tsujiguchitky/forgerock-parent</url>
        </repository>
        <repository>
          <id>oracle-repository</id>
          <name>Oracle Repository</name>
          <url>http://download.oracle.com/maven</url>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
        <repository>
          <id>restlet-repository</id>
          <name>Restlet Repository</name>
          <url>http://maven.restlet.com</url>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>github</id>
          <name>GitHub Packages</name>
          <url>https://maven.pkg.github.com/tsujiguchitky/forgerock-parent</url>
        </pluginRepository>
      </pluginRepositories>
    </profile>
  </profiles>

  <servers>
    <server>
      <id>github</id>
      <username>USERNAME</username>
      <password>TOKEN</password>
    </server>
  </servers>
</settings>
```

`repository` は GitHub のリポジトリ毎に用意する必要があるのかと思っていましたが、いずれか一つで問題無いようです。
それと、プラグインも GitHub レジストリにデプロイしているため、`pluginRepository` も指定する必要があります。

`github-packages` プロファイルが有効だと pom.xml などで設定した repository が有効にならないようです。`central` のほかにも OpenAM の pom.xml で指定している `oracle-repository`、`restlet-repository` も記載しておく必要があります。

## OpenAM を GitHub Packages を使ってビルドする

結論から言ってしまうと、GitHub Packages を使っても OpenAM だけではビルドできませんでした。JavaScript を Maven で扱うために Maven ローカルリポジトリにインストールする仕組みを forgerock-ui/forgerock-ui-external-libs に作ってしまったため、これもビルドする必要があります（いずれ修正しよう...）。

```
$ mvn clean install -f forgerock-ui/forgerock-ui-external-libs
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:24 min
[INFO] Finished at: 2019-12-20T09:13:26+00:00
[INFO] Final Memory: 15M/374M
[INFO] ------------------------------------------------------------------------
$ mvn clean install -f openam
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10:05 min
[INFO] Finished at: 2019-12-20T09:48:05+00:00
[INFO] Final Memory: 354M/2979M
[INFO] ------------------------------------------------------------------------
$ ls -l openam/openam-server/target/*.war
-rw-rw-r--. 1 builduser builduser 115615769 Dec 20 09:46 openam/openam-server/target/OpenAM-14.0.0.war
```

できたぞー。

## その他

* 費用ですが、公開パッケージについては無料のようです
* ただし、公開パッケージは削除できません
* (公開パッケージだから???)デプロイ時もビルド時も、たまに 502 Bad Gateway で失敗することがあります… コマンドをやり直しましょう…

## まとめ

GitHub Packages を紹介しました。公開パッケージであってもダウンロードに GitHub のアクセストークンが必要なのがちょっと辛いところですが、簡単にMaven リポジトリを作成することができます。もし、Maven リポジトリを簡単に立てたいと考えている方は使ってみてはいかがでしょうか。