jenkins-集成SonarQube

阅读量: zyh 2020-04-25 11:16:11
Categories: > Tags:

简介

sonarqube 自动代码审查工具,检查代码错误、漏洞等。

可以与现有的工作流程集成,实现跨项目分支和拉取请求的持续代码检查。

image-20220508163208673

image-20220508162806575

上述描述中几个组件的关系图:

image-20220508163300942

硬件准备

image-20220508155911358

软件配置

image-20220508155947747

安装 sonarqube

https://www.sonarqube.org/downloads/

基于docker方式

不过这种方式下数据库默认是个非生产数据库

## 创建数据目录
mkdir -p /data/cicd/sonarqube/{sonarqube_conf,sonarqube_extensions,sonarqube_logs,sonarqube_data}
chmod 777 -R /data/cicd/sonarqube/

## 运行
docker run  -itd  --name sonarqube \
    -p 9000:9000 \
    -v /data/cicd/sonarqube/sonarqube_conf:/opt/sonarqube/conf \
    -v /data/cicd/sonarqube/sonarqube_extensions:/opt/sonarqube/extensions \
    -v /data/cicd/sonarqube/sonarqube_logs:/opt/sonarqube/logs \
    -v /data/cicd/sonarqube/sonarqube_data:/opt/sonarqube/data \
    sonarqube:7.9.6-community

## 验证
docker logs -f sonarqube


## 将上一个步骤容器里生成的lib目录复制到宿主机

