代碼質(zhì)量管理平臺(tái)-SonarQube

介紹

SonarQube是個(gè)開(kāi)源的代碼質(zhì)量管理平臺(tái),可以通過(guò)多種工具和維度對(duì)代碼質(zhì)量進(jìn)行分析,部分功能還支持可視化,對(duì)于代碼缺陷一目了然。SonarQube比較開(kāi)放,支持通過(guò)插件擴(kuò)展功能,市面上常用的語(yǔ)言基本可以支持。同時(shí),我們也可以嘗試將sonar跟常用的jekins或者gocd集成在一起,在持續(xù)構(gòu)建的同時(shí)對(duì)代碼質(zhì)量進(jìn)行監(jiān)測(cè)。該工具功能強(qiáng)大,使用簡(jiǎn)便,實(shí)乃程序員保證代碼健康的必備良藥。

環(huán)境搭建部署

環(huán)境搭建包含兩部分,數(shù)據(jù)庫(kù)后臺(tái)和sonarqube本身,sonarqube本身內(nèi)嵌了H2用來(lái)存儲(chǔ)分析數(shù)據(jù),但是應(yīng)用到生產(chǎn)環(huán)境并不合適,針對(duì)我們的情況還是單獨(dú)部署數(shù)據(jù)庫(kù)為好。

數(shù)據(jù)庫(kù)配置

官方支持對(duì)接四種數(shù)據(jù)庫(kù),Microsoft SQL Server、Oracle、PostgreSQL、MySQL(不推薦),我使用的是postgresql數(shù)據(jù)庫(kù)。其他幾種數(shù)據(jù)庫(kù)具體安裝注意事項(xiàng)大家可以看官方文檔:Installing the Database
為了與其他應(yīng)用隔離開(kāi),針對(duì)SonarQube單獨(dú)建立相應(yīng)的數(shù)據(jù)庫(kù)、用戶(hù)和schema,在Mac OS以及Linux上,還需要建立相應(yīng)的系統(tǒng)用戶(hù)sonarqube。數(shù)據(jù)庫(kù)建用戶(hù)、建庫(kù)等操作請(qǐng)自行g(shù)oogle,另外,別忘記賦予數(shù)據(jù)庫(kù)用戶(hù)相應(yīng)的建表等權(quán)限。
schema名稱(chēng)為sonar,用戶(hù)名稱(chēng)為sonarqube:

sonar=# \dn
  List of schemas
  Name  |   Owner
--------+-----------
 public | postgres
 sonar  | sonarqube

數(shù)據(jù)庫(kù)名稱(chēng)也命名為sonar:

sonar=# \l
                              List of databases
   Name    |   Owner   | Encoding | Collate | Ctype |    Access privileges
-----------+-----------+----------+---------+-------+-------------------------
 open_lmis | postgres  | UTF8     | C       | C     |
 postgres  | postgres  | UTF8     | C       | C     |
 sonar     | sonarqube | UTF8     | C       | C     | =Tc/sonarqube          +
           |           |          |         |       | sonarqube=CTc/sonarqube
 template0 | postgres  | UTF8     | C       | C     | =c/postgres            +
           |           |          |         |       | postgres=CTc/postgres
 template1 | postgres  | UTF8     | C       | C     | =c/postgres            +
           |           |          |         |       | postgres=CTc/postgres

這塊需要注意的是,在postgresql中,新建用戶(hù)sonarqube默認(rèn)的schema還是指向public,而我們要使用新建的sonar,需要在數(shù)據(jù)庫(kù)中執(zhí)行以下命令將sonarqube的默認(rèn)schema改為sonar:

ALTER USER sonarqube SET search_path to sonar

SonarQube部署

