SonarQube整合gitlab/jenkins

kaliarch發表於2019-08-11

一 概述

對於專案程式碼質量管理,在目前的微服務/模組化/快迭代敏捷開發中如果僅依賴IDE簡單檢查和人為的codereview對於大量程式碼很不適合,不僅僅依靠開發人員的編碼規範編碼及注意程式健壯性,同時需要一些工具來幫助我們提前預防和強制檢測規範。

Sonarqube 是一款程式碼分析檢測工具,將其與devops結合,例如整合到gitlab ci/cd或jenkins中實現部署自動程式碼檢查,及時發現並處理bug,最大限度的將bug和不規範扼殺在編碼階段,其內部整合很多分析工具,比如pmd-cpd、checkstyle、findbugs、Jenkins,從七個方面幫我們來原始碼質量管理。此文章安裝最新版SonarQube-7.9.1,此版本不支援自定義資料庫MySQL,jdk需要安裝高版本11。

1.1 特點

  • 檢查程式碼是否遵循程式設計標準:如命名規範,編寫的規範等。

  • 檢查設計存在的潛在缺陷:SonarQube 通過外掛 Findbugs、Checkstyle 等工具檢測程式碼存在的缺陷。

  • 檢測程式碼的重複程式碼量:SonarQube 可以展示專案中存在大量複製貼上的程式碼。

  • 檢測程式碼中註釋的程度:原始碼註釋過多或者太少都不好,影響程式的可讀可理解性。

  • 檢測程式碼中包、類之間的關係:分析類之間的關係是否合理,複雜度情況。

1.2 元件

  • SonarQube Server:sonarqube服務端,接受客戶端掃描報告
  • SonarQube Database:ES/及資料庫引擎oracle,postgresql,mssql
  • SonarQube Plugins:可以後期在sonarqube服務端安裝外掛
  • SonarQube Scanner:安裝在客戶端掃描工具

1.3 架構圖

SonarQube整合gitlab/jenkins

開發人員把程式碼push到SCM(如gitlab)->jenkins構建定義好的job,然後通過jenkins 外掛(sonar scanner)分析原始碼->jenkins/gitlab-ci 中的scanner客戶端把分析報告發到sonarqube server

二 安裝部署

2.1 SonarQube Server安裝

2.1.1 宿主機測試環境簡單部署

# 下載
wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.9.1.zip
# 解壓
/opt/sonarqube/
unzip /opt/sonarqube/bin/[OS]/sonar.sh console

# 登入宿主機http://localhost:9000 (admin/admin)
複製程式碼

2.1.2 宿主機生產環境部署

# 宿主機requirementes
sysctl -w vm.max_map_count=262144
sysctl -w fs.file-max=65536
ulimit -n 65536
ulimit -u 4096

cat >> /etc/sysctl.conf  << EOF
vm.max_map_count=262144
fs.file-max=65536
EOF


# sonarqube不能用root使用者執行
useradd sonarqube
echo "sonarqubepwd" | passwd --stdin sonarqube

# 檢查系統
[root@devops-sonarqube ~]# grep SECCOMP /boot/config-$(uname -r)
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y
CONFIG_SECCOMP=y

cat > /etc/security/limits.d/99-sonarqube.conf <<EOF
sonarqube   -   nofile   65536
sonarqube   -   nproc    4096
EOF

# sonarqube es需要安裝安裝jdk11
yum -y install java-11-openjdk.x86_64


# 7.9最新版本不支援mysql,資料庫支援MSSQL/Oracle/PostgreSQL
# 安裝PostgreSQL
# 建立sonarqube使用者,授權使用者create, update, and delete許可權
# 如果想自定義資料庫名稱,不用pulic,則需要搜尋路徑修改
yum install -y https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm
yum install -y postgresql96-server postgresql96-contrib
/usr/pgsql-9.6/bin/postgresql96-setup initdb
systemctl start postgresql-9.6
systemctl enable postgresql-9.6
su - postgres
psql
create user sonarqube with password 'sonarqube';
create database sonarqube owner sonarqube;
grant all  on database sonarqube to sonarqube;
\q 

# 檢視postgresql監聽
vi /var/lib/pgsql/9.6/data/postgresql.conf

# 配置白名單
vi /var/lib/pgsql/9.6/data/pg_hba.conf
host    all              all             127.0.0.1/32           md5
#重啟服務
systemctl restart postgresql-9.6

ss -tan | grep 5432
# 建立庫/使用者,並授權
psql -h 127.0.0.1 -p 5432  -U postgres


