CircleCIでMavenプロジェクトのCI

以下の記事の続きで、今回はCircleCIを使ってみます。
https://qiita.com/kasa_le/items/1b97b0d36c81785522a8

# CircleCI
こちらから登録できます。
GithubかBitbucketと連携する方法しかないので、それ以外のリポジトリの方は諦めてください(笑)
https://circleci.com/

## 特徴
テンプレートが豊富だったり、Orbというジョブをまとめたライブラリ的なものを配れたりと、メジャーどころのビルド環境については整っている感じです。.NET、Androidなどもビルドできます。

Githubへの接続は、**Authorized OAuth Apps**として行われます。
Githubのアカウントの[Settings]-[Applications]-[Authorized OAuth Apps]に登録されます。(内部的には、SSHキーでの接続のようです。)

キャッシュ機能にも対応しています。

OSイメージはLinux, Windows, macOSとサポートしていますが、Dockerイメージを各種引っ張ってくることができ、今回はこれで助かりました。

## 料金
フリープランは個人の趣味使用には十分耐えられると思いますが、OSイメージはLinuxかWindowsしか対応していないので要注意です。
それ以外は月額課金となります。

https://circleci.com/ja/pricing/
プラン間の金額差が大きいように見えますが、下の方を見ていくと、チームメンバー数や利用量に応じての課金制(月額)になっています。

CIの稼働が安定的なプロジェクトなら、見積もりやすいと思います。逆に、一定時期だけ保守開発してたくさん回るけど、それ以外の運用中はあまり回らないようなプロジェクトの場合、何もしなくても最低月額はかかるので、そのあたりを見極めて使いたいところですね。

それと、OSSの場合、

>毎月 400,000 クレジットを無料プランのお客様に提供します

とのことですが、(https://circleci.com/ja/pricing/ のよくある質問より)Linuxしか使えないようなので、注意が必要です。

また、エンタープライズ向け(要問い合わせ)には、オンプレミス版も提供されています。
https://circleci.com/ja/enterprise/

## 実績
結構老舗というイメージです。
そのため、現在はVersion2.1ぽいのですが、検索するとまだまだ古い頃の情報が多数引っかかり、今のバージョンでの情報にたどり着くのが少々大変でした。

また、WebサイトのUIを変更中のようで、新しいUIと古いUIがぐちゃぐちゃに遷移するため、「あの画面にはどうやって戻るんだろう？」とかなり迷います。
４月１５日以降、古い画面は見られなくなると言っているので、そのあとには落ち着くかもしれません。

ステータスバッジなどをつける際のマークダウンの情報は、古いUIだと自分のプロジェクト、ブランチ名などを設定してコピペすれば良いようなページを提供してくれているのですが、新しいUIではそのページが無くなっていて、汎用的な説明ページでサンプルが載っているだけなので、少し不便になります。

あと、手動でワークフローをを実行することが出来ません。
(実行済みを[Rerun]することは出来ますが)

## 設定

`yml`ファイルのみで行います。
プロジェクトのルート直下に、`.circleci`というディレクトリを作成し、その下に`config.yml`を配置します。

最終的に、ビルドとテストが上手くいった設定はこちらになります。

```.circleci/config.yml
version: 2.1

jobs:
  build:
    docker:
      - image: 'cimg/openjdk:11.0.6'
    steps:
      - checkout
      - run: 
          name: Build and test
          command: mvn clean install 
      - store_artifacts:
          path: repository/target/repository.jar
      - store_artifacts:
          path: serverapi/target/serverapi.war
      - run:
          name: Save test results
          command: |
            mkdir -p ~/test-results/junit/
            find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/test-results/junit/ \;
          when: always
      - store_test_results:
          path: ~/test-results
      - store_artifacts:
          path: ~/test-results/junit

workflows:
  version: 2
  maven_test:
    jobs:
      - build:
            filters:
              branches:
                  only: feature/for_circleci
```

最初のテンプレートで`Java(Maven)`を選ぶと、Orbを使ったものを作成してくれるのですが、このイメージだとサブモジュール`repository`の`jar`がないと言われ、それに依存するサブモジュールのビルドが失敗してしまいました。

Orbに対して、Executorのｃ`tag`でJDKのバージョンを指定できそうだったので試行錯誤したのですが、私の`yml`の理解が足りないせいか、うまく渡せませんでした。

そこで、Orbのソースコードを参考に、上記のようにDockerイメージを使うことで、OpenJDKの11(LTS版)の最新版でビルドできるようになり、成功するようになりました。

Maven Orbのページ
https://circleci.com/orbs/registry/orb/circleci/maven

※もっとも、その後、`jar`と`war`のファイル名についてはMavenプロジェクト側の`pom.xml`に問題があって直したので、もしかしたらその版だとデフォルトのままで動いたかもしれません。
※そしてそれば、JDKの問題というより、もしかしたらMavenのバージョンの問題かも?

一応ステップを解説すると、次のようになります。

### ジョブ`build`

- `docker`セクション
  - `https://hub.docker.com/r/`から落としてくるイメージのパスを指定
- `steps`セクション
  - `checkout`
      - 対象ブランチをチェックアウト
  - `Build and test`
      - `mvn clean install`コマンドを実行
  - `store_artifacts`
      - `repository.jar`と`serverapi.war`をアーティファクトとして保存(※)
  - `Save test results`
      - 各モジュールのsurefireのテストレポートを一つのディレクトリにコピー(※)
  - `store_test_results`
      - テスト結果をアーカイブ
  - `store_artifacts`
      - テスト結果をアーティファクトとして保存 

### ワークフロー

`build`ジョブに対し、ブランチを`festure/for_circleci`に限定するフィルタ設定をしています。

## 感想

ステップ解説のところの(※)の部分ですが、なんと、ワイルドカードや正規表現によるパス指定に対応してくれていません！

これは非常にやっかいですね・・・

たとえば、Mavenのpomで`<build><fileName>`タグで生成物のファイル名を指定出来ますが、この指定は任意なんですね。指定が無い場合、デフォルトでは

`repository-1.1-SNAPSHOP.jar`

みたいな名前がつけられます。バージョンが付くんです。こちらのほうがわかりやすいのですが、これにしていると、`yml`のアーティファクトファイル名を、バージョンを上げると後に書き換えなければならず、とても不便です。

なので今回、このプロジェクトでは、`<build><fileName>`タグで`repository.jar`と固定することでその問題を解決するようにしましたが、これはこれで生成物のダウンロード後にバージョンが分かりづらくなり苦労するかもしれません。