1 环境准备

1.1 安装sonarqube

/app/module/sonarqube

1.2 安装sonar-scanner

/app/module/sonar-scanner

1.3 安装SonarQube Scanner插件

1.4 Jenkins配置sonar凭据

Jenkins流水线集成Sonarqube_java

1.5 Jenkins配置Sonarqube服务地址

Jenkins流水线集成Sonarqube_java_02

1.6 Jenkins配置Sonar-Scanner

Jenkins流水线集成Sonarqube_Email_03

1.7 sonarqube强制登录

Jenkins流水线集成Sonarqube_Email_04

2 Jenkins项目分析

2.1 手动分析项目

/app/module/sonar-scanner/bin/sonar-scanner \
-Dsonar.host.url=http://192.168.137.130:9000 \
-Dsonar.login=d6cfa716cbebcc03c51f8306f86ced69150e2295 \
-Dsonar.projectKey=web_demo \
-Dsonar.projectName=web_demo \
-Dsonar.projectVersion=1.0 \
-Dsonar.ws.timeout=30 \
-Dsonar.projectDescription='my first project!' \
-Dsonar.links.homepage=http://www.baidu.com \
-Dsonar.sources=src \
-Dsonar.sourceEncoding=UTF-8 \
-Dsonar.java.binaries=target/classes \
-Dsonar.java.surefire.report=target/surefire-reports
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

2.2 配置共享库

/src/org/devops/sonarqube.groovy