# 下載軟體包
cd /opt && wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.9.1.zip
ln -sv sonarqube-7.9.1 sonarqube
chown sonarqube.sonarqube sonarqube/* -R

# 切換到系統sonarqube使用者開始安裝
su - sonarqube

# 設定資料庫訪問,編輯$SONARQUBE-HOME/conf/sonar.properties
sonar.jdbc.username=sonarqube
sonar.jdbc.password=sonarqube
# 注意為127.0.0.1
sonar.jdbc.url=jdbc:postgresql://127.0.0.1/sonarqube

# 配置ES儲存路徑,編輯SONARQUBE-HOME/conf/sonar.properties 
sonar.path.data=/var/sonarqube/data
sonar.path.temp=/var/sonarqube/temp

# 配置web server,編輯SONARQUBE-HOME/conf/sonar.properties
sonar.web.host=192.0.0.1
sonar.web.port=80
sonar.web.context=/sonarqube

# web伺服器效能調優
$SONARQUBE-HOME/conf/sonar.properties
sonar.web.javaOpts=-server


$SONARQUBE-HOME/conf/wrapper.conf 
wrapper.java.command=/path/to/my/jdk/bin/java


# 執行啟動指令碼
Start:
$SONAR_HOME/bin/linux-x86-64/sonar.sh start

Graceful shutdown:
$SONAR_HOME/bin/linux-x86-64/sonar.sh stop

Hard stop:
$SONAR_HOME/bin/linux-x86-64/sonar.sh force-stop

# 外掛安裝
1.Marketplace方式安裝(Administration > Marketplace)
2.手動安裝(將下載好的外掛上傳至伺服器目錄:$SONARQUBE_HOME/extensions/plugins,重啟sonarqube服務)
複製程式碼

2.1.3 docker方式部署

docker pull sonarqube

docker run -d --name sonarqube -p 9000:9000 sonarqube

# 分析mvn專案
# On Linux:
$ mvn sonar:sonar

# With boot2docker:
$ mvn sonar:sonar -Dsonar.host.url=http://$(boot2docker ip):9000

# docker主機系統要求
sysctl -w vm.max_map_count=262144
sysctl -w fs.file-max=65536
ulimit -n 65536
ulimit -u 4096
複製程式碼

2.2 Gitlab整合

2.2.1 sonar-scanner安裝

由於gitlab專案較多,共用了gitlab-runner,因此在gitlab-runner安裝sonner-scanner即可,可通用對構建的專案進行掃描

# 下載安裝
cd /opt && wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.0.0.1744-linux.zip

# 新增進PATH
mv sonar-scanner-4.0.0.1744-linux sonar-scanner
cat > /etc/profile.d/sonar-scanner.sh <<EOF
export PATH=$PATH:/opt/sonar-scanner/bin
EOF
source /etc/profile.d/sonar-scanner.sh

[root@common-runner ~]# sonar-scanner -h
INFO: 
INFO: usage: sonar-scanner [options]
INFO: 
INFO: Options:
INFO:  -D,--define <arg>     Define property
INFO:  -h,--help             Display help information
INFO:  -v,--version          Display version information
INFO:  -X,--debug            Produce execution debug output
複製程式碼

2.2.2 sonarqube web配置專案

Create new project->Provide a token->

SonarQube整合gitlab/jenkins
SonarQube整合gitlab/jenkins

2.2.3 配置gitlab-ci

stages:
  - sonarqube_scan
  - deploy_src
  - install_dependency
  - restart_server
  - check_server

variables:
  RUNNER_BASE_DIR: "/home/gitlab-runner/builds/QFafxxxEq/0/devops/"
  BASE_DIR: "/go2cloud_api/"

job sonarqube_scan_job:
  stage: sonarqube_scan
  # 注意,此使用者為gitlab-runner執行,指定/.為此專案目錄
  script:
    - sonar-scanner -Dsonar.projectKey=go2cloud_api_test -Dsonar.sources=/. -Dsonar.host.url=http://43.xxx.xxx.xxx:9110 -Dsonar.login=a393276xxxxxxxxxxxxxxxxxxx03004a714
  tags:
    - 51common-runner
  only:
    - go2cloud-platform-test
  when: always

job deploy_src_job:
  stage: deploy_src
  script:
    - scp -r ${RUNNER_BASE_DIR}${BASE_DIR}* root@172.16.100.5:/project${BASE_DIR}
  tags:
    - 51common-runner
  only:
    - go2cloud-platform-test
  when: always

複製程式碼

SonarQube整合gitlab/jenkins

提交程式碼測試:

SonarQube整合gitlab/jenkins

檢視執行job

SonarQube整合gitlab/jenkins

檢視sonarqube專案

SonarQube整合gitlab/jenkins

![image-20190810112146155](/Users/xuel/Library/Application Support/typora-user-images/image-20190810112146155.png)

檢視詳情

SonarQube整合gitlab/jenkins

2.3 jenkins整合

可以利用外掛整合,也可以將sonar-scanner 安裝在jenkins服務區上面,每次進行工具掃描。

2.3.1 sonar-scanner安裝

sonar-scanner安裝和gitlab-runner上安裝一樣,詳見:2.2.1 sonar-scanner安裝

可以兩種方式整合:直接在構建的時候執行掃描命令分析報告,外掛形式整合。

2.3.2 整合job

2.3.2.1 指令碼構建整合

在構建的時候利用安裝好的sonar-scanner命令整合

# 配置PATH
export PATH=/data/apps/miniconda3/bin:/data/apps/miniconda3/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/data/apps/miniconda3/bin:/data/apps/software/sonar-scanner/bin:/root/bin
# 指定jenkins的workspace目錄
BASE_DIR=/root/.jenkins/workspace/
# 指定專案名稱,此job的名稱
PROJECT=go2cloud_api_prod_job
# 指定conda中專案的虛擬環境
PROJECT_ENV=go2cloud-api-prod-env
# 切換python環境
source activate ${PROJECT_ENV}
$(which python) -m pip install mock nose coverage
# 更新python環境
echo "++++++++++++++++++++++++++++++更新Python環境+++++++++++++++++++++++++++++++++++++++"

if [ -f ${BASE_DIR}${PROJECT}/requirements.txt ];then
    $(which python) -m pip install -r ${BASE_DIR}${PROJECT}/requirements.txt && echo 0 || echo 0
fi

# 程式碼檢查/單元測試/程式碼測試覆蓋率
echo "+++++++++++++++++++++++++++++++程式碼檢查+++++++++++++++++++++++++++++++++++++++"
cd ${BASE_DIR}
# 生成pylint.xml
$(which pylint) -f parseable --disable=C0103,E0401,C0302 $(find ${PROJECT}/* -name *.py) >${BASE_DIR}${PROJECT}-pylint.xml || echo 0

#echo "+++++++++++++++++++++++++++++++單元測試+++++++++++++++++++++++++++++++++++++++"
# 生成nosetests.xml
#$(which nosetests) --with-xunit --all-modules --traverse-namespace --with-coverage --cover-package=go2cloud-api-deploy-prod --cover-inclusive || echo 0
#$(which nosetests) --with-xunit --all-modules --traverse-namespace --with-coverage --py3where=${PROJECT} --cover-package=${PROJECT} --cover-inclusive || echo 0
#echo "+++++++++++++++++++++++++++++++程式碼覆蓋率+++++++++++++++++++++++++++++++++++++++"
# 生成coverage.xml
# -m coverage xml --include=${PROJECT}* || echo 0

# sonarqube 程式碼掃描
sonar-scanner \
  -Dsonar.projectKey=go2cloud_api_prod \
  -Dsonar.sources=${BASE_DIR}${PROJECT}/. \
  -Dsonar.host.url=http://xxx.xxx.xxx.xxx:9100 \
  -Dsonar.login=2194d90xxxxxxxxxxxxxxxxxxxxxxxxbec7f69
複製程式碼

SonarQube整合gitlab/jenkins

執行專案檢視

SonarQube整合gitlab/jenkins

檢視sonarqube專案

SonarQube整合gitlab/jenkins

SonarQube整合gitlab/jenkins

SonarQube整合gitlab/jenkins

2.3.2.2 外掛形式整合

  • jenkins伺服器scanner配置
# 如果在構建中未指定將掃描報告傳送給server端地址,需要在客戶端中配置,在安裝好scanner的conf目錄下修改:sonar-scanner.properties 服務端的地址
sonar.host.url=http://xxx.xxx.xxx.xxx:9100
複製程式碼
  • jenkins伺服器安裝scanner

    SonarQube整合gitlab/jenkins

  • 工具中配置scanner

SonarQube整合gitlab/jenkins

  • sonarqube server生產token

需要在sonarqube server配置jenkins的api token,用來jenkins將報告傳送給sonarqube server

SonarQube整合gitlab/jenkins

  • 全域性工具配置中新增SonarQube servers

jenkins利用sonarqube的token建立憑據

SonarQube整合gitlab/jenkins

SonarQube整合gitlab/jenkins

  • 構建專案配置

SonarQube整合gitlab/jenkins

根據掃描的程式語言填寫對應的analysis properties,在此填寫專案相關資訊。

如果使用pipeline,可以參考宣告式示例

pipeline {
    agent any
    stages {
        stage('SonarQube analysis 1') {
            steps {
                sh 'mvn clean package sonar:sonar'
            }
        }
        stage("Quality Gate 1") {
            steps {
                waitForQualityGate abortPipeline: true
            }
        }
        stage('SonarQube analysis 2') {
            steps {
                sh 'gradle sonarqube'
            }
        }
        stage("Quality Gate 2") {
            steps {
                waitForQualityGate abortPipeline: true
            }
        }
    }
}

複製程式碼
  • 檢視掃描結果

在jenkins上面配置了projectname,在sonarqube上就不用配置專案

SonarQube整合gitlab/jenkins

三 思考

  • 整合場景由於專案後端為python,在此沒有編譯,java專案需要安裝對應mvn或其他編譯工具,
  • 測試環境之間為gitlab ci/cd,正式環境利用jenkins釋出
  • 對比jenkins指令碼整合和外掛方式整合,可以發現指令碼方式需要在兩邊都配置,而且針對不同的專案,每次都需要申請token和關聯專案筆記比較麻煩,外掛形式一次配置好,就不用在去sonarqube上去配置,之後配置jenkins的job只需要配置簡單的projectname即可,比較方便。

四 錯誤處理

  • Gitlab-runner輸出限制,gitlab介面顯示不全ob's log exceeded limit of 4194304 bytes.

    https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/configuration/advanced-configuration.md#the-runners-section
    複製程式碼

五 參考連結:

相關文章