时间 标题 内容







上午







代码质量平台实践
(SonarQube)

1. SonarQube平台的简介与工作原理
2. SonarQube平台的安装部署(LTS 7.9.x)
3. 常用的SonarScanner工具使用方法
4. 使用SonarScanner进行代码质量检查
5. 扫描报告指标含义及如何配置

1. CI流水线集成Sonar代码扫描阶段
2. SonarQube开源版本存在的问题
3. 使用SonarAPI完成项目的创建
4. 使用SonarAPI完成质量规则与质量阈配置



下午



制品库管理
(Nexus/Harbor)

1. Sonar代码多分支扫描(开源插件)
2. Sonar代码扫描报告关联Git Commit(开源插件)
3. 开源制品库管理软件-Nexus简介与基本概念
4. 使用Nexus搭建一个Maven私服
5. 使用Harbor搭建一个Docker私服

1. CI流水线上传制品阶段实现(二进制包)
2. CI流水线上传制品阶段实现(Docker镜像)

Jenkins共享库代码:
devops-library-service-day4-init-version.tar.gz

课程中遗留问题: gitlabapi未成功下载文件的解决方法:

  1. curl --header "Private-Token: FUZwKwZ713ST" "http://www.gitlab.com/api/v4/projects/PROJECT_ID/repository/files/FILE_PATH/raw?ref=BRANCH_NAME"
  • PROJECT_ID : 项目的 ID
  • FILE_PATH: 文件路径(从/出发)
  • BRANCH_NAME: 分支名称

实例: 获取项目ID为50, master分支的根目录下的Jenkinsfile文件内容:

  1. curl --header "Private-Token: FUZwKwZ713ST" "http://www.gitlab.com/api/v4/projects/50/repository/files/Jenkinsfile/raw?ref=master"

1. 代码质量平台实践

image.png

1.1 SonarQube 简介

SonarQube®是一种自动代码审查工具,可检测代码中的错误,漏洞和代码味道。它可以与您现有的工作流程集成,以实现跨项目分支拉取请求的持续代码检查。

image.png

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

1.2 SonarQube平台安装配置

  • SonarQube Server启动3个主要进程:
    • Web服务器,供开发人员,管理人员浏览高质量的快照并配置SonarQube实例
    • 基于Elasticsearch的Search Server从UI进行搜索服务。
    • Compute Engine服务器,负责处理代码分析报告并将其保存在SonarQube数据库中。
  • SonarQube数据库要存储:SonarQube实例的配置(安全,插件设置等)项目,视图质量快照。
  • 服务器上安装了多个SonarQube插件,可能包括语言,SCM,集成,身份验证和管理插件。
  • 在持续集成服务器上运行一个或多个SonarScanner,以分析项目。

image.png
image.png

  • Java (Oracle JRE 11 or OpenJDK 11) ```bash

    创建数据目录

    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

  1. 访问: [http://192.168.1.200:9000/](http://192.168.1.200:9000/about)<br />![](https://cdn.nlark.com/yuque/0/2021/png/2584012/1618575547977-6d1433f1-9d63-498a-8026-13623c709306.png#clientId=ue3cb5713-816c-4&from=paste&height=410&id=u4331cb37&originHeight=722&originWidth=1287&originalType=binary&size=90902&status=done&style=none&taskId=u9dfb0701-0b5e-466d-8395-ee157a76294&width=731.4943237304688)<br />默认账号: admin/admin<br />![](https://cdn.nlark.com/yuque/0/2021/png/2584012/1618576096711-556a3c0e-8e7b-44cb-9ef1-143dd9c5e76a.png#clientId=ue3cb5713-816c-4&from=paste&height=306&id=u28943b05&originHeight=404&originWidth=969&originalType=binary&size=17965&status=done&style=none&taskId=u4cef3766-37c2-436b-b9ff-4d6e9d5d964&width=733.4857788085938)
  2. <a name="nEjMJ"></a>
  3. ### 安装中文插件
  4. 在线安装或者手动上传插件
  5. **在线安装:操作如下图**<br />![](https://cdn.nlark.com/yuque/0/2021/png/2584012/1618576142717-ab44c40a-c539-4575-9e9b-4e6486c97c9c.png#clientId=ue3cb5713-816c-4&from=paste&height=499&id=P865L&originHeight=888&originWidth=1281&originalType=binary&size=166059&status=done&style=none&taskId=u15fe667d-1481-483e-9482-48693bf7f98&width=719.4971313476562)阅
  6. **手动上传插件**
  7. 为什么需要手动安装? 在线源可能会失败,超时。
  8. ```bash
  9. Caused by: org.sonar.api.utils.SonarException: Fail to download: https://github.com/xuhuisheng/sonar-l10n-zh/releases/download/sonar-l10n-zh-plugin-1.29/sonar-l10n-zh-plugin-1.29.jar (no proxy)
  10. at org.sonar.core.util.DefaultHttpDownloader.failToDownload(DefaultHttpDownloader.java:155)
  11. at org.sonar.core.util.DefaultHttpDownloader.download(DefaultHttpDownloader.java:150)
  12. at org.sonar.server.plugins.PluginDownloader.downloadRelease(PluginDownloader.java:152)
  13. at org.sonar.server.plugins.PluginDownloader.download(PluginDownloader.java:126)
  14. ... 47 common frames omitted
  15. Caused by: java.net.SocketTimeoutException: Read timed out