sonarqube的部署非常簡(jiǎn)單,我下載的版本是7.3。下載后解壓,然后執(zhí)行bin目錄中相應(yīng)操作系統(tǒng)的啟動(dòng)即可,不過(guò)在這之前需要對(duì)數(shù)據(jù)庫(kù)信息進(jìn)行配置。配置方法是進(jìn)入到解壓后的文件夾的conf目錄中,修改sonar.properties文件,文件中有很多配置項(xiàng),不過(guò)都是被注釋掉的。這個(gè)配置文件里面的說(shuō)明非常詳細(xì),包括需要適配數(shù)據(jù)庫(kù)的哪些版本等等。里面提示Postgresql需要在9.3版本及以上,我機(jī)器裝的是9.4,剛好可以用,大家在安裝相應(yīng)版本的時(shí)也請(qǐng)仔細(xì)閱讀這個(gè)配置里面的說(shuō)明信息,防止因?yàn)榘姹締?wèn)題出錯(cuò)。同時(shí),也包含其他配置信息,暫時(shí)沒(méi)有時(shí)間研究,我們先盡快把sonarqube跑起來(lái)再說(shuō)。

(2.0-moz)? % j sonar                                                                                                                                                              ~/IdeaProjects/open-lmis
/Users/zbao/Tool/sonarqube-7.3
% ll                                                                                                                                                                                   ~/Tool/sonarqube-7.3
total 16
-rw-r--r--@  1 zbao  staff   7.5K Aug 10 17:31 COPYING
drwxr-xr-x@  8 zbao  staff   256B Aug 10 17:31 bin
drwxr-xr-x@  4 zbao  staff   128B Sep  3 22:45 conf
drwxr-xr-x@  6 zbao  staff   192B Sep  3 22:46 data
drwxr-xr-x@ 11 zbao  staff   352B Aug 10 17:31 elasticsearch
drwxr-xr-x@  5 zbao  staff   160B Sep  3 17:52 extensions
drwxr-xr-x@  7 zbao  staff   224B Aug 10 17:40 lib
drwxr-xr-x@ 16 zbao  staff   512B Sep  5 09:27 logs
drwxr-xr-x@  8 zbao  staff   256B Sep  5 21:19 temp
drwxr-xr-x@ 24 zbao  staff   768B Aug 10 17:40 web
% cd conf                                                                                                                                                                              ~/Tool/sonarqube-7.3
% ll                                                                                                                                                                              ~/Tool/sonarqube-7.3/conf
total 48
-rw-r--r--@ 1 zbao  staff    20K Sep  3 22:45 sonar.properties
-rw-r--r--@ 1 zbao  staff   3.1K Aug 10 17:31 wrapper.conf

這個(gè)配置現(xiàn)在只需要修改三個(gè)配置即可,數(shù)據(jù)庫(kù)用戶(hù)、數(shù)據(jù)庫(kù)密碼和jdbc的url:

# User credentials.
# Permissions to create tables, indices and triggers must be granted to JDBC user.
# The schema must be created first.
sonar.jdbc.username=sonarqube
sonar.jdbc.password=password
#----- PostgreSQL 9.3 or greater
# If you don't use the schema named "public", please refer to http://jira.sonarsource.com/browse/SONAR-5000
sonar.jdbc.url=jdbc:postgresql://localhost/sonar

sonarqube的web服務(wù)默認(rèn)是全零監(jiān)聽(tīng)在9000端口上,如果想修改,可以修改這兩個(gè)配置,我用的是默認(rèn):

# Binding IP address. For servers with more than one IP address, this property specifies which
# address will be used for listening on the specified ports.
# By default, ports will be used on all IP addresses associated with the server.
sonar.web.host=0.0.0.0

# Web context. When set, it must start with forward slash (for example /sonarqube).
# The default value is root context (empty value).
#sonar.web.context=
# TCP port for incoming HTTP connections. Default value is 9000.
sonar.web.port=9000

修改完成后,進(jìn)入bin目錄,根據(jù)操作系統(tǒng)選擇,我用的是Mac OS,直接使用下面命令啟動(dòng):

