MavenプロジェクトでSonarQubeを使ってみる

# What's？

こちらのエントリでSonarQubeサーバーのインストール方法はわかったので、今後はSonarQubeを動かしてみましょう。

[CentOS 8にSonarQubeサーバーをインストールする](https://qiita.com/charon/items/b5e54fab02dd9aae9525)

Java（Maven）なプロジェクトで、SonarQubeのソースコード解析を動かしてみます。


# 環境

SonarQubeサーバーのバージョンは`8.6.0.39681`、SonarQubeサーバーが稼働しているサーバーのIPアドレスは`192.168.33.10`とします。

JavaやMavenのバージョンはこちら。

```shell
$ java --version
openjdk 11.0.9.1 2020-11-04
OpenJDK Runtime Environment (build 11.0.9.1+1-Ubuntu-0ubuntu1.20.04)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 11.0.9.1, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-64-generic", arch: "amd64", family: "unix"
```


# サンプルプロジェクト

ソースコード解析をしようにも、ソースコードがないとどうにもなりません。

今回は、すでに存在するものを引っ張ってくることにしました。Spring PetClinicです。

[Spring PetClinic Sample Application](https://github.com/spring-projects/spring-petclinic)

cloneしてきて

```shell
$ git clone https://github.com/spring-projects/spring-petclinic.git
$ cd spring-petclinic
```

特定のタグにcheckoutしたかったところですが、タグがなかったのでコミットにしておきました。

```shell
$ git log -1
commit 02babdd8cb0d494d043fdf35a24dd2127c5d5167 (HEAD -> main, origin/main, origin/HEAD)
Author: Stephane Nicoll <snicoll@vmware.com>
Date:   Fri Dec 25 13:02:48 2020 +0100

    Upgrade to Spring Boot 2.4.1

$ git checkout 02babdd8cb0d494d043fdf35a24dd2127c5d5167
```

これで、ソースコードを解析するプロジェクトの準備は完了です。


# SonarQubeでソースコードを解析する

SonarQubeサーバー側では、ユーザーとプロジェクトを作成しておきます。

プロジェクト作成時に

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/d6af35a6-9d0c-b4f8-9e42-3f94e8fd13f3.png)

トークンを作って

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/23a460e4-26fc-7ede-ddcb-3b269ffda4e9.png)

ビルドシステムや言語を選ぶと、使い方を教えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/888d2eea-ad0a-2f65-305f-b93dc77cdbd8.png)


今回は、プロジェクト名は`sonar-spring-petclinic`としました。  
※キャプチャとは違う名前ですね…

以下のように、システムプロパティでSonarQubeサーバー上のプロジェクト名、接続先、トークンを指定して`sonar:sonar`ゴールを実行します。

```shell
$ mvn compile sonar:sonar \
  -Dsonar.projectKey=sonar-spring-petclinic \
  -Dsonar.host.url=http://192.168.33.10:9000 \
  -Dsonar.login=[SonarQubeトークン]
```

この時、ソースコードのビルドは完了している必要があります。

Sonar Maven Plugin実行時の様子です。