mkdir -p /data/cicd/sonarqube/sonarqube_lib
cd  /data/cicd/sonarqube/sonarqube_lib
docker cp sonarqube:/opt/sonarqube/lib/* ./

docker run  -itd  --name sonarqube \
    -p 9000:9000 \
    -v /data/cicd/sonarqube/sonarqube_conf:/opt/sonarqube/conf \
    -v /data/cicd/sonarqube/sonarqube_extensions:/opt/sonarqube/extensions \
    -v /data/cicd/sonarqube/sonarqube_logs:/opt/sonarqube/logs \
    -v /data/cicd/sonarqube/sonarqube_data:/opt/sonarqube/data \
    -v /data/cicd/sonarqube/sonarqube_lib:/opt/sonarqube/lib \
    sonarqube:7.9.6-community

访问地址: http://ip:9000

账户密码:admin/admin

基于二进制安装方式

image-20220508160136785

安装 sonarqube 中文插件

image-20220508170131292

如果自动安装不上,可能需要手动安装

https://www.yuque.com/zeyangli/wmaaq7/pcgq4k

选择对应的版本:

https://github.com/xuhuisheng/sonar-l10n-zh/tree/sonar-l10n-zh-plugin-8.8#the-chinese-translation-pack-for-sonarqube

下载对应的版本:

https://github.com/xuhuisheng/sonar-l10n-zh/releases/tag/sonar-l10n-zh-plugin-1.29

cd /data/cicd/sonarqube/sonarqube_extensions/downloads
wget https://github.com/xuhuisheng/sonar-l10n-zh/releases/download/sonar-l10n-zh-plugin-1.29/sonar-l10n-zh-plugin-1.29.jar
chmod +x sonar-l10n-zh-plugin-1.29.jar

docker restart sonarqube

配置 sonarqube

开启强制认证

image-20220508160310946

安装 sonar-scanner 到 jenkins slave

https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner

命令行方式安装

$ wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.0.2311-linux.zip
$ tar zxf sonar-scanner-xxxx.tar.gz -C /usr/local
$ vim /etc/profile
export SCANNER_HOME=/usr/local/sonar-scanner-4.6.0.2311-linux
export PATH=$PATH:$SCANNER_HOME/bin

$ source /etc/profile 
$ sonar-scanner -v
INFO: Scanner configuration file: /usr/local/sonar-scanner-4.6.0.2311-linux/conf/sonar-scanner.properties
INFO: Project root configuration file: NONE
INFO: SonarScanner 4.6.0.2311
INFO: Java 11.0.3 AdoptOpenJDK (64-bit)
INFO: Linux 4.18.0-80.el8.x86_64 amd64

docker 方式安装

docker run \
    --rm \
    -e SONAR_HOST_URL="http://${SONARQUBE_URL}" \
    -e SONAR_LOGIN="myAuthenticationToken" \
    -v "${YOUR_REPO}:/usr/src" \
    sonarsource/sonar-scanner-cli 

sonar-scanner 的使用

两种方式:

加载配置文件方式:sonar-project.properties

# 定义唯一的关键字
sonar.projectKey=devops-hello-service

# 定义项目名称
sonar.projectName=My project

# 定义项目的版本信息
sonar.projectVersion=1.0
 
# 指定扫描代码的目录位置(多个逗号分隔)
sonar.sources=.
 
# 执行项目编码
sonar.sourceEncoding=UTF-8

# sonarqube 的地址、账户、密码
sonar.host.url=
sonar.login
sonar.password

命令行方式:

# 指定配置文件
sonar-scanner -Dproject.settings=myproject.properties

# 命令行传参
sonar-scanner -Dsonar.projectKey=myproject -Dsonar.sources=src1

扫java项目

👙sonarqube 先安装java语言规则插件:Java code quality and security

sonar-scanner 扫描java项目会使用一些文件:

image-20220508173652730

sonar.links.ci = 项目对应的 jenkins 地址

sonar.links.homepage = 项目对应的 git 地址,对应扫描后的项目报告里的项目主页

sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \
-Dsonar.projectKey=devops-maven-service \
-Dsonar.projectName=devops-maven-service \
-Dsonar.projectVersion=1.0 \
-Dsonar.login=admin \
-Dsonar.password=admin \
-Dsonar.ws.timeout=30 \
-Dsonar.projectDescription="my first project!" \
-Dsonar.links.homepage=http://192.168.1.200/devops/devops-maven-service \
-Dsonar.links.ci=http://192.168.1.200:8080/job/demo-pipeline-service/ \
-Dsonar.sources=src \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.java.binaries=target/classes \
-Dsonar.java.test.binaries=target/test-classes \
-Dsonar.java.surefire.report=target/surefire-reports

扫前端项目

插件:SonarJS

sonar-scanner -Dsonar.projectKey=devops-web-service \
-Dsonar.projectName=devops-web-service \
-Dsonar.projectVersion=1.0 \
-Dsonar.sources=src \
-Dsonar.host.url=http://192.168.1.200:9000 \
-Dsonar.login=admin \
-Dsonar.password=admin \
-Dsonar.sourceEncoding=UTF-8
#sonar.sources=dist/static/js

扫golang项目

插件:SonarGo

sonar-scanner -Dsonar.projectKey=devops-golang-service \
-Dsonar.projectName=devops-golang-service \
-Dsonar.sources=src \
-Dsonar.login=admin \
-Dsonar.password=admin \
-Dsonar.host.url=http://192.168.1.200:9000


## 有测试用例的情况
sonar.exclusions=**/*_test.go
sonar.tests=.
sonar.test.inclusions=**/*_test.go

登录方式集成

ldap 集成

👙截图里配置要写入到 sonarqube 的主配置文件里

image-20220508160503633

gitlab 集成

安装 gitlab auth 插件并重启

gitlab 创建应用

👙redirect uri 的格式必须是截图里的格式,主地址是 sonarqube 地址。

image-20220508161323615

sonarqube 配置 gitlab auth 插件,填写上面创建的 gitlab 应用信息

image-20220508161250818

正式集成到jenkins

安装 jenkins 插件: SonarQube Scanner,这个插件有以下优点:

配置 SonarQube Scanner 插件:

image-20220508185130593

image-20220508185237920

👙下面两个文件和文章:jenkins-集成gitlab 里的代码并不太一致。

Jenkinslib:https://github.com/Spinestars/jenkins/blob/master/src/org/devops/sonarqube.groovy

Jenkinsfile:https://github.com/Spinestars/jenkins/blob/master/ci.jenkinsfile

sonarqube 规则定义

image-20220508191140263

sonarqube 质量阈

超过质量阈,sonarqube 项目会报错。

image-20220508191231710

超过质量阈退出流水线

Jenkinslib:https://github.com/Spinestars/jenkins/blob/master/src/org/devops/sonarqube.groovy

质量阈接口的返回json。上述代码用到了这个接口返回值。

image-20220508205946591

涉及的代码如下:

    //获取扫描结果, 如果超出质量阈,则执行 error 关键词,退出流水线。
    result = GetProjectStatus(projectName)
    println(result)
    if (result.toString() == "ERROR"){
        mytools.EmailUser(userEmail,"代码质量阈错误")
        error " 代码质量阈错误!请及时修复!"
    } else {
        println(result)
    }
    
    ...
    

def HttpReq(reqType,reqUrl,reqBody){
    def sonarServer = "http://192.168.1.200:9000/api"
   
    response = httpRequest authentication: '4675830a-4330-4dd6-9185-cf62161967f0',
            httpMode: reqType, 
            contentType: "APPLICATION_JSON",
            consoleLogResponseBody: true,
            ignoreSslErrors: true, 
            requestBody: reqBody,
            url: "${sonarServer}/${reqUrl}"
            //quiet: true
    
    return response
}


//获取Sonar质量阈状态
// 这个接口从 sonarqube 项目详情页里通过F12就可以看到,是一个get请求,并返回json字符串,包含质量阈的结果
def GetProjectStatus(projectName){
    apiUrl = "project_branches/list?project=${projectName}"
    response = HttpReq("GET",apiUrl,'')
    
    response = readJSON text: """${response.content}"""
    result = response["branches"][0]["status"]["qualityGateStatus"]
    
    //println(response)
    
   return result
}

自动绑定规则和质量阈到项目

Api地址:http:///web_api/api/

image-20220508212018844

Jenkinslib:https://github.com/Spinestars/jenkins/blob/master/src/org/devops/sonarqube.groovy

查找项目

接口返回数据,通过判断 total 是否为 0,来判断项目是否存在。

image-20220508212753835

涉及代码:

    //搜索项目, 返回项目是否存在的结果
    result = SerarchProject(projectName)
    println(result)
    
    //判断项目是否存在
    if (result == "false"){
        println("${projectName}---项目不存在,准备创建项目---> ${projectName}!")
        CreateProject(projectName)
    } else {
        println("${projectName}---项目已存在!")
    }
    
...

//搜索Sonar项目
def SerarchProject(projectName){
    apiUrl = "projects/search?projects=${projectName}"
    response = HttpReq("GET",apiUrl,'')

    response = readJSON text: """${response.content}"""
    result = response["paging"]["total"]

    if(result.toString() == "0"){
       return "false"
    } else {
       return "true"
    }
}

新建项目

//创建Sonar项目
def CreateProject(projectName){
    apiUrl =  "projects/create?name=${projectName}&project=${projectName}"
    response = HttpReq("POST",apiUrl,'')
    println(response)
}

更新语言规则集

👙需要先在 sonarqube 服务上定义好质量规则

    // 绑定项目质量规则,从项目名里获取质量规则名.
    // 项目名规则: 质量规则名-项目名
    qpName=projectName.split("-")[0]   //anyops
    //qpName="myjava"

    if (projectType == "npm"){
        ConfigQualityProfiles(projectName,"js",qpName)
        ConfigQualityProfiles(projectName,"ts",qpName)
    } else if (projectType == "maven") {
        ConfigQualityProfiles(projectName,"java",qpName)
    }
    
...

//绑定项目质量规则

def ConfigQualityProfiles(projectName,lang,qpname){
    apiUrl = "qualityprofiles/add_project?language=${lang}&project=${projectName}&qualityProfile=${qpname}"
    response = HttpReq("POST",apiUrl,'')
    println(response)
}

获取质量阈ID

要绑定质量阈到项目,需要先获取质量阈ID

其API地址是:http:///api/qualitygates/show?name=<质量阈规则名>

json数据

image-20220508224048527

代码如下:

//获取质量阈ID
def GetQualtyGateId(gateName){
    apiUrl= "qualitygates/show?name=${gateName}"
    response = HttpReq("GET",apiUrl,'')
    response = readJSON text: """${response.content}"""
    result = response["id"]
    
    return result
}

绑定质量阈到项目

    //配置质量阈
    ConfigQualityGates(projectName,qpName)
    
...

//配置项目质量阈

def ConfigQualityGates(projectName,gateName){
    gateId = GetQualtyGateId(gateName)
    apiUrl = "qualitygates/select?gateId=${gateId}&projectKey=${projectName}"
    response = HttpReq("POST",apiUrl,'')
    println(response)println(response)
}

扫描结果输出到 gitlab 的 commit 上

仅支持 sonarqube 6.7 版本,通过在 sonar-scanner 添加额外的命令行参数启用。

教程链接:https://youdianzhishi.com/web/course/1013/1290

配置 sonarqube 多分支模式的支撑

默认社区版 sonarqube 不支持多分支项目。不过这个插件本身作者是不保证持续维护的。

两种方式使用这个多分支插件。

第一种,使用作者打包好的 docker 镜像:https://hub.docker.com/r/mc1arke/sonarqube-with-community-branch-plugin

第二种,在社区版里添加插件

插件地址:https://github.com/mc1arke/sonarqube-community-branch-plugin

插件安装方法:

  1. Copy the plugin JAR file to the extensions/plugins/ directory of your SonarQube instance
  2. Add -javaagent:./extensions/plugins/sonarqube-community-branch-plugin-${version}.jar=web to the sonar.web.javaAdditionalOpts property in your Sonarqube installation’s config/sonar.properties file, e.g. sonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.8.0.jar=web
  3. Add -javaagent:./extensions/plugins/sonarqube-community-branch-plugin-${version}.jar=ce to the sonar.ce.javaAdditionalOpts property in your Sonarqube installation’s config/sonar.properties file, e.g. sonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.8.0.jar=ce
  4. Start Sonarqube, and accept the warning about using third-party plugins

扫描的时候加上额外的参数:-Dsonar.branch.name = branch_name (e.g master)

最终效果:

image-20220508231335349