阅读说明文档:找到sonarqube 版本对应的插件版本。
https://github.com/xuhuisheng/sonar-l10n-zh/tree/sonar-l10n-zh-plugin-8.8#the-chinese-translation-pack-for-sonarqube
Day4-代码质量平台与制品库实践 - 图5

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

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

插件源:https://update.sonarsource.org/
文档: 待补充


配置强制登录

默认所有项目都可以公开的查看,在企业内肯定要配置成私有的。只有登录后才能查看。
Day4-代码质量平台与制品库实践 - 图6


配置Scanner

  1. wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.0.2311-linux.zip
  2. tar zxf sonar-scanner-xxxx.tar.gz -C /usr/local
  3. vim /etc/profile
  4. export SCANNER_HOME=/usr/local/sonar-scannerxxx
  5. export PATH=$PATH:$SCANNER_HOME/bin
  6. source /etc/profile
  7. /usr/local/sonar-scanner-4.6.0.2311-linux/bin
  8. [root@zeyang-nuc-service bin]# vi /etc/profile
  9. [root@zeyang-nuc-service bin]# sourece /etc/profile
  10. bash: sourece: command not found...
  11. [root@zeyang-nuc-service bin]# source /etc/profile
  12. [root@zeyang-nuc-service bin]# sonar-scanner -v
  13. INFO: Scanner configuration file: /usr/local/sonar-scanner-4.6.0.2311-linux/conf/sonar-scanner.properties
  14. INFO: Project root configuration file: NONE
  15. INFO: SonarScanner 4.6.0.2311
  16. INFO: Java 11.0.3 AdoptOpenJDK (64-bit)
  17. INFO: Linux 4.18.0-80.el8.x86_64 amd64

修改scanner的java使用版本

  1. [root@zeyang-nuc-service sonar-scanner-4.6.0.2311-linux]# vi bin/sonar-scanner
  2. [root@zeyang-nuc-service sonar-scanner-4.6.0.2311-linux]#
  3. [root@zeyang-nuc-service sonar-scanner-4.6.0.2311-linux]# sonar-scanner -v
  4. INFO: Scanner configuration file: /usr/local/sonar-scanner-4.6.0.2311-linux/conf/sonar-scanner.properties
  5. INFO: Project root configuration file: NONE
  6. INFO: SonarScanner 4.6.0.2311
  7. INFO: Java 1.8.0_282 AdoptOpenJDK (64-bit)
  8. INFO: Linux 4.18.0-80.el8.x86_64 amd64

1.3 SonarScanner使用方法

  • 配置文件方式读取扫描参数
  • 命令行方式读取扫描参数

一个基本的sonar-project.properties配置文件的参数:

  1. # 定义唯一的关键字
  2. sonar.projectKey=devops-hello-service
  3. # 定义项目名称
  4. sonar.projectName=My project
  5. # 定义项目的版本信息
  6. sonar.projectVersion=1.0
  7. # 指定扫描代码的目录位置(多个逗号分隔)
  8. sonar.sources=.
  9. # 执行项目编码
  10. sonar.sourceEncoding=UTF-8
  11. sonar.host.url=
  12. sonar.login
  13. sonar.password

这些配置项都是统一的,目前sonar支持将扫描参数以文件的方式存放或者以命令行传参的方式读取。 文件方式:可以将扫描参数放到项目的根目录或者sonar-scanner的配置文件目录等自定义的目录中, 命令行传参则可以直接将变量传递给sonarsacnner cli -Dsonar.projectKey=xxx

  1. # 指定配置文件
  2. sonar-scanner -Dproject.settings=myproject.properties
  3. # 命令行传参
  4. sonar-scanner -Dsonar.projectKey=myproject -Dsonar.sources=src1

