串接 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:9000open in new window 開啟 Web 介面

建立 sonarcube 專案

在 sonar 上建立 manual project

  1. Create new project - manual
  2. 設定 Project key, Display name
  3. 產生一組 token 並妥善保存
  4. 執行分析專案,此步驟需下載 scanner

下載 scanner

根據環境可以在此open in new window下載不同的 scanner

CI 串接

以 Github 舉例

  1. 創建 Github App 並安裝到目標專案的 Organization
  2. 設定 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 使用,並根據這個教學open in new window進行 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

但實際上原因可能是參數會相關設定錯誤導致,可參考這篇討論串open in new window

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
Last Updated:
Contributors: johnnywang