质量管理平台集成

本章主要我们主要学习与质量管理平台Sonarqube集成。

目录


认识sonarqube

架构

  • 一台SonarQube Server启动3个主要过程:

    • Web服务器,供开发人员,管理人员浏览高质量的快照并配置SonarQube实例
    • 基于Elasticsearch的Search Server从UI进行后退搜索
    • Compute Engine服务器,负责处理代码分析报告并将其保存在SonarQube数据库中
  • 一个SonarQube数据库要存储:

    • SonarQube实例的配置(安全性,插件设置等)
    • 项目,视图等的质量快照。
  • 服务器上安装了多个SonarQube插件,可能包括语言,SCM,集成,身份验证和管理插件
  • 在构建/持续集成服务器上运行一个或多个SonarScanner,以分析项目

images

工作原理

开发人员在IDE开发代码,可以安装SonarLint插件进行提交前代码扫描 当开发人员提交代码到版本控制系统中,自动触发jenkins进行代码扫描

images

版本

开源社区版、开发版、企业版、数据中心版 images

安装

我们这里使用Docker运行一个测试的环境,可以参考博客安装 博文地址: https://www.cnblogs.com/mascot1/p/11179767.html

  1. docker run --rm -d --name sonarqube \
  2. -p 9000:9000 \
  3. -v ${LOCALDIR}/sonar/sonarqube_conf:/opt/sonarqube/conf \
  4. -v ${LOCALDIR}/sonar/sonarqube_extensions:/opt/sonarqube/extensions \
  5. -v ${LOCALDIR}/sonar/sonarqube_logs:/opt/sonarqube/logs \
  6. -v ${LOCALDIR}/sonar/sonarqube_data:/opt/sonarqube/data \
  7. sonarqube:7.9.2-community

WEB 页面 http://127.0.0.1:9000

images

sonarqube配置管理

强制登录

默认所有项目都可以公开的查看,在企业内肯定要配置成私有的。只有登录后才能查看。 images

ldap集成

安装LDAP插件 images

不用找了哦,页面上没有LDAP配置。需要修改sonar配置文件,然后重启服务器。

  1. #LDAP settings
  2. #admin
  3. sonar.security.realm=LDAP
  4. ldap.url=ldap://192.168.1.200:389
  5. ldap.bindDn=cn=admin,dc=devops,dc=com
  6. ldap.bindPassword=ldap12344
  7. #users
  8. ldap.user.baseDn=ou=jenkins,dc=devops,dc=com
  9. ldap.user.request=(&(objectClass=inetOrgPerson)(cn={login}))
  10. ldap.user.realNameAttribute=cn
  11. ldap.user.emailAttribute=mail

gitlab认证集成

安装GitlabAuth插件 images

在gitlab中创建一个应用 系统设置 应用管理,填写http://sonarserver:9000/oauth2/callback/gitlab

images images

接下来在sonarqube中配置gitlab信息。这个真的有图形页面,可以直接配置。主要填写gitlab的信息。

images

登录时出现此选项表明成功了 images

github认证集成

安装GithubAuth插件 images

在github中创建一个应用 系统设置 应用管理,填写http://sonarserver:9000/oauth2/callback

images

接下来在sonarqube中配置 images

最终效果 images

项目分析

安装配置sonarscanner

下载地址:https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner images

  1. tar zxf sonar-scanner-xxxx.tar.gz -C /usr/local
  2. vim /etc/profile
  3. export SCANNER_HOME=/usr/local/sonar-scannerxxx
  4. export PATH=$PATH:$SCANNER_HOME/bin
  5. source /etc/profile

本地分析项目