扩展-Docker运行sonarscanner

  1. docker run \
  2. --rm \
  3. -e SONAR_HOST_URL="http://${SONARQUBE_URL}" \
  4. -e SONAR_LOGIN="myAuthenticationToken" \
  5. -v "${YOUR_REPO}:/usr/src" \
  6. sonarsource/sonar-scanner-cli

关于项目参数可以参考:https://docs.sonarqube.org/latest/analysis/analysis-parameters/
各种语言的扫描示例:https://docs.sonarqube.org/latest/analysis/languages/


SonarQube中各种语言的扫描规则都是以jar包的方式。默认没有安装语言规则插件, 需要手动安装。 服务端安装**Java Code Quality and Security**``SonarJS SonarGO插件,并重启服务器。(如果这里由于网速原因下载不了插件,可以使用课程提供的压缩包,解压到downloads目录下然后重启sonarqube)

  1. [root@zeyang-nuc-service ~]# cd /data/cicd/plugin-sonar/
  2. [root@zeyang-nuc-service plugin-sonar]# ls
  3. sonar-go-plugin-1.6.0.719.jar sonar-l10n-zh-plugin-1.29.jar
  4. sonar-java-plugin-6.3.2.22818.jar sonar-typescript-plugin-2.1.0.4359.jar
  5. sonar-javascript-plugin-6.2.2.13315.jar
  6. [root@zeyang-nuc-service plugin-sonar]# cp sonar-go-plugin-1.6.0.719.jar sonar-java-plugin-6.3.2.22818.jar sonar-javascript-plugin-6.2.2.13315.jar sonar-typescript-plugin-2.1.0.4359.jar /data/cicd/sonarqube/sonarqube_extensions/downloads/
  7. [root@zeyang-nuc-service plugin-sonar]# ls /data/cicd/sonarqube/sonarqube_extensions/downloads/
  8. sonar-go-plugin-1.6.0.719.jar sonar-javascript-plugin-6.2.2.13315.jar
  9. sonar-java-plugin-6.3.2.22818.jar sonar-typescript-plugin-2.1.0.4359.jar
  10. [root@zeyang-nuc-service plugin-sonar]# chmod +x /data/cicd/sonarqube/sonarqube_extensions/downloads/*
  11. [root@zeyang-nuc-service plugin-sonar]# ls /data/cicd/sonarqube/sonarqube_extensions/downloads/
  12. sonar-go-plugin-1.6.0.719.jar sonar-javascript-plugin-6.2.2.13315.jar
  13. sonar-java-plugin-6.3.2.22818.jar sonar-typescript-plugin-2.1.0.4359.jar
  14. [root@zeyang-nuc-service plugin-sonar]# docker restart sonarqube
  15. sonarqube

Day4-代码质量平台与制品库实践 - 图7

1.3.1 Java项目扫描

sonarqube服务器端需要安装Java语言规则插件
Day4-代码质量平台与制品库实践 - 图8

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=devops-maven-service \
  3. -Dsonar.projectName=devops-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://192.168.1.200/devops/devops-maven-service \
  10. -Dsonar.links.ci=http://192.168.1.200:8080/job/demo-pipeline-service/ \
  11. -Dsonar.sources=src \
  12. -Dsonar.sourceEncoding=UTF-8 \
  13. -Dsonar.java.binaries=target/classes \
  14. -Dsonar.java.test.binaries=target/test-classes \
  15. -Dsonar.java.surefire.report=target/surefire-reports

1.3.2 Web前端项目扫描

Day4-代码质量平台与制品库实践 - 图9

  1. sonar.projectKey=devops-web-service
  2. sonar.projectName=devops-web-service
  3. sonar.projectVersion=1.0
  4. sonar.sources=src
  5. #sonar.sources=dist/static/js
  6. sonar.host.url=http://192.168.1.200:9000
  7. sonar.login=admin
  8. sonar.password=admin
  9. sonar.sourceEncoding=UTF-8

1.3.4 Golang项目扫描

Day4-代码质量平台与制品库实践 - 图10

  1. sonar-scanner -Dsonar.projectKey=devops-golang-service \
  2. -Dsonar.projectName=devops-golang-service \
  3. -Dsonar.sources=src \
  4. -Dsonar.login=admin \
  5. -Dsonar.password=admin \
  6. -Dsonar.host.url=http://192.168.1.200:9000
  7. ## 有测试用例的情况
  8. sonar.exclusions=**/*_test.go
  9. sonar.tests=.
  10. sonar.test.inclusions=**/*_test.go

1.4 CI流水线集成

shell 命令行方式

