CircleCIで計測したカバレッジ変化をSlackに晒す


しばらく前に CI ツールを Jenkins から CircleCI にスイッチしたのですが、

[Jenkinsで収集したカバレッジの変化情報をSlackに投稿する](http://qiita.com/u-minor/items/e0e30655168dadf2b10e)

でやっていた Slack への通知ができなくなったことで「テストを書く」という意識が少々低下した感じがしたので、同様の内容を CircleCI で実装しました。

~~晒す~~可視化するのはけっこう大事。

![Slack.png](https://qiita-image-store.s3.amazonaws.com/0/15611/4c2f9fa9-e407-395e-092c-de7af2ecadf8.png "Slack.png")

artifacts に保存しているカバレッジ情報の XML を元に比較を行い、変化を通知します。
ブランチが複数ある場合は、そのブランチの1つ前のビルド（直前とは限らない）を優先して比較するようにしています。
ブランチの初回ビルドの場合や1つ前のビルドの artifacts にカバレッジ情報が見つからなかった場合は、ビルド番号を1つづつ減らして過去に遡ります（最大5回）。

メッセージ内のリンクは次の通りです。

- プロジェクト名: CircleCI のプロジェクトトップへのリンク
- ビルド番号: 該当ビルドへのリンク
- Commit ID: github の該当 commit へのリンク

対応しているカバレッジ情報 XML のフォーマットは、cobertura, jacoco です。

> JS 系では、jscoverage や istanbul 等が cobertura 形式をサポートしています。
> Java や Scala は jacoco を使います。

# 前提条件

既に CircleCI 上でカバレッジ情報を計測、artifacts に XML が登録されていることとします。

# 設定手順

## Slack の Webhook URL の取得

既に CircleCI の Integration を追加している前提です。
まだ未設定であれば、通常の連携設定を先に行っておいてください。

まず、 Slack の Apps & Custom Integration から Installed Apps に移動し、「Circle CI」を選択します。

![Configure_Apps___Sprocket_Slack.png](https://qiita-image-store.s3.amazonaws.com/0/15611/49443021-99dc-03dc-fa4a-207c4888d04f.png "Configure_Apps___Sprocket_Slack.png")

CircleCI の App 詳細画面がでるので、設定済みの configuration の編集ボタンを押します。

![Configure_Circle_CI___Sprocket_Slack.png](https://qiita-image-store.s3.amazonaws.com/0/15611/69937402-4f35-e385-4101-9d0f1661e877.png "Configure_Circle_CI___Sprocket_Slack.png")

すると、詳細設定が表示されますので、Webhook URL をコピーしておきます。

![Circle_CI___Sprocket_Slack.png](https://qiita-image-store.s3.amazonaws.com/0/15611/65b485ed-a67b-defa-3da9-f05f3351f043.png "Circle_CI___Sprocket_Slack.png")

## CircleCI の設定

### API Permissions の設定

前回のビルド情報の取得に CircleCI の API を利用しているので、その API 用のトークンを生成します。

自分が所有するリポジトリ（github のリポジトリの前半が自分のユーザ名）の場合は、ビルド時のコンテナ内からそのまま CircleCI の API をコールできるのですが、チーム用のリポジトリの場合は API アクセスにトークンが必要になります。

> 自分が所有するリポジトリの場合は、この設定は必要ありませんのでスキップしてください。

Project Settings -> API Permissions に移動し、Add API Token で API Token を追加します。
API トークンの種別は `Build Artifacts` を選択、Label は適当に付けてトークンを生成します。

![2020-09-22 19-46-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/a19a5dfd-13ff-a948-26ff-e0cbc3e79863.png)

トークンが生成されたら、コピーしておきます。

![2020-09-22 19-49-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/1585fb97-46c8-19fc-d3eb-f022bbcd19e1.png)

### Contexts の設定

Slack の Endpoint 等、複数プロジェクト間で共通の設定は、Organization Settings の Contexts で設定しておくと便利です。
Organization Settings -> Contexts に行き、org-global（なければ作成）内にて環境変数を追加します。

- Environment Variable Name: SLACK_ENDPOINT
- Value: コピーした Webhook URL

を入力し、保存します。

![2020-09-22 19-58-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/c7f312c9-0a5f-ecbe-3490-4698d84f5ae6.png)

![2020-09-22 20-04-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/6b611ba2-9194-6811-20d0-9d99a5032a4f.png)

### Environment Variables の設定

CircleCI の API Token は、Project Settings の Environment Variables で登録します。


- Name: CIRCLE_TOKEN
- Value: コピーした API Token

を入力し、保存します。

![2020-09-22 20-02-42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/7443a6d5-9397-a448-caa7-7b7af07b93e0.png)

![2020-09-22 20-03-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/8dd8d53f-d7ec-130e-3207-ebd142c24def.png)

### config.yml の設定

CircleCI の設定ファイルの steps に、以下のようにカバレッジ計測用の処理を追加します。

```config.yaml
      - run:
          name: Post coverage report to Slack
          command: |
            export COMMIT_AUTHOR="$(git log --format='%an <%ae>' -1 | sed 's/\\/\\\\/g;s/\"/\\"/g')"
            export COMMIT_LOG="$(git log --format=%s -1 | sed 's/\\/\\\\/g;s/\"/\\"/g')"
            curl -s -L https://gist.githubusercontent.com/u-minor/20c7876b9bc4b875d9c73b59f2a4365f/raw/circleci2-coverage-slack | sh -s
```

> [gist](https://gist.githubusercontent.com/u-minor/20c7876b9bc4b875d9c73b59f2a4365f/raw/circleci2-coverage-slack) にコードがありますので、そのまま使うなり複製して使うなりしてください。 

ここまでの設定がうまく行けば、ビルド -> テスト（カバレッジ計測）完了後に Slack に結果が通知されます。

# 補足

## XML のファイル名が `coverage.xml` で終わらない場合

artifacts 内のカバレッジ情報のファイル名は `coverage.xml` で終わるものを探しています。
このファイル名で終わらない場合は、Environment Variables に以下の内容を追加でセットします。

- Name: COVERAGE_FILE
- Value: XML ファイル名

## jacoco を利用する場合

デフォルトでは cobertura 形式とみなして処理します。
jacoco 形式の場合は Test Commands の最後の bash コマンドを `bash -s jacoco` に変更します。

```
curl -s -L https://gist.githubusercontent.com/u-minor/20c7876b9bc4b875d9c73b59f2a4365f/raw/circleci2-coverage-slack | sh -s jacoco
```

またカバレッジ情報ファイル名が標準で `jacoco.xml` となるため、COVERAGE_FILE 環境変数も追加します。

- Name: COVERAGE_FILE
- Value: jacoco.xml

# 2016/03/11 追記

~~Post-test commands だと build やテストに失敗しても実行されてしまうので、テスト成功時のみ実行するのであれば、`circle.yml` の deployment セクションに以下のように追記する必要があります。~~

```circle.yml
deployment:
  report_coverage:
    branch: /.*/
    commands:
      - curl -s -L https://gist.githubusercontent.com/u-minor/8cb27fa9c04163142ebd/raw/circleci-coverage-slack | bash -s
```

# 2020/09/22 追記

CircleCI 2.0 に合わせてもろもろ改変。git のコードも更新しました。