持續檢查 C# 程式碼品質

SonarQube 是一套 程式碼品質檢查工具,可以幫我們檢查 code 的 bugs、 vulenrability、code smell 與 duplication,也屬於 持續整合 重要的一環。

SonarQube 已經內建 SonarC#,可以直接對 C# 進行檢查,本文將以 .NET Core 為例,並搭配 Jenkins 自動執行 SonarQube,將結果通知 Slack。

Version


macOS High Sierra 10.13.4
SonarQube 6.7.2 LTS
Jenkins 2.107.1
Slack 3.0.5
.NET Core 2.0.6

GitHub


將 .NET Core 專案放到 GitHub。

lack00

  1. 本文將 .NET Core 專案放在 https://github.com/oomusou/Core2JenkinsSonarQubeSlack

當然也可以將 git repository 放在不同的 git server,如 Bitbucket

SonarQube


安裝 SonarQube

1
2
$ brew update
$ brew install sonarqube

使用 Homebrew 安裝 SonarQube。

lack00

  1. 輸入 brew install sonarqube 安裝
  2. 若想在每次 Mac 重開機就自動執行 SonarQube,輸入 brew services start sonarqube
  3. 若想自行啟動 SonarQube,輸入 sonar console

啟動 SonarConsole

1
$ sonar console

使用 sonar console 自行啟動 SonarQube。

lack00

  1. 輸入 sonar console 自行啟動 SonarQube

測試 SonarQube

lack00

  1. 輸入 localhost:9000,若看到 SonarQube 首頁,則表示安裝成功
  2. 右上角 Log in 可登入管理設定 SonarQube,預設為 admin/admin

SonarQube Scanner


SonarQube 雖然已經包含 SonarC#,但必須靠 SonarQube Scanner 才能執行,預設 SonarQube 並沒有包含 Scanner,必須自行安裝。

下載 Scanner

hp00

Analyzing with SonarQube Scanner 下載 Scanner,選擇 Mac OS X 64 bit 下載。

lack00

下載後為一 zip 壓縮檔,解壓縮後可安裝在任何目錄。

lack00

  1. 選擇 home directory
  2. sonar-scanner-3.1.0.1141-macosx 放在 home directory 下

設定 Server

sonar-scanner.properties

1
2
#----- Default SonarQube server
sonar.host.url=http://localhost:9000

設定 SonarQube server 位址,並將 # 註解拿掉。

lack00

  1. sonar-scanner.properties 位於 sonar-scanner-3.1.0.1141-macosx/conf/ 目錄下

測試 Scanner

將 SonarQube Scanner 加到 system path。

.zshrc
lack00

  1. ~/sonar-scanner-3.1.0.1141-macosx/bin 目錄加到 system path
1
~/MyProject $ sonar-scanner -Dsonar.projectKey=NETCore2 -Dsonar.sources=. -Dsonar.projectName=NETCore2 -Dsonar.projectVersion=1.0

使用 sonar-scanner 對 Laravel 專案進行檢查。

  • -D : 對 SonarQube 的 property 進行設定
  • sonar.projectKey:SonarQube 對專案的 key,內部將以此 key 作為辨別,必須唯一
  • sonar.sources:SonarQube 要檢查的目錄,因為已經在專案目錄下,. 即為 目前目錄
  • sonar.projectName:在 SonarQube 網頁上顯示的名稱
  • sonar.projectVersion:在 SonarQube 網頁上顯示的版本編號

lack00

  1. 在專案目錄下輸入 sonar-scanner 檢查 C#

lack01

  1. 若能看到 EXECUTION SUCCESS,則表示 SonarQube Scanner 安裝成功

lack01

進入 SonarQube 網頁,就可看到 NETCore2 專案已經出現 SonarQube。

到目前為止,SonarQube 對 C# 的檢查已經完成,就算只將 SonarQube 裝在本機,也對 C# 程式碼品質的檢查有很大的幫助。

若每次 SonarQube 檢查完,都能將結果送到 Slack,讓 Slack 成為實質的 持續整合 中心,那就太好了。

Slack


新增 Channel

lack01

  1. 按下 Channels 右側的 + 新增 channel

lack01

  1. Privacy : 設定為 PublicPrivate channel
  2. Name : 設定 channel 名稱
  3. Purpose : channel 的功能描述,可以不輸入
  4. Send invites to : 設定 channel 成員,可以稍後再設定
  5. Create Channel 開始建立 channel

lack01

  1. Got It! 進入 channel

lack01

  1. 正式進入 channel,將來 SonarQube 訊息會傳進此 channel

新增 Notification

lack01

  1. 選擇右上方的 option
  2. 選擇 Add an app

新增 Incoming WebHooks

lack01

Slack 將開啟瀏覽器

  1. 稍微往下捲輸入 webhook
  2. 選擇 Incoming WebHooks

新增 Configuration

lack01

  1. Add Configuration 加入 Jenkins CI

新增 Integration

lack01

  1. Add Incoming WebHooks Integration 正式加入整合

Slack 設定完成

lack02

  1. 介紹 SonarQube 設定流程

Slack 部分已經設定完成,接下來是 SonarQube 的設定

Slack 網頁先不要關閉,稍後會用到

SonarQube Slack Notifier


SonarQube 預設並沒有辦法直接對 Slack 發出 notification,必須另外安裝 CKS Sonar Slack Notifier Plugin

下載 Plugin

lack02

安裝 Plugin

lack02

cks-slack-notifier-2.1.2.jar 複製到 /usr/local/Cellar/sonarqube/7.0/libexec/extensions/plugins 目錄下。

因為 Homebrew 會將 app 安裝在 /usr/local/Cellar/ 目錄下