流水线中添加代码扫描阶段

  1. def buildTools = [ "maven" : "/usr/local/apache-maven-3.8.1",
  2. "gradle": "/usr/local/gradle-6.8.3/",
  3. "golang": "/usr/local/go",
  4. "web" : "/usr/local/node-v14.16.1-linux-x64/",
  5. "sonar" : "/usr/local/sonar-scanner-4.6.0.2311-linux"]
  6. pipeline {
  7. stages{
  8. stage("SonarScan"){
  9. steps{
  10. script{
  11. sh """
  12. ${buildTools["sonar"]}/bin/sonar-scanner -Dproject.settings=sonar.properties \
  13. -Dsonar.login=admin \
  14. -Dsonar.password=admin \
  15. -Dsonar.host.url=http://192.168.1.200:9000
  16. """
  17. }
  18. }
  19. }
  20. }
  21. }

Jenkins 插件方式

参考:https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-jenkins/
创建SonaQube的账户token
Day4-代码质量平台与制品库实践 - 图11

将token保存到Jenkins凭据中
Day4-代码质量平台与制品库实践 - 图12
在Jenkins中安装插件sonarqube scanner。
Day4-代码质量平台与制品库实践 - 图13

然后转到”管理Jenkins>系统配置“,向下滚动到SonarQube配置部分,单击Add SonarQube,添加服务器,选择凭据。
Day4-代码质量平台与制品库实践 - 图14

使用withSonarQubeEnv DSL引入在Jenkins中配置的sonar环境。

  1. //使用sonar服务器
  2. stage("SonarScanForPlugin"){
  3. steps{
  4. script{
  5. withSonarQubeEnv("mysonarserver"){
  6. def sonarDate = sh returnStdout: true, script: 'date +%Y%m%d%H%M%S'
  7. sonarDate = sonarDate - "\n"
  8. sh """
  9. ${buildTools["sonar"]}/bin/sonar-scanner \
  10. -Dsonar.projectKey=${JOB_NAME} \
  11. -Dsonar.projectName=${JOB_NAME} \
  12. -Dsonar.projectVersion=${sonarDate} \
  13. -Dsonar.ws.timeout=30 \
  14. -Dsonar.projectDescription="my test project" \
  15. -Dsonar.links.homepage=http://www.baidu.com \
  16. -Dsonar.sources=src \
  17. -Dsonar.sourceEncoding=UTF-8 \
  18. -Dsonar.java.binaries=target/classes \
  19. -Dsonar.java.test.binaries=target/test-classes \
  20. -Dsonar.java.surefire.report=target/surefire-reports \
  21. #echo \$PATH
  22. """
  23. }
  24. }
  25. }
  26. }

FAQ: sonar服务器名称错误,需要与系统设置中配置的一致。

  1. ERROR: SonarQube installation defined in this job (mysonarserver) does not match any configured installation. Number of installations that can be configured: 1.
  2. If you want to reassign jobs to a different SonarQube installation, check the documentation under https://redirect.sonarsource.com/plugins/jenkins.html

最终的效果如下:
Day4-代码质量平台与制品库实践 - 图15


1.5 SonarQube REST API实践

http://192.168.1.200:9000/web_api

  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}"

HTTP Request Plugin

Day4-代码质量平台与制品库实践 - 图16

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

1.6 其他日常使用问题

1.6.1 规则的禁用与启用

目的: 掌握默认规则中的一部分规则如何激活和禁用。
进入质量配置页面, 可以看到所有的语言规则配置。在这里可以看到规则的使用情况。
Day4-代码质量平台与制品库实践 - 图17
这里假设我要调整Go语言的规则配置, 点击规则数量数字。
Day4-代码质量平台与制品库实践 - 图18

Day4-代码质量平台与制品库实践 - 图19

创建新的规则集
Day4-代码质量平台与制品库实践 - 图20
点击更多激活规则, 进入规则设置页面。
Day4-代码质量平台与制品库实践 - 图21
激活或者下线规则。(活动/挂起)
Day4-代码质量平台与制品库实践 - 图22

使用规则: 先在页面配置项目,然后使用SonarScanner扫描。
Day4-代码质量平台与制品库实践 - 图23
Day4-代码质量平台与制品库实践 - 图24


1.6.2 质量阈的配置

目的: 适用于以质量门禁作为交付关卡。
Day4-代码质量平台与制品库实践 - 图25

Day4-代码质量平台与制品库实践 - 图26

1.6.3 代码覆盖率统计

找一个具有大量单元测试的项目, 然后集成jacoco插件,生成覆盖率报告,最后由sonar收集。

