SonarQube と CircleCI を使って Github でのコードレビューを自動化する

最近では SideCI なども人気があり、静的解析が再び注目されているように感じていますが、Java をはじめとする多くの言語では、まだまだ ASP による静的解析サービスが存在していないのが現状です。(2016-07-09 本日現在)

一方、オンプレになってはしまいますが、老舗静的解析である SonarQube は、多くの言語に対応しており、先日 LTS となる 5.6 もリリースされ、まだしばらくは活躍するのかなという感じ。

過去に、[SonarQube x TravisCI x GitHub による連携エントリ](http://qiita.com/yo1000/items/740f0f775a5ba3753d5f)は書きましたが、今回はバージョンも新たに、CircleCI と連携させてみたので残しておきます。

# 環境

- SonarQube 5.6
- SonarQube GitHub Plugin 1.3
- GitHub (2016-07-09 現在)
- CircleCI (2016-07-09 現在)

```
$ curl http://127.0.0.1:9000 | grep -e "Version [0-9\.]*"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10570  100 10570    0     0   164k      0 --:--:-- --:--:-- --:--:--  166k
      Version 5.6 -
```

# 事前準備

まず、SonarQube へ、GitHub Plugin がインストールされている必要があります。また、必要な情報として、Github のアクセストークン、および対象リポジトリ情報、SonarQube サーバーのログイン情報を準備します。

それぞれ、以下のように取得します。

## GitHub Plugin のインストール

すでにインストールが完了している場合は、この手順をスキップしてください。

SonarQube へログインし、[Administration] > [System] > [Update Center] > [Available] と進めると、"GitHub" が見つかるので、[Install] します。インストールが完了したら、SonarQube を再起動します。

## Github アクセストークン

プロフィールアイコンから、[Settings] へ進みます。

<img width="185" alt="スクリーンショット 2016-02-09 16.37.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/47993/00a75e1c-281b-6e95-a693-c0e58066e21d.png">

サイドメニューから、[Personal access tokens] へ進みます。

<img width="236" alt="スクリーンショット 2016-02-09 16.38.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/47993/e29cb4ea-1c3d-e08c-4068-e6e70dc608e8.png">

[Generate new token] ボタンから、トークンを新規作成します。

<img width="736" alt="スクリーンショット 2016-02-09 16.39.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/47993/64c76c57-7e00-5d8a-6168-4848b2372cc8.png">

[Token description] にトークンの説明を記入し、[Select scopes] では、[repo] にチェックを入れ、[Generate token] ボタンをクリックして、トークンを生成します。

<img width="738" alt="スクリーンショット 2016-02-09 16.42.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/47993/0bf94df3-aa1f-90f5-e001-35a7d19a465b.png">
<img width="738" alt="スクリーンショット 2016-02-09 16.44.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/47993/1f2ee687-550b-ec37-902c-a86861bce30c.png">

生成されたトークンが表示されるので、これを控えておきます。

<img width="736" alt="スクリーンショット 2016-02-09 16.46.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/47993/1eeae45e-c164-15bd-63e5-a60195933ce5.png">

## GitHub リポジトリ情報

リポジトリ URL のうち、Owner または、Organization、およびリポジトリ名を、スラッシュで繋いだものを控えます。以下の URL を例に取った場合は次のようになります。

URL: https://github.com/yo1000/sonarqube-collaboration

リポジトリ情報: `yo1000/sonarqube-collaboration`


## SonarQube ログイン情報

SonarQube サーバーの URL と、ログインに使用する、[Login] と [Password] を控えておきます。

![スクリーンショット 2016-02-09 16.47.58.png](https://qiita-image-store.s3.amazonaws.com/0/47993/17fab486-ae4b-cd51-fc5a-ecf53cdbe895.png)

## CircleCI 環境変数

ここまでで以下の値が揃ったはずです。

- GitHub アクセストークン
- GitHub リポジトリ情報
- SonarQube URL
- SonarQube ログイン ユーザー名
- SonarQube ログイン パスワード

これらの値を CircleCI に、環境変数として設定していきます。
プロジェクトのトップで、画面右上の [Project Settings] > [Environment Variables] と進んでいきます。

先ほどの値を使用して、それぞれ以下のように設定していきます。

| Name               | Value                      |
|--------------------|----------------------------|
| GITHUB_OAUTH       | Github アクセストークン       |
| GITHUB_REPOS       | Github リポジトリ情報        |
| SONARQUBE_URL      | SonarQube URL              |
| SONARQUBE_LOGIN    | SonarQube ログイン ユーザー名 |
| SONARQUBE_PASSWORD | SonarQube ログイン パスワード |

![スクリーンショット 2016-07-10 19.12.17.png](https://qiita-image-store.s3.amazonaws.com/0/47993/fd1abe82-4edb-a9fe-7133-13a3b25ba666.png "スクリーンショット 2016-07-10 19.12.17.png")


# ビルド構成

事前準備を終えたら、ビルド構成を作成していきます。

## circle.yml

CircleCI を使用するので、プロジェクトルートに `circle.yml` を作成、配置します。
以下のようなファイルを作成します。

```yaml:circle.yml
machine:
  java:
    version: openjdk8
test:
  override:
    - bash .ci/analyze-sonarqube.sh
    - mvn integration-test
```

```yaml:.ci/analyze-sonarqube.sh
#!/bin/bash

echo "${CI_PULL_REQUEST}"

if [[ ! "${CI_PULL_REQUEST}" =~ /pull/[0-9]+$ ]]; then
  exit 0
fi

PR_NUMBER=`echo "${CI_PULL_REQUEST}" | sed -e 's/.*\///g'`

echo "mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar"
echo "  -Dmaven.test.skip=true"
echo "  -Dclirr=true"
echo "  -Dsonar.host.url=${SONARQUBE_URL}"
echo "  -Dsonar.login=****"
echo "  -Dsonar.password=****"
echo "  -Dsonar.sourceEncoding=UTF-8"
echo "  -Dsonar.analysis.mode=issues"
echo "  -Dsonar.github.pullRequest=${PR_NUMBER}"
echo "  -Dsonar.github.oauth=****"
echo "  -Dsonar.github.repository=${GITHUB_REPOS}"
echo "  -B -e -V"

mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar \
  -Dmaven.test.skip=true			\
  -Dclirr=true				\
  -Dsonar.host.url="${SONARQUBE_URL}"		\
  -Dsonar.login="${SONARQUBE_LOGIN}"		\
  -Dsonar.password="${SONARQUBE_PASSWORD}"	\
  -Dsonar.sourceEncoding=UTF-8		\
  -Dsonar.analysis.mode=issues		\
  -Dsonar.github.pullRequest="${PR_NUMBER}"	\
  -Dsonar.github.oauth="${GITHUB_OAUTH}"	\
  -Dsonar.github.repository="${GITHUB_REPOS}"	\
  -B -e -V
```

`test.override` で、`.ci/analyze-sonarqube.sh` を実行し、その中では、事前に設定した各種環境変数を `mvn` コマンドに渡しています。

CircleCI では、事前に環境変数で定義された値を、スクリプト内で参照できるため、先ほど設定した、Github アクセストークンや、SonarQube ログイン情報などがここで使用されているわけです。

ただ、先ほど設定しなかった、`${CI_PULL_REQUEST}` については、事前設定した環境変数たちとは少々異なるもので、CircleCI 側で用意してくれるものになり、値にはプルリクエスト URL が入ります。

内容としては、プルリクエスト URL の末尾が `/pull/{PullRequestNumber}` だった場合、sonar-maven-plugin を使用して、SonarQube サーバーに解析リクエストを投入し、受け取った解析結果を Github の対象プルリクエストにコメントさせる、というものになります。

CircleCI では、プルリクエストの発生や、対象ブランチの更新もビルドトリガとなるため、プルリクエストが上がってきたら、自動的にコードの静的解析と、結果のコメントまでが実施されるようになります。

ただし CircleCI では、何度か試してみたのですが、プルリクエストを作成した直後のビルドでは、`${CI_PULL_REQUEST}` に値が設定されないということが度々ありました。これについては、レビューをかけるよりも前に WIP 状態で事前にプルリクエストを投げておくなど、何らかの対策が必要になるかもしれません。

なお、すべての環境変数については以下から確認できます。
https://circleci.com/docs/environment-variables/


# 動作確認

最終的なプロジェクトは以下のようになりました。
https://github.com/yo1000/sonarqube-collaboration/tree/pr-test

実際にひどいコード変更を入れて、プルリクエストを投げてみます。
https://github.com/yo1000/sonarqube-collaboration/pull/2

![スクリーンショット 2016-07-11 0.35.52.png](https://qiita-image-store.s3.amazonaws.com/0/47993/e62b2240-3844-1aa2-fe0a-0b9e2036377e.png "スクリーンショット 2016-07-11 0.35.52.png")

CircleCI が動き始めます。

![スクリーンショット 2016-07-11 0.33.10.png](https://qiita-image-store.s3.amazonaws.com/0/47993/b7fcab9f-24a1-073a-1f69-b94adca0783d.png "スクリーンショット 2016-07-11 0.33.10.png")

レビュー結果がコメントされましたね！！

![スクリーンショット 2016-07-11 0.37.29.png](https://qiita-image-store.s3.amazonaws.com/0/47993/a1c07a87-7823-edcd-d433-b5f675e1db41.png "スクリーンショット 2016-07-11 0.37.29.png")

コメントをつけているユーザーは、Github アクセストークンに基づくので、自動レビュー用に別途ユーザーを用意してもいいかもしれません。

ここまでで連携は完了です。
以前は TravisCI で紹介しましたが、CircleCI でも同様にコードレビューを自動化することができました。SonarQube を使い倒して、効率的に開発していきたいですね！