% cd macosx-universal-64                                                                                                                                                           ~/Tool/sonarqube-7.3/bin
% ll                                                                                                                                                           ~/Tool/sonarqube-7.3/bin/macosx-universal-64
total 288
-rw-r--r--  1 zbao  staff     5B Sep  5 21:19 SonarQube.pid
drwxr-xr-x@ 3 zbao  staff    96B Aug 10 17:31 lib
-rwxr-xr-x@ 1 zbao  staff    15K Aug 10 17:31 sonar.sh
-rwxr-xr-x@ 1 zbao  staff   123K Aug 10 17:31 wrapper
% sh sonar.sh start                                                                                                                                            ~/Tool/sonarqube-7.3/bin/macosx-universal-64
Starting SonarQube...
Started SonarQube.

啟動(dòng)后,查詢(xún)sonar數(shù)據(jù)庫(kù)里面新建了不少表,說(shuō)明sonarqube已經(jīng)在啟動(dòng)時(shí)將必須的數(shù)據(jù)刷進(jìn)去了,下面是其中的部分表:

sonar=> \d
                        List of relations
 Schema |              Name               |   Type   |   Owner
--------+---------------------------------+----------+-----------
 sonar  | active_rule_parameters          | table    | sonarqube
 sonar  | active_rule_parameters_id_seq   | sequence | sonarqube
 sonar  | active_rules                    | table    | sonarqube
 sonar  | active_rules_id_seq             | sequence | sonarqube
 sonar  | alm_app_installs                | table    | sonarqube
 sonar  | analysis_properties             | table    | sonarqube
 sonar  | ce_activity                     | table    | sonarqube
 sonar  | ce_activity_id_seq              | sequence | sonarqube
 sonar  | ce_queue                        | table    | sonarqube
 sonar  | ce_queue_id_seq                 | sequence | sonarqube
 sonar  | ce_scanner_context              | table    | sonarqube
 sonar  | ce_task_characteristics         | table    | sonarqube
 sonar  | ce_task_input                   | table    | sonarqube
 sonar  | default_qprofiles               | table    | sonarqube
 sonar  | deprecated_rule_keys            | table    | sonarqube
 sonar  | duplications_index              | table    | sonarqube
 sonar  | duplications_index_id_seq       | sequence | sonarqube
 sonar  | es_queue                        | table    | sonarqube

數(shù)據(jù)庫(kù)表中有張user表,是用來(lái)存儲(chǔ)用戶(hù)信息的,默認(rèn)用戶(hù)名和密碼均為admin和admin,第一次登陸系統(tǒng)需要輸入這個(gè)密碼:

sonar=> select * from users;
 id | login |     name      | email |                       crypted_password                       | salt | active |  created_at   |  updated_at   | scm_accounts | external_login | external_identity_provider | user_local | is_root | onboarded | homepage_type | homepage_parameter | hash_method | uuid  | external_id | organization_uuid
----+-------+---------------+-------+--------------------------------------------------------------+------+--------+---------------+---------------+--------------+----------------+----------------------------+------------+---------+-----------+---------------+--------------------+-------------+-------+-------------+-------------------
  1 | admin | Administrator |       | $2a$12$LJLoKEDVZgBCO6OahphMYeYS6lqE7p0J/Fm6EdKdsqxMgpXGNpmhq |      | t      | 1535987042646 | 1536023846785 |              | admin          | sonarqube                  | t          | f       | t         |               |                    | BCRYPT      | admin | admin       |
(1 row)

啟動(dòng)后稍等片刻,打開(kāi)瀏覽器輸入http://localhost:9000/,點(diǎn)擊Log in,用戶(hù)名admin,密碼admin,便可以登陸進(jìn)去了。至此,sonarqube環(huán)境搭建完成。

sonarqube.png

SonarJava插件

SonarQube支持了市面上大部分語(yǔ)言的分析,具體方式是通過(guò)Sonar插件來(lái)實(shí)現(xiàn)的,這樣很方便插件開(kāi)發(fā)人員。


sonar plugins.png