設定 Plugin

lack02

重新啟動 SonarQube:

  1. Administration 下會發現多了 Slack
  2. 選擇 Slack
  3. Slack web integration hook:設定 Slack web integration hook
  4. Plugin enabledenable

Q: Slack web integration hook 該填什麼呢?

lack02

回到 Slack 最後的網頁往下捲到 Webhook URL

  1. Webhook URL 的一長串 URL 複製,貼到 SonarQube 的 Slack web integration hook

最後按 Save 存檔。

設定 Project 與 Channel

雖然已經設定了 SonarQube 的 Webhook URL,但還要繼續設定 project 與所對應的 Slack channel,才會正式開啟 notification。

lack02

  1. Project Key: 設定 SonarQube 的 project key
  2. Slack channel:設定所要通知 Slack channel

最後按 Save 存檔。

測試 Plugin

1
~/MyProject $ sonar-scanner -Dsonar.projectKey=NETCore2 -Dsonar.sources=. -Dsonar.projectName=NETCore2 -Dsonar.projectVersion=1.0

重新執行 sonar-scanner

lack02

  1. 重新在專案目錄下輸入 sonar-scanner 檢查 C#

lack02

  1. Slack 會收到 SonarQube 檢查的結果

實務上 SonarQube 還會與其他 CI server 合作,接下來將以 Jenkins 為例,介紹如何以 Jenkins 自動化 SonarQube。

Jenkins


安裝 Jenkins

1
$ brew install jenkins-lts

使用 Homebrew 安裝 Jenkins。

lack02

  1. 輸入 brew install jenkins-lts 安裝
  2. 若想在每次 Mac 重開機就自動執行 Jenkins,輸入 brew services start jenkins-lts
  3. 若想自行啟動 Jenkins,輸入 jenkins-lts

啟動 Jenkins

1
$ jenkins-lts

使用 jenkins-lts 自行啟動 Jenkins。

lack02

Unlock Jenkins

lack03

  1. 輸入 localhost:8080,看到 Unlock Jenkins,開始設定 Jenkins
  2. 預設密碼放在 ./jenkins/secrets/initialAdminPassword

Customize Jenkins

lack03

  1. 選擇 Install suggested plugins 即可

Getting Started

lack03

安裝 default plugin 中。

Create Admin User

lack03

  1. 建立管理者帳號

Jenkins is Ready

lack03

  1. Jenkins 安裝完成,按 Start using jenkins 開始使用 Jenkins

Welcome to Jenkins

lack03

  1. 進入 Jenkins 管理介面,如此 Jenkins 已經設定成功

SonarQube Scanner for Jenkins


要讓 Jenkins 能自動執行 SonarQube Scanner,必須另外安裝 plugin。

安裝 SonarQube Scanner for Jenkins

lack03

  1. 左側選擇 Manage Jenkins
  2. 右側選擇 Manage Plugins

lack03

  1. 選擇 SonarQube Scanner
  2. Download now and install after restart

lack03

安裝 plugin 中。

  1. Restart Jenkins when installation is complete and no jobs are running 打勾

設定 SonarQube 環境變數

lack03

  1. 左側選擇 Manage Jenkins
  2. 右側選擇 Configure System

lack04

  1. 找到 SonarQube servers 區段
  2. Enable injection of SonarQube server configuration as build environment variables 打勾
  3. 設定 SonarQube server 名稱與網址

最後按 ApplySave 儲存設定。

設定 SonarQube Scanner 環境變數

lack04

  1. 左側選擇 Manage Jenkins
  2. 右側選擇 Global Tool Configuration

lack04

  1. 找到 SonarQube Scanner 區段
  2. 設定 SonarQube Scanner 名稱

最後按 ApplySave 儲存設定。

Jenkins Job


Source Code Management

lack04

  1. 選擇 Job,按左側 Configure

lack04

  1. 找到 Source Code Management 區段
  2. 將 Git 的 Repository URL 設定到 https://github.com/oomusou/Core2JenkinsSonarQubeSlack

Build

lack04

  1. 找到 Build 區段
  2. Add build step 選擇 Execute SonarQube Scanner

lack04

1
2
3
4
sonar.projectKey=NETCore2
sonar.sources=.
sonar.projectName=NETCore2
sonar.projectVersion=1.0

Analysis properties 加上以上設定。

1
~/MyProject $ sonar-scanner -Dsonar.projectKey=NETCore2 -Dsonar.sources=. -Dsonar.projectName=NETCore2 -Dsonar.projectVersion=1.0

還記得之前曾經下過以上指令嗎?就是將這些 SonarQube property 設定在 Jenkins,改由 Jenkins 幫我們傳。

lack04

  1. 按左側 Build Now 執行 Job
  2. 執行成功後會出現 OKSuccess

lack04

剛剛 Jenkins 執行的 Project 出現在 SonarQube 上。

lack04

  1. Slack 也再次收到 SonarQube 檢查的結果

Conclusion


  • SonarQube 已經內建 SonarC#,也可以用來檢查 C# 與 .NET Core
  • 就算不將 SonarQube 安裝在 server,安裝在本機也能有效的檢查 C# 程式碼品質
  • SonarQube 也能將檢查結果推送到 Slack
  • 藉由 Jenkins 幫忙,我們就可以自動化執行 SonarQube

Sample Code


完整的範例可以在我的 GitHub 上找到

Reference


SonarQube, SonarQube Downloads
SonarQube, Analyzing with SonarQube Scanner
SonarQube, Analying with SonarQube Scanner for Jenkins
Jenkins, SonarQube Scanner
Antti Koivisto, CKS Sonar Slack Notifier Plugin