Maven集成Jacoco
添加jacoco-maven-pluginjunit插件。

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.jacoco</groupId>
  4. <artifactId>jacoco-maven-plugin</artifactId>
  5. <version>0.8.2</version>
  6. <scope>test</scope>
  7. </dependency>
  8. <dependency>
  9. <groupId>junit</groupId>
  10. <artifactId>junit</artifactId>
  11. <version>4.12</version>
  12. <scope>test</scope>
  13. </dependency>
  14. </dependencies>

添加插件

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-compiler-plugin</artifactId>
  4. <version>3.6.1</version>
  5. <configuration>
  6. <skipMain>true</skipMain>
  7. <skip>true</skip>
  8. <source>1.8</source>
  9. <target>1.8</target>
  10. </configuration>
  11. </plugin>
  12. <plugin>
  13. <groupId>org.jacoco</groupId>
  14. <artifactId>jacoco-maven-plugin</artifactId>
  15. <version>0.7.5.201505241946</version>
  16. <executions>
  17. <execution>
  18. <id>prepare-agent</id>
  19. <goals>
  20. <goal>prepare-agent</goal>
  21. </goals>
  22. </execution>
  23. <execution>
  24. <id>report</id>
  25. <phase>prepare-package</phase>
  26. <goals>
  27. <goal>report</goal>
  28. </goals>
  29. </execution>
  30. <execution>
  31. <id>post-unit-test</id>
  32. <phase>test</phase>
  33. <goals>
  34. <goal>report</goal>
  35. </goals>
  36. <configuration>
  37. <dataFile>target/jacoco.exec</dataFile>
  38. <outputDirectory>target/jacoco-reports</outputDirectory>
  39. </configuration>
  40. </execution>
  41. </executions>
  42. <configuration>
  43. <systemPropertyVariables>
  44. <jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
  45. </systemPropertyVariables>
  46. </configuration>
  47. </plugin>

SonarQube安装Jacoco插件
https://github.com/SonarSource/sonar-jacoco/releases/download/1.1.0.898/sonar-jacoco-plugin-1.1.0.898.jar
Day4-代码质量平台与制品库实践 - 图27

  1. # 指定代码覆盖率工具为jacoco
  2. sonar.core.codeCoveragePlugin=jacoco
  3. # 指定exec二进制文件存放路径
  4. sonar.jacoco.reportPaths=target/jacoco.exec
  1. cd devops-jacoco-service/
  2. sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \
  3. -Dsonar.projectKey=devops-jacoco-service \
  4. -Dsonar.projectName=devops-jacoco-service \
  5. -Dsonar.projectVersion=1.0 \
  6. -Dsonar.login=admin \
  7. -Dsonar.password=admin \
  8. -Dsonar.ws.timeout=30 \
  9. -Dsonar.projectDescription="my first project!" \
  10. -Dsonar.links.homepage=http://www.baidu.com \
  11. -Dsonar.sources=src \
  12. -Dsonar.sourceEncoding=UTF-8 \
  13. -Dsonar.java.binaries=target/classes \
  14. -Dsonar.java.test.binaries=target/test-classes \
  15. -Dsonar.java.surefire.report=target/surefire-reports \
  16. -Dsonar.core.codeCoveragePlugin=jacoco \
  17. -Dsonar.jacoco.reportPaths=target/jacoco.exec

1.6.4 多分支代码扫描

https://github.com/mc1arke/sonarqube-community-branch-plugin/releases

将插件放到extensions/pluginslib/common目录中,然后重启sonar。

  1. ## 临时方案
  2. docker exec -it sonarqube bash
  3. cd /opt/sonarqube/lib/common
  4. cp ../../extensions/plugins/sonarqube-community-branch-plugin-1.3.2 ./
  5. exit
  6. docker restart sonarqube
  7. ## 持久化lib目录后
  8. [root@zeyang-nuc-service sonarqube]# ls
  9. sonarqube_conf sonarqube_data sonarqube_extensions sonarqube_lib sonarqube_logs
  10. [root@zeyang-nuc-service sonarqube]# cp /root/sonarqube-community-branch-plugin-1.3.2.jar sonarqube_extensions/plugins/
  11. [root@zeyang-nuc-service sonarqube]# chmod +x sonarqube_extensions/plugins/sonarqube-community-branch-plugin-1.3.2.jar
  12. [root@zeyang-nuc-service sonarqube]#
  13. [root@zeyang-nuc-service sonarqube]#
  14. [root@zeyang-nuc-service sonarqube]# cp /root/sonarqube-community-branch-plugin-1.3.2.jar sonarqube_lib/common/
  15. [root@zeyang-nuc-service sonarqube]# chmod +x sonarqube_lib/common/sonarqube-community-branch-plugin-1.3.2.jar
  16. [root@zeyang-nuc-service sonarqube]#
  17. docker restart sonarqube