sonar.projectKey 指定项目的关键字,sonar.host.url指定服务器地址(可以直接在配置文件中写死),projectName指定项目的名称, projectVersion指定项目的版本(可以用构建时间和构建ID定义),login指定登录用户名,password指定登录用户密码, projectDescription指定项目的描述信息, links.homepage指定项目的主页(超链接), sources指定扫描的目录, sourceEncoding指定扫描时的编码, java.binaries指定编译后的类文件目录(必填), java.test.binaries指定编译后的测试类目录,java.surefire.report指定测试报告目录。

  1. sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \
  2. -Dsonar.projectKey=demo-maven-service \
  3. -Dsonar.projectName=demo-maven-service \
  4. -Dsonar.projectVersion=1.0 \
  5. -Dsonar.login=admin \
  6. -Dsonar.password=admin \
  7. -Dsonar.ws.timeout=30 \
  8. -Dsonar.projectDescription="my first project!" \
  9. -Dsonar.links.homepage=http://www.baidu.com \
  10. -Dsonar.sources=src \
  11. -Dsonar.sourceEncoding=UTF-8 \
  12. -Dsonar.java.binaries=target/classes \
  13. -Dsonar.java.test.binaries=target/test-classes \
  14. -Dsonar.java.surefire.report=target/surefire-reports

自动化分析

在jenkins中安装插件sonarqube scanner 配置SonarQube服务器:登录Jenkins,然后转到“ 管理Jenkins”>“配置系统”。 向下滚动到SonarQube配置部分,单击Add SonarQube,然后添加提示您的值。 服务器身份验证令牌应创建为“机密文本”凭据。

images

首先我们在共享库中定义一个sonarqube.groovy,用与扫描。新建文件src/org/devops/sonarqube.groovy 在这里我们定义了一个服务器列表,用于选择本次扫描使用的服务器(存在多个sonar的时候很有用处) 使用withSonarQubeEnv使用在Jenkins中配置sonar环境。这个方法有5个参数服务器类型、项目名称、项目描述、项目扫描路径、分支名称

  1. package org.devops
  2. //scan
  3. def SonarScan(sonarServer,projectName,projectDesc,projectPath,branchName){
  4. //定义sonar服务器列表
  5. def servers = ["test":"sonarqube-test","prod":"sonarqube-prod"]
  6. //使用sonar服务器
  7. withSonarQubeEnv("${servers[sonarServer]}"){
  8. def scannerHome = "/home/jenkins/buildtools/sonar-scanner-3.2.0.1227-linux/"
  9. def sonarDate = sh returnStdout: true, script: 'date +%Y%m%d%H%M%S'
  10. sonarDate = sonarDate - "\n"
  11. sh """
  12. ${scannerHome}/bin/sonar-scanner -Dsonar.projectKey=${projectName} \
  13. -Dsonar.projectName=${projectName} -Dsonar.projectVersion=${sonarDate} -Dsonar.ws.timeout=30 \
  14. -Dsonar.projectDescription=${projectDesc} -Dsonar.links.homepage=http://www.baidu.com \
  15. -Dsonar.sources=${projectPath} -Dsonar.sourceEncoding=UTF-8 -Dsonar.java.binaries=target/classes \
  16. -Dsonar.java.test.binaries=target/test-classes -Dsonar.java.surefire.report=target/surefire-reports -Dsonar.branch.name=${branchName} -X
  17. """
  18. }
  19. }

在Jenkinsfile中引用: 我们首先加载jenkinslibrary共享库,引用sonarqube.groovy

  1. @Library('jenkinslibrary@master') _
  2. //func from shareibrary
  3. def sonar = new org.devops.sonarqube()
  4. pipeline {
  5. agent any
  6. stages {
  7. stage("codescan"){
  8. steps{
  9. script{
  10. sonar.SonarScan("test","${JOB_NAME}","${JOB_NAME}","src")
  11. }
  12. }
  13. }
  14. }
  15. }

效果:此时流水线运行完成后,在项目中可以看到Sonarqube的链接。点击即可进入sonarqube images

项目的扫描结果 images images

sonarqube接口

根据sonar官方的文档获取接口使用详情。

  1. //查找项目
  2. api/projects/search?projects=${projectName}"
  3. //创建项目
  4. api/projects/create?name=${projectName}&project=${projectName}"
  5. //更新语言规则集
  6. api/qualityprofiles/add_project?language=${language}&qualityProfile=${qualityProfile}&project=${projectName}"
  7. //项目授权
  8. api/permissions/apply_template?projectKey=${projectKey}&templateName=${templateName}"
  9. //更新质量阈
  10. api/qualitygates/select?projectKey=${projectKey}&gateId=${gateId}"

