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


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

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

過去に、SonarQube x TravisCI x GitHub による連携エントリは書きましたが、今回はバージョンも新たに、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] へ進みます。

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

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

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


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

GitHub リポジトリ情報

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

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

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

SonarQube ログイン情報

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

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 ログイン パスワード

ビルド構成

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

circle.yml

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

circle.yml
machine:
  java:
    version: openjdk8
test:
  override:
    - bash .ci/analyze-sonarqube.sh
    - mvn integration-test
.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

CircleCI が動き始めます。

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

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

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