Day4-代码质量平台与制品库实践 - 图28

  1. ##扫描参数增加 –Dsonar.branch.name=
  2. sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \
  3. -Dsonar.projectKey=devops-maven2-service \
  4. -Dsonar.projectName=devops-maven2-service \
  5. -Dsonar.projectVersion=1.0 \
  6. -Dsonar.login=admin \
  7. -Dsonar.password=admin \
  8. -Dsonar.ws.timeout=30 \
  9. -Dsonar.projectDescription="my first project!" \
  10. -Dsonar.links.homepage=http://192.168.1.200/devops/devops-maven-service \
  11. -Dsonar.links.ci=http://192.168.1.200:8080/job/demo-pipeline-service/ \
  12. -Dsonar.sources=src \
  13. -Dsonar.sourceEncoding=UTF-8 \
  14. -Dsonar.java.binaries=target/classes \
  15. -Dsonar.java.test.binaries=target/test-classes \
  16. -Dsonar.java.surefire.report=target/surefire-reports \
  17. -Dsonar.branch.name=release-1.1.1

FAQ: 需要先把主分支扫描一遍,不然会报错。

  1. ERROR: Error during SonarScanner execution
  2. ERROR: No branches currently exist in this project. Please scan the main branch without passing any branch parameters.
  3. ERROR:
  4. ERROR: Re-run SonarScanner using the -X switch to enable full debug logging.

Day4-代码质量平台与制品库实践 - 图29


1.6.5 扫描结果关联commitid

提前装好插件:https://github.com/gabrie-allaigre/sonar-gitlab-plugin/tree/4.1.0-SNAPSHOT插件的说明文档查看该插件的Readme文档。

  1. [root@zeyang-nuc-service ~]# cp sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar /data/cicd/sonarqube/sonarqube_extensions/plugins/
  2. [root@zeyang-nuc-service ~]# chmod +x /data/cicd/sonarqube/sonarqube_extensions/plugins/sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar
  3. [root@zeyang-nuc-service ~]# docker restart sonarqube

Day4-代码质量平台与制品库实践 - 图30
-Dsonar.gitlab.failure_notification_mode 值为commit-status表示更改提交状态, 值为nothing不做任何动作。

  1. sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \
  2. -Dsonar.projectKey=devops-maven2-service \
  3. -Dsonar.projectName=devops-maven2-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://192.168.1.200/devops/devops-maven-service \
  10. -Dsonar.links.ci=http://192.168.1.200:8080/job/demo-pipeline-service/ \
  11. -Dsonar.sources=src \
  12. -Dsonar.sourceEncoding=UTF-8 \
  13. -Dsonar.java.binaries=target/classes \
  14. -Dsonar.java.test.binaries=target/test-classes \
  15. -Dsonar.java.surefire.report=target/surefire-reports \
  16. -Dsonar.branch.name=release-1.1.1 \
  17. -Dsonar.gitlab.commit_sha=665c36c3d0036942612f950d1dc42a433ec03f6d \
  18. -Dsonar.gitlab.ref_name=release-1.1.1 \
  19. -Dsonar.gitlab.project_id=3 \
  20. -Dsonar.dynamicAnalysis=reuseReports \
  21. -Dsonar.gitlab.failure_notification_mode=commit-status \
  22. -Dsonar.gitlab.url=http://192.168.1.200 \
  23. -Dsonar.gitlab.user_token=Hc-a6dEidbyxgcsTvbEr \
  24. -Dsonar.gitlab.api_version=v4

效果

Day4-代码质量平台与制品库实践 - 图31


1.6.6 控制代码扫描步骤运行

  1. String skipSonar = "${env.skipSonar}"
  2. stage("SonarScan"){
  3. when {
  4. environment name: 'skipSonar', value: 'false'
  5. }
  6. }

Day4-代码质量平台与制品库实践 - 图32

Day4-代码质量平台与制品库实践 - 图33

2. 制品库管理实践

https://help.sonatype.com/repomanager3/release-notes

2.1 Nexus 制品库实践

2.1.1 Nexus基本功能简介

从3.x开始,它默认支持许多主流的软件包格式。

  • Bower
  • Docker
  • Git LFS
  • Maven
  • npm
  • NuGet
  • PyPI
  • Ruby
  • Gems
  • Yum
  • Proxy
  • Helm Charts