package org.devops
//scan
def SonarScan(projectName,projectDesc,projectPath){
    def scannerHome = tool 'sonar-scanner'
    def sonarServer = "http://192.168.137.130:9000"
    def sonarDate = sh  returnStdout: true, script: 'date  +%Y%m%d%H%M%S'
    sonarDate = sonarDate - "\n"
    sh """ 
        ${scannerHome}/bin/sonar-scanner \
        -Dsonar.host.url=${sonarServer} \
        -Dsonar.login=d6cfa716cbebcc03c51f8306f86ced69150e2295 \
        -Dsonar.projectKey=${projectName} \
        -Dsonar.projectName=${projectName} \
        -Dsonar.projectVersion=${sonarDate} \
        -Dsonar.ws.timeout=30 \
        -Dsonar.projectDescription=${projectDesc} \
        -Dsonar.links.homepage=http://www.baidu.com \
        -Dsonar.sources=${projectPath} \
        -Dsonar.sourceEncoding=UTF-8 \
        -Dsonar.java.binaries=target/classes \
        -Dsonar.java.surefire.report=target/surefire-reports
    """
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

2.3 jenkinsfile配置

Jenkins流水线集成Sonarqube_java_05

Jenkins流水线集成Sonarqube_git_06

2.4 构建结果

Jenkins流水线集成Sonarqube_git_07

Jenkins流水线集成Sonarqube_Email_08

2.5 分析项目结果

Jenkins流水线集成Sonarqube_Email_09

Jenkins流水线集成Sonarqube_java_10

3 支持多sonar服务

3.1 配置共享库

/src/org/devops/sonarqube.groovy进行修改

支持多sonar服务
package org.devops
//scan
def SonarScan(sonarServer,projectName,projectDesc,projectPath){
    //定义服务器列表
	//因为SonarQube servers系统设置就配置了一个name为SonarQube
    def servers = ["dev":"SonarQube","test":"SonarQube"]
    withSonarQubeEnv("${servers[sonarServer]}"){
        def scannerHome = tool 'sonar-scanner'
        //def sonarServer = "http://192.168.137.130:9000" 将认证url和token都可以删除了
        def sonarDate = sh  returnStdout: true, script: 'date  +%Y%m%d%H%M%S'
        sonarDate = sonarDate - "\n"
        sh """ 
            ${scannerHome}/bin/sonar-scanner \
            //-Dsonar.host.url=${sonarServer} \
            //-Dsonar.login=d6cfa716cbebcc03c51f8306f86ced69150e2295 \
            -Dsonar.projectKey=${projectName} \
            -Dsonar.projectName=${projectName} \
            -Dsonar.projectVersion=${sonarDate} \
            -Dsonar.ws.timeout=30 \
            -Dsonar.projectDescription=${projectDesc} \
            -Dsonar.links.homepage=http://www.baidu.com \
            -Dsonar.sources=${projectPath} \
            -Dsonar.sourceEncoding=UTF-8 \
            -Dsonar.java.binaries=target/classes \
            -Dsonar.java.surefire.report=target/surefire-reports
        """
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

3.2 Jenkinsfile配置

Jenkins流水线集成Sonarqube_java_11

3.3 分析项目结果

Jenkins流水线集成Sonarqube_git_12

4 Sonarqube项目管理

4.1 规则使用

4.1.1 质量配置

1、新增质量配置

Jenkins流水线集成Sonarqube_java_13

2、给质量配置绑定规则

Jenkins流水线集成Sonarqube_java_14

Jenkins流水线集成Sonarqube_git_15

Jenkins流水线集成Sonarqube_java_16

Jenkins流水线集成Sonarqube_git_17

3、给项目绑定质量规则

Jenkins流水线集成Sonarqube_Email_18

4.1.2 质量阈

Jenkins流水线集成Sonarqube_git_19

Jenkins流水线集成Sonarqube_Email_20

4.1.3 构建结果

Jenkins流水线集成Sonarqube_git_21

4.1.4 分析项目结果

Jenkins流水线集成Sonarqube_git_22

4.2 质量阈错误通知管理员并终止流水线

4.2.1 配置共享库
/src/org/devops/sonarapi.groovy

package org.devops
//封装HTTP
def HttpReq(reqType,reqUrl,reqBody){
    def sonarServer = "http://192.168.137.130:9000/api"
    result = httpRequest authentication: 'sonar-admin-auth',
            httpMode: reqType, 
            contentType: "APPLICATION_JSON",
            consoleLogResponseBody: true,
            ignoreSslErrors: true, 
            requestBody: reqBody,
            url: "${sonarServer}/${reqUrl}"
            //quiet: true
    
    return result
}
//获取Sonar质量阈状态
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
}
//搜索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)
}
//配置项目质量规则
def ConfigQualityProfiles(projectName,lang,qpname){
    apiUrl = "qualityprofiles/add_project?language=${lang}&project=${projectName}&qualityProfile=${qpname}"
    response = HttpReq("POST",apiUrl,'')
    println(response)
}
//获取质量阈ID
def GetQualtyGateId(gateName){
    apiUrl= "qualitygates/show?name=${gateName}"
    response = HttpReq("GET",apiUrl,'')
    response = readJSON text: """${response.content}"""
    result = response["id"]
    return result
}
//配置项目质量阈
def ConfigQualityGates(projectName,gateName){
    gateId = GetQualtyGateId(gateName)
    apiUrl = "qualitygates/select?gateId=${gateId}&projectKey=${projectName}"
    response = HttpReq("POST",apiUrl,'')
    println(response)println(response)
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
4.2.2 创建sonar账号密码凭据

Jenkins流水线集成Sonarqube_java_23

4.2.3 jenkinsfile配置

Jenkins流水线集成Sonarqube_java_24

Jenkins流水线集成Sonarqube_java_25

4.2.4 构建结果

Jenkins流水线集成Sonarqube_git_26

4.2.5 邮箱信息

Jenkins流水线集成Sonarqube_git_27

4.3 查找项目

Jenkins流水线集成Sonarqube_git_28

Jenkins流水线集成Sonarqube_git_29

4.4 新建项目

Jenkins流水线集成Sonarqube_java_30

4.5 配置项目质量规则

Jenkins流水线集成Sonarqube_java_31

Jenkins流水线集成Sonarqube_git_32

Jenkins流水线集成Sonarqube_git_33

Jenkins流水线集成Sonarqube_Email_34

4.6 更新质量阈

Jenkins流水线集成Sonarqube_git_35

Jenkins流水线集成Sonarqube_java_36

Jenkins流水线集成Sonarqube_Email_37

Jenkins流水线集成Sonarqube_git_38

5 附录

5.1 jenkinsfile

#!groovy
@Library('jenkinslib') _
def tools = new org.devops.tools()
def build = new org.devops.build()
def gitlab = new org.devops.gitlab()
def toemail = new org.devops.toemail()
def sonar = new org.devops.sonarqube()
def sonarapi = new org.devops.sonarapi()
def WebHookData = readJSON text : allData
String branch=WebHookData.ref
String userName=WebHookData.user_username
String projectId=WebHookData.project.id
String commitSha=WebHookData.checkout_sha
pipeline {
  agent {
    node {
      label "built-in"
    }
  }
  environment {
    String GsrcUrl="${env.srcUrl}"
    String GbranchName="${env.branchName}"
    String GbuildType="${env.buildType}"
    String GbuildShell="${env.buildShell}"
    String qpName = "demo"   //Sonar%20way
  }
  stages {
    stage('CheckOut') {
      steps {
        script {
          if ("$runOpts" == "GitlabPush"){
              GbranchName = branch - 'refs/heads/'
              currentBuild.description = "Trigger by user ${userName} \n branch: ${GbranchName}"
              gitlab.ChangeCommitStatus(projectId,commitSha,"running")
          }
		  tools.PrintMes("获取代码",'green')
		  checkout scmGit(branches: [[name: "${GbranchName}"]], 
		                  extensions: [cleanBeforeCheckout()], 
		                  userRemoteConfigs: [[credentialsId: '8c8a0774-7d4c-48a9-8f52-dd1a04f71320', 
		                  url: "${GsrcUrl}"]])
        }
      }
    }
    stage("Build") {
      steps {
        script {
          tools.PrintMes("执行打包",'green')
          build.Build(GbuildType,GbuildShell)
        }
      }
    }
    stage('QA') {
      steps {
        script {
          tools.PrintMes("搜索项目",'green')
          result = sonarapi.SerarchProject("${JOB_NAME}")
          println(result)
          if ( result == 'false' ){
            println("${JOB_NAME}---项目不存在,准备创建项目---> ${JOB_NAME}!")
            sonarapi.CreateProject("${JOB_NAME}")
          } else {
            println("${JOB_NAME}---项目已存在")
          }
          tools.PrintMes("配置项目质量规则","green")
          sonarapi.ConfigQualityProfiles("${JOB_NAME}","web",qpName)
          tools.PrintMes("配置质量阈","green")
          sonarapi.ConfigQualityGates("${JOB_NAME}",qpName)
          tools.PrintMes("代码扫描",'green')
          sonar.SonarScan("dev","${JOB_NAME}","${JOB_NAME}","src")
          sh "sleep 20"
          tools.PrintMes("获取扫描结果",'green')
          result = sonarapi.GetProjectStatus("${JOB_NAME}")
          println(result)
          if ( result.toString() == "ERROR" ){
            toemail.Email("代码质量阈错误,请及时修复!",userEmail)
            error "代码质量阈错误,请及时修复!"
          }else {
            println(result)
          }
        }
      }
    }
  }
  post {
    always {
      script {
        println("always")
      }
    }
    success {
      script {
        println("success")
        gitlab.ChangeCommitStatus(projectId,commitSha,"success")
        toemail.Email("流水线成功了",userEmail)
      }
    }
    failure {
      script {
        println("failure")
        gitlab.ChangeCommitStatus(projectId,commitSha,"failed")
        toemail.Email("流水线失败了",userEmail)
      }
    }
    aborted {
      script {
        println("aborted")
        gitlab.ChangeCommitStatus(projectId,commitSha,"canceled")
        toemail.Email("流水线被取消了",userEmail)
      }
    }
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.

5.2 Ldap认证

1.准备工作
获取LDAP服务信息、admin账号、安装sonarldap插件。
 
2.LDAP配置
#LDAP settings
#admin
sonar.security.realm=LDAP
ldap.url=ldap://192.168.1.200:389
ldap.bindDn=cn=admin,dc=devops,dc=com
ldap.bindPassword=ldap12344
#users
ldap.user.baseDn=ou=jenkins,dc=devops,dc=com
ldap.user.request=(&(objectClass=inetOrgPerson)(cn={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail

3.测试验证
重启sonarqube
systemctl restart sonarqube
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

5.3 Gitlab认证

1、安装插件

sonar插件地址:https://github.com/gabrie-allaigre/sonar-auth-gitlab-plugin

安装插件: 下载插件然后通过maven打包然后放入到sonar的插件目录中(/home/sonar/sonarqube/extensions/plugins),重启sonarqube。

2、gitlab配置

创建应用,填写sonar地址(必须是https)

Jenkins流水线集成Sonarqube_git_39

Jenkins流水线集成Sonarqube_Email_40

3、sonarqube配置

配置》gitlab 启动gitlab认证,填写gitlab地址,应用ID,secret信息

Jenkins流水线集成Sonarqube_git_41

Jenkins流水线集成Sonarqube_java_42