根據(jù)官方介紹,使用了最先進(jìn)的技術(shù)(模式匹配、數(shù)據(jù)流分析)對(duì)代碼質(zhì)量進(jìn)行管理,包括代碼壞味道檢查(不了解的可以參考重構(gòu)一書(shū))、findbugs以及代碼安全檢查。自稱(chēng)檢查的深度、精度、速度都很不錯(cuò)。

SonarSource delivers what is probably the best static code analyzer you can find on the market for Java. Based on our own Java compiler front-end, it uses the most advanced techniques (pattern matching, dataflow analysis) to analyze code and find code smells, bugs and security vulnerabilities. As for any product we develop at SonarSource, it was built on the following principles: depth, accuracy and speed.

優(yōu)點(diǎn):
支持400+的規(guī)則,規(guī)則數(shù)還比較多
支持規(guī)則自定義,用戶(hù)實(shí)現(xiàn)相關(guān)接口便可以注入自己的檢查規(guī)則
支持與Maven、Ant、Gradle的集成,快速簡(jiǎn)便
支持Jacoco和Cobertura覆蓋率報(bào)告導(dǎo)入
支持導(dǎo)入用戶(hù)的findbugs/pmd/checkstyle報(bào)告

Gradle集成

由于項(xiàng)目是Gradle構(gòu)建,僅介紹與Gradle構(gòu)建相關(guān)的集成,具體其他方式可以參考Analyzing Source Code。
集成過(guò)程在Gradle中很簡(jiǎn)單,引入sonar-runner和org.sonarqube插件,插件默認(rèn)會(huì)導(dǎo)入sonarqube的task。

apply plugin: 'java'
apply plugin: 'sonar-runner'
apply plugin: 'org.sonarqube'
buildscript {
   classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2"
}
sonarqube {
    properties {
        property "sonar.sourceEncoding", "UTF-8"
     }
 }

關(guān)于Gradle更詳細(xì)的配置,可以參考:SonarQube與Gradle集成
在工程目錄中執(zhí)行如下命令,便開(kāi)始靜態(tài)檢查過(guò)程,檢查完成后會(huì)將結(jié)果存入數(shù)據(jù)庫(kù),并在前臺(tái)界面顯示。

./gradlew clean  sonarqube --stacktrace

分析結(jié)果:


分析結(jié)果

代碼覆蓋率根據(jù)不同的包進(jìn)行圖形化展示:


代碼覆蓋率

單元測(cè)試覆蓋率報(bào)告集成

Jacoco和Cobertura都是用來(lái)統(tǒng)計(jì)java單元測(cè)試覆蓋率的工具,SonarQube本身不具有統(tǒng)計(jì)覆蓋率的功能,它支持導(dǎo)入Jacoco和Cobertura的覆蓋率結(jié)果,然后進(jìn)行界面呈現(xiàn)。
該兩種覆蓋率分析工具都可以通過(guò)在Gradle中集成相關(guān)插件實(shí)現(xiàn)。
JaCoCo插件
Cobertura插件
這塊需要注意的地方,是需要在gradle腳本中的sonarqube任務(wù)中設(shè)置報(bào)告的路徑或者在sonar的界面配置中配置相關(guān)報(bào)告路徑,因?yàn)閷?shí)際上sonar只負(fù)責(zé)展示報(bào)告結(jié)果,分析報(bào)告還是由插件生成的。

sonar支持導(dǎo)入分析結(jié)果報(bào)告

sonar也支持導(dǎo)入自己工程跑出的checkstyle,findbugs等的結(jié)果報(bào)告,同樣,需要在gradle腳本中設(shè)置相關(guān)結(jié)果的報(bào)告路徑或者在界面配置中設(shè)置,具體配置大家自行g(shù)oogle就可以找到,不再贅述。

使用方法

Gradle的使用方法很簡(jiǎn)單,執(zhí)行執(zhí)行以下命令,執(zhí)行完成后,分析結(jié)果會(huì)自動(dòng)導(dǎo)入到數(shù)據(jù)庫(kù)中,并展示在web界面上。