仓库类型:

  • proxy 代理仓库。
  • hosted 私有仓库。
  • group 仓库组,将多个仓库组合在一起,通过同一个URL对外提供。

2.1.2 Nexus安装部署配置

  1. docker pull sonatype/nexus3:3.30.0
  2. mkdir -p /data/cicd/nexus3/data
  3. chmod 777 -R /data/cicd/nexus3/
  4. docker run -itd \
  5. --privileged=true --name=nexus3 \
  6. -p 8081:8081 \
  7. -v /data/cicd/nexus3/data:/nexus-data \
  8. sonatype/nexus3:3.30.0

日志查看Nexus是否已启动并准备就绪,请运行以下命令:

  1. docker logs nexus3 -f

在日志中,看到消息:Started Sonatype Nexus OSS 3.30.0-01这意味着Nexus Repository Manager可以使用了。现在转到浏览器并打开.

  1. http://your-ip-addr:8081

安装完成后, 默认的admin账号密码存储在了数据目录,获取初始化密码:

  1. docker exec -i nexus3 cat /nexus-data/admin.password

Day4-代码质量平台与制品库实践 - 图34登录后更新密码 admin/admin123
Day4-代码质量平台与制品库实践 - 图35

2.1.3 Nexus制品库搭建

搭建Maven私服(代理仓库)

默认安装nexus后会自动创建的。
Day4-代码质量平台与制品库实践 - 图36
私服: 将外网仓库代理到企业内容本地仓库中。 图中的地址可以自定义修改。
Day4-代码质量平台与制品库实践 - 图37

搭建制品库(本地仓库)

新建raw类型的仓库
Day4-代码质量平台与制品库实践 - 图38
设置仓库的信息
Day4-代码质量平台与制品库实践 - 图39

2.1.4 CI流水线中制品库集成

制品规范

按照 业务/服务/版本 层级。

依赖上传

参考:https://support.sonatype.com/hc/en-us/articles/213465818-How-can-I-programmatically-upload-an-artifact-into-Nexus-2-

我们需要在nexus中创建一个新的仓库maven-hostd,同时我们需要在maven的配置文件settings.xml中配置maven-hostd认证。如下:

  1. <server>
  2. <id>maven-hosted</id>
  3. <username>admin</username>
  4. <password>admin123</password>
  5. </server>

注意使用mvn deploy 发布时,server.id == respository.id。

  1. mvn deploy:deploy-file
  2. -DgroupId=xxxxxx pom中的groupId
  3. -DartifactId=xxxxxx pom中的artifactId
  4. -Dversion=xxxxxx pom中的版本号version
  5. -Dpackaging=xxxxxx pom中打包方式
  6. -Dfile=xxxxxx 本地文件
  7. -Durl=xxxxxx 仓库url
  8. -DrepositoryId=xxxxxx 对应的是setting.xml(认证)

直接读取pom文件(方便)

  1. mvn deploy:deploy-file \
  2. -DgeneratePom=false \
  3. -DrepositoryId=maven-hosted \
  4. -Durl=http://192.168.1.200:8081/repository/maven-hosted/ \
  5. -DpomFile=pom.xml \
  6. -Dfile=target/demo-0.0.1-SNAPSHOT.jar

自定义pom信息(灵活)

  1. mvn deploy:deploy-file -Dmaven.test.skip=true \
  2. -Dfile=target/demo-0.0.1-SNAPSHOT.jar \
  3. -DgroupId=com.example \
  4. -DartifactId=demo \
  5. -Dversion=1.1.1 \
  6. -Dpackaging=jar \
  7. -DrepositoryId=maven-hosted \
  8. -Durl=http://192.168.1.200:8081/repository/maven-hosted/

Day4-代码质量平台与制品库实践 - 图40
Day4-代码质量平台与制品库实践 - 图41

