zoukankan      html  css  js  c++  java
  • 通过开源插件实现sonarqube区分不同分支显示代码扫描结果

      问题: 


             开源版本sonarqube-server,同一个代码仓库,无法区分不同分支,从而实现按代码的不同分支显示对应分支的扫描结果。

    如上图,所有分支的扫描结果,全部显示为master,而pipeline在checkout代码时,使用的为分支通配符形式。

    解决:

          后经过调查,发现github上面有开源插件,能实现上述功能,github地址如下:https://github.com/mc1arke/sonarqube-community-branch-plugin

          下载插件放置到 ${SONAR_HOME}/extensions/plugins目录下,重启soanrqube-server。扫描时,在项目的sonar-project.properties文件里面,增加sonar.branch.name=${GIT_BRANCH}配置即可。

     如上图,在checkout代码时,获取实际分支设置为环境变量。

    如上图,在sonar-project.properties文件里面,增加sonar.branch.name的配置;最终sonarqube效果如下图

    完整jenkinsfile如下:

    pipeline{
    
    	triggers{
    			bitbucketPush()
    pollSCM('')
    
    		}
    
    	agent any
    
    	options{
    		disableConcurrentBuilds()
    		buildDiscarder(logRotator(numToKeepStr: '200'))
    	}
    
    	stages{
    		stage("Checkout"){
    
    	
    	steps{
    		deleteDir()
    script{
        def getGitCredentialsID = { String gitRepositoryPath ->
            if(gitRepositoryPath.startsWith("ssh://")){
                return "svcacctdevops-git"
            }
            if(gitRepositoryPath.startsWith("http")){
                return "svcacctdevops-git-http"
            }
            return "svcacctdevops-git"
        }
        def gitCredentialsID = getGitCredentialsID("http://xxxxx/testjava.git")
        REPOSITORY_PATH = "http://xxxxx/testjava.git"  //代码仓库地址
        def targetRefSpec = ''
        def  getTargetBranches ={ String branchName ->
            if (branchName.startsWith(":")) {
                return  branchName
            }
            if (branchName.contains("*")) {
                return "origin/${branchName}"
            }
            return "refs/heads/${branchName}"
        }
        def targetBranches = []
        def targetBranch = getTargetBranches("release**") //代码仓库分支名,为通配符形式
        targetBranches.add([name:"${targetBranch}"])
        def scmVars = checkout(
          [$class: 'GitSCM', branches: targetBranches, doGenerateSubmoduleConfigurations: false, 
          extensions:  [[$class: 'CloneOption', depth: 0, honorRefspec: true, noTags: true, reference: '', shallow: false]], submoduleCfg: [], 
          userRemoteConfigs: [[credentialsId: gitCredentialsID, name: 'origin', refspec: targetRefSpec, url: REPOSITORY_PATH]]])
    
    
        GIT_COMMIT = scmVars.GIT_COMMIT
        GIT_BRANCH = scmVars.GIT_BRANCH.replaceAll("origin/","").replaceAll("/","_")
        env.CODE_COMMIT = GIT_COMMIT
        env.GIT_COMMIT = GIT_COMMIT
        env.CODE_BRANCH = GIT_BRANCH
        // def GIT_BRANCH = "release/1.0.1"
        env.GIT_BRANCH = GIT_BRANCH
        env.GIT_REPOSITORY = "http://xxxxx/testjava.git" 
        env.GIT_CREDENTIALSID = gitCredentialsID
        stash "cloneCode"
    }
    }
    }
    stage("BuildImage"){
    
    	
    	options{
    		timeout(time:3600, unit:'SECONDS')
    	}
    	
    	steps{
    		script{
      def getVolumes = {
        def volumes = [
          hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'),
          hostPathVolume(hostPath: '/jenkins/data/.m2/repository', mountPath: '/root/.m2/repository/')
        ]
        return volumes
      }
    
      def safePath = { String path ->
            if(path.startsWith("/")){
                path = "." + path
            }
            if(!path.endsWith("/")){
                path = path + "/"
            }
            return path
      }
    
    
      // def ciImage = "<no value>/<no value>:<no value>"
      def ciImage = "http:/xxxxxx/java:oraclejdk8"   //CI镜像地址
      def contextPath = safePath("./")
      def pomPath = safePath("./")
    
      def execCmds = {
        def cmdstr = ""
        def cmds = []
        cmds << "mvn clean install -DskipTests=true"
        cmdstr = cmds.join("
    ")
    
        return {
          try{
            sh cmdstr
          }
          finally{
          }
        }
      }
    
      def pom = readMavenPom file: pomPath + "pom.xml"
      env.POM_ARTIFACTId = pom.artifactId
      env.POM_GROUPID = pom.groupId
      env.POM_VERSION = pom.version
      env.POM_MODELVERSION = pom.modelVersion
      env.POM_NAME = pom.name
      
      def registry = alauda.parseRegistry("${ciImage}")
      def label = "ci-node-${UUID.randomUUID().toString()}"
    
      podTemplate(
              label: label,
              containers:[
                      containerTemplate(name: 'ci-container', image: "${ciImage}", ttyEnabled: true,
                          envVars: [envVar(key: "LANG", value: "C.UTF-8")])
              ],
              nodeUsageMode: "EXCLUSIVE",
              volumes: getVolumes(),
              nodeSelector: 'jenkins-ci=true',
              imagePullSecrets: [ 'common-registry-user' ],
              inheritFrom: 'base'
      ){
        node(label) {
          container('ci-container') {
              def dest = "${env.WORKSPACE}/__dest__"
              def source = "${env.WORKSPACE}/__source__"
              def bin = "${env.WORKSPACE}/__bin__"
              def upload = "${env.WORKSPACE}/__upload__"
              sh "mkdir -p ${dest}"
    
              dir("./__source__"){
                  unstash "cloneCode"
                  withEnv([
                          "ALAUDACI_DEST_DIR=${dest}","ALAUDACI_SOURCE_DIR=${source}", "ALAUDACI_BIN_DIR=${bin}", "ALAUDACI_UPLOAD_DIR=${upload}"
                  ]){
                      dir("${contextPath}"){
                          execCmds()()
                      }
                  }
    
                  def count = sh(script: "ls -A ${dest} |wc -w", returnStdout:true).trim()
                  if(count == "0"){
                      echo "dest directory is empty, will copy source directory to dest"
                      sh "cp -r ./ ${dest}"
                  }
              }
    
              dir("./__dest__"){
                  stash "alaudaciDest"
              }
          }
        }
      }
    }
    }
    }
    stage("CodeScan"){
    
    	agent {label "sonarqube"}
    	options{
    		timeout(time:7200, unit:'SECONDS')
    	}
    	
    	steps{
    		script{
      def safePath = { String path ->
        if(path.startsWith("/")){
            path = "." + path
        } 
        if(!path.endsWith("/")){
            path = path + "/"
        }
        return path
      }
      def sonarProjectName = "${env.JOB_NAME}".replaceAll("/",":")
      def sonarProjectKey = "devopstools:${sonarProjectName}"
      def genSonarProperties ={ sonar_info ->
        def propertiesPath = "sonar-project.properties"
        def userPropsStr = ""
        if (fileExists(propertiesPath)){
            def userProps = readProperties file: propertiesPath
            userPropsStr = userProps.collect{k,v->return k+"="+v}.join('
    ')
        }
        def sonarContextPath = safePath(".")
        writeFile file: propertiesPath, text: """${userPropsStr}
          sonar.projectKey=${sonarProjectKey}
          sonar.projectName=${sonarProjectName}
          sonar.host.url=${sonar_info.getEndpoint()}
          sonar.login=${sonar_info.getToken()}
          sonar.junit.reportPaths=${sonarContextPath}target/surefire-reports
          sonar.jacoco.reportPaths=${sonarContextPath}target/jacoco.exec
          sonar.language=Java
          sonar.sources=${sonarContextPath}
          sonar.branch.name=${GIT_BRANCH}
        """
        return propertiesPath
      }
    
      unstash "alaudaciDest"
      // Retrieve Sonar Info
      def sonar_info = alauda.integration("6c32eb4c-c143-45ad-9f4d-16d27494c6be", "devopstools").retrieve()
      
      // Generate sonar-project.properties file
      def propertiesPath = genSonarProperties(sonar_info)
      // Init Sonar Project
      sh "echo start setting qualitygate to 4"
      withCredentials([string(credentialsId: 'sonarToken', variable: 'SONARTOKEN')])
          {
         retry(3){
           sh "cmdsonar qualitygate select --host ${sonar_info.getEndpoint()} --token ${SONARTOKEN} 
            --gate-id 4 --name ${sonarProjectName} --properties ${propertiesPath}"
             } 
    //cmdsonar为封装sonarqube的api的一个二进制工具,能实现在扫描代码前设置使用非默认的quality gate
          }
      // Start scan
      sh "sonar-scanner -Dsonar.java.binaries=./target/classes -Dproject.settings=${propertiesPath}"
      addShortText(text:"SonarQube", link:"${sonar_info.getEndpoint()}/dashboard?id=${sonarProjectKey}")
    }
    }
    }
    
    	}
    
    	post{
    		always{
    	
    			script{
    				echo "clean up workspace"
    				deleteDir()
    			}
    
    }
    
    	}
    }
    
  • 相关阅读:
    (二十)WebGIS中图层树功能的设计和实现
    WebGIS中矢量切图的初步研究
    百度兴趣点下载工具设计和实现
    服务端常规知识详解
    Shp数据批量导入Postgresql工具的原理和设计
    浅谈C#中一种类插件系统编写的简单方法(插件间、插件宿主间本身不需要通信)
    从底层开发谈WebGIS中实现地理长度固定的可视窗口的思路和方法
    用存储过程判断某个人员在一天的行进轨迹中是否有超过指定时间的停留
    Linux启动与禁止SSH用户及IP的登录
    JVM中的垃圾回收
  • 原文地址:https://www.cnblogs.com/360linux/p/13062058.html
Copyright © 2011-2022 走看看