串接 Sonarcube 筆記
SonarQube 是一款基於 Java 開發的原始碼檢測與品質管理系統,因著 Java 的關係,Server 與 Client 都是跨平台的
Install
docker image
$ docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest
前往 http://localhost:9000 開啟 Web 介面
建立 sonarcube 專案
在 sonar 上建立 manual project
- Create new project - manual
- 設定 Project key, Display name
- 產生一組 token 並妥善保存
- 執行分析專案,此步驟需下載 scanner
下載 scanner
根據環境可以在此下載不同的 scanner
CI 串接
以 Github 舉例
- 創建 Github App 並安裝到目標專案的 Organization
- 設定 sonarcube 專案
Webhooks
加入 PR Webhook
PR Decoration
sonar.com > Your project > Project Settings > General Settings > Pull Request Decoration
Quality Profiles
根據專案需求,在設定頁面裡的 Quality Profiles
加入對掃描的套用規範
- CSS: sonar way
設定 package.json 產生 coverage report
{
"scripts": {
"test:ci": "jest --ci --collectCoverage"
}
}
設定 sonar-project.properties
建立專案後,需要產生一組 sonar_login_token
使用,並根據這個教學進行 sonar 的 project 配置
sonar.host.url= http://localhost:9000
sonar.login=your_login_token
sonar.projectBaseDir=./
# sonar 上的專案名稱
sonar.projectKey=your_project_name
# test coverage report 位置
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# scanner 規則設定
sonar.sources=src
sonar.eslint.eslintconfigpath=.eslintrc.js
sonar.typescript.tsconfigPath=tsconfig.json
sonar.coverage.exclusions=**/node_modules/**, **.spec.ts, **.test.ts, **.spec.js, **.test.js, **/*.html, **/next.config.js
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
# 專案位置
sonar.analysis.repoLink=path_to_your_repository
設定 drone.yml
以下範例,配置 jest 產生 report,並接著執行 sonar scanner
需要注意,因為 sonar scanner 會根據傳入的參數判斷是 push 或是 pull_request,如果傳入參數裡有 pull request 相關設定,即使是 null 值,一樣會被判定成 pull_request,這樣會導致實際 merge 進 main branch 時沒有被正確解析,而是被當成 pull_request 處理了,發生這問題時錯誤提示只會顯示
“master” branch has not been analyzed yet and you have multiple branches already
但實際上原因可能是參數會相關設定錯誤導致,可參考這篇討論串
kind: pipeline
name: default
trigger:
branch: ["main", "precommit/*"]
event: ["push", "pull_request"]
steps:
- name: prepare
image: "node:16.13.1"
commands:
- "npm run lint"
- "npm run test:ci"
- name: sonar-scan
image: sonarsource/sonar-scanner-cli
environment:
SONAR_TOKEN:
from_secret: sonar_login_token
commands:
- "if (echo $DRONE_TARGET_BRANCH$DRONE_PULL_REQUEST | grep -w $DRONE_TARGET_BRANCH); then sonar-scanner; else sonar-scanner -Dsonar.pullrequest.key=$DRONE_PULL_REQUEST -Dsonar.pullrequest.branch=$DRONE_SOURCE_BRANCH -Dsonar.pullrequest.base=$DRONE_TARGET_BRANCH; fi;"
depends_on:
- prepare