```shell
[INFO] --- sonar-maven-plugin:3.8.0.2131:sonar (default-cli) @ spring-petclinic ---
[INFO] User cache: $HOME/.sonar/cache
[INFO] SonarQube version: 8.6.0
[INFO] Default locale: "ja_JP", source code encoding: "UTF-8"
[INFO] Load global settings
[INFO] Load global settings (done) | time=216ms
[INFO] Server id: 641C58CB-AXcoJzcTxqy5V9PiCfw8
[INFO] User cache: $HOME/.sonar/cache
[INFO] Load/download plugins
[INFO] Load plugins index
[INFO] Load plugins index (done) | time=66ms
[INFO] Load/download plugins (done) | time=105ms
[INFO] Process project properties
[INFO] Process project properties (done) | time=7ms
[INFO] Execute project builders
[INFO] Execute project builders (done) | time=1ms
[INFO] Project key: sonar-spring-petclinic
[INFO] Base dir: /path/to/spring-petclinic
[INFO] Working dir: /path/to/spring-petclinic/target/sonar
[INFO] Load project settings for component key: 'sonar-spring-petclinic'
[INFO] Load project settings for component key: 'sonar-spring-petclinic' (done) | time=16ms
[INFO] Load quality profiles
[INFO] Load quality profiles (done) | time=44ms
[INFO] Load active rules
[INFO] Load active rules (done) | time=798ms
[INFO] Indexing files...
[INFO] Project configuration:
[INFO] 37 files indexed
[INFO] 0 files ignored because of scm ignore settings
[INFO] Quality profile for java: My Sonar way
[INFO] Quality profile for xml: Sonar way
[INFO] ------------- Run sensors on module petclinic
[INFO] Load metrics repository
[INFO] Load metrics repository (done) | time=19ms
[INFO] Sensor JavaSquidSensor [java]
[INFO] Configured Java source version (sonar.java.source): 8
[INFO] JavaClasspath initialization
[INFO] JavaClasspath initialization (done) | time=20ms
[INFO] JavaTestClasspath initialization
[INFO] JavaTestClasspath initialization (done) | time=4ms
[INFO] Java Main Files AST scan
[INFO] 25 source files to be analyzed
[INFO] Load project repositories
[INFO] Load project repositories (done) | time=20ms
[INFO] 25/25 source files have been analyzed
[INFO] Java Main Files AST scan (done) | time=2436ms
[INFO] Java Test Files AST scan
[INFO] 11 source files to be analyzed
[INFO] Java Test Files AST scan (done) | time=710ms
[INFO] 11/11 source files have been analyzed
[INFO] Java Generated Files AST scan
[INFO] 0 source files to be analyzed
[INFO] Java Generated Files AST scan (done) | time=1ms
[INFO] 0/0 source files have been analyzed
[INFO] Sensor JavaSquidSensor [java] (done) | time=3399ms
[INFO] Sensor CSS Rules [cssfamily]
[INFO] No CSS, PHP, HTML or VueJS files are found in the project. CSS analysis is skipped.
[INFO] Sensor CSS Rules [cssfamily] (done) | time=1ms
[INFO] Sensor JaCoCo XML Report Importer [jacoco]
[INFO] 'sonar.coverage.jacoco.xmlReportPaths' is not defined. Using default locations: target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml
[INFO] No report imported, no coverage information will be imported by JaCoCo XML Report Importer
[INFO] Sensor JaCoCo XML Report Importer [jacoco] (done) | time=7ms
[INFO] Sensor C# Properties [csharp]
[INFO] Sensor C# Properties [csharp] (done) | time=1ms
[INFO] Sensor SurefireSensor [java]
[INFO] parsing [/path/to/spring-petclinic/target/surefire-reports]
[INFO] Sensor SurefireSensor [java] (done) | time=2ms
[INFO] Sensor JavaXmlSensor [java]
[INFO] 1 source files to be analyzed
[INFO] Sensor JavaXmlSensor [java] (done) | time=219ms
[INFO] 1/1 source files have been analyzed
[INFO] Sensor HTML [web]
[INFO] Sensor HTML [web] (done) | time=3ms
[INFO] Sensor XML Sensor [xml]
[INFO] 1 source files to be analyzed
[INFO] Sensor XML Sensor [xml] (done) | time=123ms
[INFO] 1/1 source files have been analyzed
[INFO] Sensor VB.NET Properties [vbnet]
[INFO] Sensor VB.NET Properties [vbnet] (done) | time=1ms
[INFO] ------------- Run sensors on project
[INFO] Sensor Zero Coverage Sensor
[INFO] Sensor Zero Coverage Sensor (done) | time=11ms
[INFO] Sensor Java CPD Block Indexer
[INFO] Sensor Java CPD Block Indexer (done) | time=56ms
[INFO] SCM Publisher SCM provider for this project is: git
[INFO] SCM Publisher 1 source file to be analyzed
[INFO] SCM Publisher 0/1 source files have been analyzed (done) | time=286ms
[WARNING] Missing blame information for the following files:
[WARNING]   * pom.xml
[WARNING] This may lead to missing/broken features in SonarQube
[INFO] CPD Executor 12 files had no CPD blocks
[INFO] CPD Executor Calculating CPD for 13 files
[INFO] CPD Executor CPD calculation finished (done) | time=11ms
[INFO] Analysis report generated in 71ms, dir size=251 KB
[INFO] Analysis report compressed in 95ms, zip size=112 KB
[INFO] Analysis report uploaded in 82ms
[INFO] ANALYSIS SUCCESSFUL, you can browse http://192.168.33.10:9000/dashboard?id=sonar-spring-petclinic
[INFO] Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
[INFO] More about the report processing at http://192.168.33.10:9000/api/ce/task?id=AXcqAWMeAa54pbha1y28
[INFO] Analysis total time: 7.170 s
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  15.828 s
[INFO] Finished at: 2021-01-22T21:11:10+09:00
[INFO] ------------------------------------------------------------------------
```

SonarQubeサーバーへの送信が上手くいったら、プロジェクトのページを見てみます。

こんな感じになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/74eafcd8-8e94-f709-7e2e-ed8d9fb14fd6.png)