封装到共享库中sonarapi.groovy

  1. package org.devops
  2. //封装HTTP
  3. def HttpReq(reqType,reqUrl,reqBody){
  4. def sonarServer = "http://192.168.1.200:30090/api"
  5. result = httpRequest authentication: 'sonar-admin-user',
  6. httpMode: reqType,
  7. contentType: "APPLICATION_JSON",
  8. consoleLogResponseBody: true,
  9. ignoreSslErrors: true,
  10. requestBody: reqBody,
  11. url: "${sonarServer}/${reqUrl}"
  12. //quiet: true
  13. return result
  14. }
  15. //获取Sonar质量阈状态
  16. def GetProjectStatus(projectName){
  17. apiUrl = "project_branches/list?project=${projectName}"
  18. response = HttpReq("GET",apiUrl,'')
  19. response = readJSON text: """${response.content}"""
  20. result = response["branches"][0]["status"]["qualityGateStatus"]
  21. //println(response)
  22. return result
  23. }
  24. //搜索Sonar项目
  25. def SerarchProject(projectName){
  26. apiUrl = "projects/search?projects=${projectName}"
  27. response = HttpReq("GET",apiUrl,'')
  28. response = readJSON text: """${response.content}"""
  29. result = response["paging"]["total"]
  30. if(result.toString() == "0"){
  31. return "false"
  32. } else {
  33. return "true"
  34. }
  35. }
  36. //创建Sonar项目
  37. def CreateProject(projectName){
  38. apiUrl = "projects/create?name=${projectName}&project=${projectName}"
  39. response = HttpReq("POST",apiUrl,'')
  40. println(response)
  41. }
  42. //配置项目质量规则
  43. def ConfigQualityProfiles(projectName,lang,qpname){
  44. apiUrl = "qualityprofiles/add_project?language=${lang}&project=${projectName}&qualityProfile=${qpname}"
  45. response = HttpReq("POST",apiUrl,'')
  46. println(response)
  47. }
  48. //获取质量阈ID
  49. def GetQualtyGateId(gateName){
  50. apiUrl= "qualitygates/show?name=${gateName}"
  51. response = HttpReq("GET",apiUrl,'')
  52. response = readJSON text: """${response.content}"""
  53. result = response["id"]
  54. return result
  55. }
  56. //配置项目质量阈
  57. def ConfigQualityGates(projectName,gateName){
  58. gateId = GetQualtyGateId(gateName)
  59. apiUrl = "qualitygates/select?gateId=${gateId}&projectKey=${projectName}"
  60. response = HttpReq("POST",apiUrl,'')
  61. println(response)println(response)
  62. }

应用实践:

  1. stage("QA"){
  2. steps {
  3. script{
  4. //搜索项目
  5. result = sonarapi.SerarchProject("${JOB_NAME}")
  6. println(result)
  7. //判断项目是否存在
  8. if (result == "false"){
  9. println("${JOB_NAME}---项目不存在,准备创建项目---> ${JOB_NAME}!")
  10. sonarapi.CreateProject("${JOB_NAME}")
  11. } else {
  12. println("${JOB_NAME}---项目已存在!")
  13. }
  14. //配置项目质量规则
  15. qpName="${JOB_NAME}".split("-")[0] //Sonar%20way
  16. sonarapi.ConfigQualityProfiles("${JOB_NAME}","java",qpName)
  17. //配置质量阈
  18. sonarapi.ConfigQualityGates("${JOB_NAME}",qpName)
  19. //代码扫描
  20. sonar.SonarScan("test","${JOB_NAME}","${JOB_NAME}","src")
  21. sleep 30
  22. //获取扫描结果
  23. result = sonarapi.GetProjectStatus("${JOB_NAME}")
  24. println(result)
  25. if (result.toString() == "ERROR"){
  26. error " 代码质量阈错误!请及时修复!"
  27. } else {
  28. println(result)
  29. }
  30. }
  31. }
  32. }

配置多分支

将插件放到两个目录中,然后重启sonar

images

扫描参数增加 –Dsonar.branch.name= images

效果 images