FAQ:

  1. [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy-file (default-cli) on project demo: Failed to deploy artifacts: Could not transfer artifact com.example:demo:jar:0.0.1-20210417.075618-1 from/to maven-hosted (http://192.168.1.200:8081/repository/maven-hosted/): transfer failed for http://192.168.1.200:8081/repository/maven-hosted/com/example/demo/0.0.1-SNAPSHOT/demo-0.0.1-20210417.075618-1.jar, status: 400 Repository version policy: RELEASE does not allow version: 0.0.1-20210417.075618-1 -> [Help 1]

使用Nexus插件

安装Nexus Artifact Uploader插件、使用片段生成器生成DSL。
Day4-代码质量平台与制品库实践 - 图42

  1. nexusArtifactUploader artifacts: [[ artifactId: 'myapp',
  2. classifier: '',
  3. file: './target/demo-0.0.1-SNAPSHOT.jar',
  4. type: 'jar']],
  5. credentialsId: 'cabaa495-918b-4e73-9090-eafd5ac98c1b',
  6. groupId: 'com.devops',
  7. nexusUrl: '192.168.1.200:8081',
  8. nexusVersion: 'nexus3',
  9. protocol: 'http',
  10. repository: 'maven-hosted',
  11. version: '1.1.1'

发布制品

安装Maven Artifact ChoiceListProvider (Nexus)插件
Day4-代码质量平台与制品库实践 - 图43
用户选择制品,在应用服务器通过salt、ansible下载制品并部署

Day4-代码质量平台与制品库实践 - 图44

2.1.5 Nexus REST API

http://192.168.1.200:8081/#admin/system/api
Day4-代码质量平台与制品库实践 - 图45


2.2 Harbor镜像库实践

官网: https://goharbor.io/

2.2.1 Harbor基本功能简介

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,可以用来构建企业内部的Docker镜像仓库。具有一些企业需要的功能特性,如镜像同步复制、漏洞扫描和权限管理等。

2.2.2 Harbor安装部署配置

安装docker-compose

参考文档:https://docs.docker.com/compose/install/#install-compose-on-linux-systems

  1. curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  2. cp docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
  3. chmod +x /usr/local/bin/docker-compose
  4. ## 测试命令
  5. docker-compose
  6. Define and run multi-container applications with Docker.
  7. Usage:
  8. docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
  9. docker-compose -h|--help

下载release包: https://goharbor.io/docs/2.2.0/install-config/download-installer/
https://github.com/goharbor/harbor/releases

Day4-代码质量平台与制品库实践 - 图46

  1. ## 解压
  2. tar zxf harbor-online-installer-v1.10.4.tgz
  3. cd harbor
  4. ## 编辑配置文件
  5. vim harbor.yml
  6. ----
  7. ### 修改主机名,注释https
  8. hostname: 192.168.1.200
  9. # http related config
  10. http:
  11. # port for http, default is 80. If https enabled, this port will redirect to https port
  12. port: 80
  13. # https related config
  14. #https:
  15. # https port for harbor, default is 443
  16. # port: 443
  17. # The path of cert and key files for nginx
  18. #certificate: /your/certificate/path
  19. #private_key: /your/private/key/path
  20. ----
  21. ## 安装
  22. sh install.sh
  23. [Step 4]: starting Harbor ...
  24. Creating network "harbor_harbor" with the default driver
  25. Creating harbor-log ... done
  26. Creating registry ... done
  27. Creating harbor-portal ... done
  28. Creating registryctl ... done
  29. Creating redis ... done
  30. Creating harbor-db ... done
  31. Creating harbor-core ... done
  32. Creating nginx ... done
  33. Creating harbor-jobservice ... done
  34. ----Harbor has been installed and started successfully.----

2.2.3 创建镜像仓库

Day4-代码质量平台与制品库实践 - 图47

2.2.4 CI流水线中制品库集成

镜像规范

业务/服务:commitId

镜像上传

  1. docker login 192.168.1.200:8088
  2. Username: admin
  3. Password:
  4. WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
  5. Configure a credential helper to remove this warning. See
  6. https://docs.docker.com/engine/reference/commandline/login/#credentials-store
  7. Login Succeeded
  8. # docker tag nginx:1.9.1 192.168.1.200:8088/devops/devops-nginx-service:1.9.1
  9. # docker tag nginx:1.9.1 192.168.1.200:8088/devops/devops-nginx-service:1.9.2
  10. # docker push 192.168.1.200:8088/devops/devops-nginx-service:1.9.2
  11. The push refers to repository [192.168.1.200:8088/devops/devops-nginx-service]
  12. 5f70bf18a086: Layer already exists
  13. 23923d6d8fc4: Layer already exists
  14. 2471231f3381: Layer already exists
  15. 21d3d9e179b7: Layer already exists
  16. 7dc0e946afc6: Layer already exists
  17. a622086a695f: Layer already exists
  18. d55f823e63e3: Layer already exists
  19. 1.9.2: digest: sha256:a42a428525996f3a84d466ee628a074cac568e0e8c99b5d6f7398be342337039 size: 2805

镜像下载

  1. docker pull 192.168.1.200:8088/devops/devops-nginx-service:1.9.2

2.1.5 Harbor REST API

http://192.168.1.200:8088/devcenter-api-2.0

Day4-代码质量平台与制品库实践 - 图48