検出された問題の一覧が見れたり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/0fee6ef0-2317-470d-79af-8f18236a1996.png)

指摘箇所が見れたり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/8df212f6-1bf2-b3fa-b25c-bd6fcacee8cf.png)

ソースコードも見れたりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/7b3c763b-e6c5-059c-928f-077800fa655c.png)

ということは、プロジェクトのソースコードはSonarQubeサーバーに送っているんですね。

# Sonar Maven Pluginをpom.xmlに組み込む

先ほどは`mvn`実行時のシステムプロパティですべての設定を行い、またプラグインのバージョン指定などもなかったので、今度は`pom.xml`にSonar Maven Pluginを組み込んでみましょう。

こちらですね。

[SonarScanner for Maven](https://docs.sonarqube.org/8.6/analysis/scan/sonarscanner-for-maven/)

[SonarQube Scanner for Maven](http://sonarsource.github.io/sonar-scanner-maven/)

シンプルに、こんな感じになります。設定項目はほぼありません（スキップの指定があるくらいです）。

```xml

  <build>
    <plugins>
      <plugin>
        <groupId>org.sonarsource.scanner.maven</groupId>
        <artifactId>sonar-maven-plugin</artifactId>
        <version>3.8.0.2131</version>
      </plugin>

      ...

    </plugins>
  </build>
```

設定がないと書きましたが、先ほどのSonarQubeサーバーのURLなどの説明は？というと、こちらにあります。

[Analysis Parameters](https://docs.sonarqube.org/8.6/analysis/analysis-parameters/)

これらは、`pom.xml`にプロパティとして指定しましょう。

```xml
  <properties>
    <!-- SonarQube -->
    <sonar.projectKey>sonar-spring-petclinic</sonar.projectKey>
    <sonar.host.url>http://192.168.33.10:9000</sonar.host.url>
    <sonar.login>dummy</sonar.login>

    ...

  </properties>
```

トークンだけは、システムプロパティで実行時に渡すことにしました。

```shell
$ mvn sonar:sonar -Dsonar.login=[トークン]
```

実際には、ソースコードのビルドとともに動かすことになると思うので、以下のような使い方になるでしょう。

```shell
$ mvn compile sonar:sonar -Dsonar.login=[トークン]
$ mvn test sonar:sonar -Dsonar.login=[トークン]
$ mvn package sonar:sonar -Dsonar.login=[トークン]
```

ちなみに、Spring PetClinicの場合、HTTPでSonarQubeへの接続先を書いていたらCheckStyleでNGになりました…。

```shell
[INFO] --- maven-checkstyle-plugin:3.1.1:check (nohttp-checkstyle-validation) @ spring-petclinic ---
[INFO] There is 1 error reported by Checkstyle 8.32 with src/checkstyle/nohttp-checkstyle.xml ruleset.
[ERROR] pom.xml:[36,22] (extension) NoHttp: http:// URLs are not allowed but got 'http://192.168.33.10:9000'. Use https:// instead.
```

今回は、コメントアウトしておきます…。

```xml:src/checkstyle/nohttp-checkstyle.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
		"-//Puppy Crawl//DTD Check Configuration 1.2//EN"
		"https://checkstyle.org/dtds/configuration_1_2.dtd">
<module name="com.puppycrawl.tools.checkstyle.Checker">
	<!-- <module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"/> -->
</module>
```


# 適用しているルールについて

今回はなにも考えずに実行しましたが、デフォルトのルールでソースコードチェックされていることになります。

Project Informationで見た時の、「Quality Profile」というものが適用しているルールをまとめたプロファイルです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/126ce527-0ae4-7032-d731-2abcfa9c59ed.png)

デフォルトでは「Sonar way」というプロファイルが使われています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/fc995582-bfab-341f-1e52-1ba274c5c10f.png)

各言語の全ルールが有効になっているわけではなく、ある程度は選別されているようです。

一覧はこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/be266ae1-13c9-a19d-607a-8363d62503c6.png)

Sonar wayはビルトインプロファイルなので、編集することができません。

Sonar wayをベースにカスタマイズするには、コピーして新しいプロファイルを作って行うのがよいのでしょう。

こちらは、Sonar wayプロファイルをコピーして作成した「My Sonar way」というプロファイルです。`Deactivate`が押せるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/77ce626e-4f68-3954-7d7f-75641e49f3cd.png)

あとは、プロジェクト側のQuality Profiliesで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/22b01f46-7013-5078-6afd-aa1d737adf98.png)

作成したプロファイルを選択すると、次回の解析から使用されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309669/d90b388a-552e-51f0-50a6-930d39daea67.png)

これで、SonarQubeでの解析が始められますね。