./gradlew clean sonarqube --stacktrace

Q&A

問(wèn)題1

Caused by: The folder 'src/test' does not exist for ':modules:migration' (base directory = /Users/zbao/IdeaProjects/open-lmis/modules/migration)
解決辦法:在migration的src目錄下面創(chuàng)建test目錄
參考:(http://sonarqube-archive.15.x6.nabble.com/Build-fails-if-src-main-does-not-exists-td5027877.html

問(wèn)題2

Caused by: File [...] can't be indexed twice.
解決辦法:在root project的build.gradle中添加如下配置

    sonarqube {
        properties {
            property "sonar.sources", "src/main"
            property "sonar.tests", "src/test"
        }
    }

參考:(https://github.com/SonarOpenCommunity/sonar-cxx/wiki/FAQ)

問(wèn)題3

Cobertura report not found at /Users/zbao/IdeaProjects/open-lmis/modules/reporting/target/site/cobertura/coverage.xml
將sonar.cobertura.reportPath設(shè)置成報(bào)告路徑,如下:

property "sonar.cobertura.reportPath", "build/report/cobertura/coverage.xml"

也可以通過(guò)SonarQube界面進(jìn)行修改:


通過(guò)界面修改sonar.cobertura.reportPath

參考:(https://github.com/galexandre/sonar-cobertura)(https://stackoverflow.com/questions/24134595/sonar-cobertura-plugin-not-finding-coverage-xml-file)

問(wèn)題4

如何掃描js代碼
參考問(wèn)題2配置sonar.sources屬性,其中包含js代碼即可,同時(shí)保證SonarJS插件已添加(默認(rèn)已經(jīng)安裝)。

問(wèn)題5

JS公共庫(kù)被掃描導(dǎo)致結(jié)果不準(zhǔn)
添加sonar.javascript.exclusions,從參數(shù)可以看出js是需要單獨(dú)指定參數(shù)才能exclude掉不需要分析公共庫(kù)。

property "sonar.javascript.exclusions", "src/main/webapp/public/lib/*,src/main/webapp/public/api-docs/*,src/main/webapp/public/device/*"

也可以通過(guò)界面配置sonar.javascript.exclusions:

js exclusions.png

處理這個(gè)問(wèn)題遇到了比較大的坑,因?yàn)槌薺s代碼外,其他的代碼都使用sonar.exclusions這個(gè)屬性還進(jìn)行剔除,之前并不知道存在sonar.javascript.exclusions這個(gè)屬性,導(dǎo)致在這里搞了好一會(huì)才解決。sonar.exclusions也支持從界面配置:
source file exclusions

(https://docs.sonarqube.org/display/PLUG/SonarJS)

問(wèn)題6

Gradle 2.4集成checkstyle插件報(bào)找不到checkstyle()方法
Gradle低版本bug,將gradle或者gradlew升級(jí)到2.7解決

參考:(https://docs.sonarqube.org/display/SONAR/Narrowing+the+Focus)(https://stackoverflow.com/questions/21323276/sonarqube-exclude-a-directory

問(wèn)題7

Jacoco單元測(cè)試覆蓋率報(bào)告不準(zhǔn)確
需要合并Jacoco單元測(cè)試結(jié)果,此處問(wèn)題暫未解決,解決后進(jìn)行更新

問(wèn)題8

Exception in thread "main" java.lang.ClassNotFoundException: org.jacoco.agent.rt.internal_932a715.PreMain
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
FATAL ERROR in native method: processing of -javaagent failed
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:304)
    at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)

解決辦法,加入 tasks.withType(Test) {
systemProperties['user.dir'] = workingDir
}:

    tasks.withType(Test) {
        systemProperties['user.dir'] = workingDir
    }

參考:(https://discuss.gradle.org/t/jacoco-multiproject-build-cant-load-jacocoagent/11540)

相關(guān)資料

gradle-cobertura-plugin
SonarJava插件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容