| 时间 | 标题 | 内容 |
|---|---|---|
上午 |
代码质量平台实践 (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未成功下载文件的解决方法:
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文件内容:
curl --header "Private-Token: FUZwKwZ713ST" "http://www.gitlab.com/api/v4/projects/50/repository/files/Jenkinsfile/raw?ref=master"
1. 代码质量平台实践
1.1 SonarQube 简介
SonarQube®是一种自动代码审查工具,可检测代码中的错误,漏洞和代码味道。它可以与您现有的工作流程集成,以实现跨项目分支和拉取请求的持续代码检查。

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


- 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
访问: [http://192.168.1.200:9000/](http://192.168.1.200:9000/about)<br /><br />默认账号: admin/admin<br /><a name="nEjMJ"></a>### 安装中文插件在线安装或者手动上传插件**在线安装:操作如下图**<br />阅**手动上传插件**为什么需要手动安装? 在线源可能会失败,超时。```bashCaused 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)at org.sonar.core.util.DefaultHttpDownloader.failToDownload(DefaultHttpDownloader.java:155)at org.sonar.core.util.DefaultHttpDownloader.download(DefaultHttpDownloader.java:150)at org.sonar.server.plugins.PluginDownloader.downloadRelease(PluginDownloader.java:152)at org.sonar.server.plugins.PluginDownloader.download(PluginDownloader.java:126)... 47 common frames omittedCaused 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
https://github.com/xuhuisheng/sonar-l10n-zh/releases/tag/sonar-l10n-zh-plugin-1.29
cd /data/cicd/sonarqube/sonarqube_extensions/downloadswget https://github.com/xuhuisheng/sonar-l10n-zh/releases/download/sonar-l10n-zh-plugin-1.29/sonar-l10n-zh-plugin-1.29.jarchmod +x sonar-l10n-zh-plugin-1.29.jardocker restart sonarqube
插件源:https://update.sonarsource.org/
文档: 待补充
配置强制登录
默认所有项目都可以公开的查看,在企业内肯定要配置成私有的。只有登录后才能查看。
配置Scanner
- Gradle - SonarScanner for Gradle
- .NET - SonarScanner for .NET
- Maven - use the SonarScanner for Maven
- Jenkins - SonarScanner for Jenkins
- Azure DevOps - SonarQube Extension for Azure DevOps
- Ant - SonarScanner for Ant
- anything else (CLI) - SonarScanner
wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.6.0.2311-linux.ziptar zxf sonar-scanner-xxxx.tar.gz -C /usr/localvim /etc/profileexport SCANNER_HOME=/usr/local/sonar-scannerxxxexport PATH=$PATH:$SCANNER_HOME/binsource /etc/profile/usr/local/sonar-scanner-4.6.0.2311-linux/bin[root@zeyang-nuc-service bin]# vi /etc/profile[root@zeyang-nuc-service bin]# sourece /etc/profilebash: sourece: command not found...[root@zeyang-nuc-service bin]# source /etc/profile[root@zeyang-nuc-service bin]# sonar-scanner -vINFO: Scanner configuration file: /usr/local/sonar-scanner-4.6.0.2311-linux/conf/sonar-scanner.propertiesINFO: Project root configuration file: NONEINFO: SonarScanner 4.6.0.2311INFO: Java 11.0.3 AdoptOpenJDK (64-bit)INFO: Linux 4.18.0-80.el8.x86_64 amd64
修改scanner的java使用版本
[root@zeyang-nuc-service sonar-scanner-4.6.0.2311-linux]# vi bin/sonar-scanner[root@zeyang-nuc-service sonar-scanner-4.6.0.2311-linux]#[root@zeyang-nuc-service sonar-scanner-4.6.0.2311-linux]# sonar-scanner -vINFO: Scanner configuration file: /usr/local/sonar-scanner-4.6.0.2311-linux/conf/sonar-scanner.propertiesINFO: Project root configuration file: NONEINFO: SonarScanner 4.6.0.2311INFO: Java 1.8.0_282 AdoptOpenJDK (64-bit)INFO: Linux 4.18.0-80.el8.x86_64 amd64
1.3 SonarScanner使用方法
- 配置文件方式读取扫描参数
- 命令行方式读取扫描参数
一个基本的sonar-project.properties配置文件的参数:
# 定义唯一的关键字sonar.projectKey=devops-hello-service# 定义项目名称sonar.projectName=My project# 定义项目的版本信息sonar.projectVersion=1.0# 指定扫描代码的目录位置(多个逗号分隔)sonar.sources=.# 执行项目编码sonar.sourceEncoding=UTF-8sonar.host.url=sonar.loginsonar.password
这些配置项都是统一的,目前sonar支持将扫描参数以文件的方式存放或者以命令行传参的方式读取。 文件方式:可以将扫描参数放到项目的根目录或者sonar-scanner的配置文件目录等自定义的目录中, 命令行传参则可以直接将变量传递给sonarsacnner cli -Dsonar.projectKey=xxx 。
# 指定配置文件sonar-scanner -Dproject.settings=myproject.properties# 命令行传参sonar-scanner -Dsonar.projectKey=myproject -Dsonar.sources=src1
扩展-Docker运行sonarscanner
docker run \--rm \-e SONAR_HOST_URL="http://${SONARQUBE_URL}" \-e SONAR_LOGIN="myAuthenticationToken" \-v "${YOUR_REPO}:/usr/src" \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)
[root@zeyang-nuc-service ~]# cd /data/cicd/plugin-sonar/[root@zeyang-nuc-service plugin-sonar]# lssonar-go-plugin-1.6.0.719.jar sonar-l10n-zh-plugin-1.29.jarsonar-java-plugin-6.3.2.22818.jar sonar-typescript-plugin-2.1.0.4359.jarsonar-javascript-plugin-6.2.2.13315.jar[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/[root@zeyang-nuc-service plugin-sonar]# ls /data/cicd/sonarqube/sonarqube_extensions/downloads/sonar-go-plugin-1.6.0.719.jar sonar-javascript-plugin-6.2.2.13315.jarsonar-java-plugin-6.3.2.22818.jar sonar-typescript-plugin-2.1.0.4359.jar[root@zeyang-nuc-service plugin-sonar]# chmod +x /data/cicd/sonarqube/sonarqube_extensions/downloads/*[root@zeyang-nuc-service plugin-sonar]# ls /data/cicd/sonarqube/sonarqube_extensions/downloads/sonar-go-plugin-1.6.0.719.jar sonar-javascript-plugin-6.2.2.13315.jarsonar-java-plugin-6.3.2.22818.jar sonar-typescript-plugin-2.1.0.4359.jar[root@zeyang-nuc-service plugin-sonar]# docker restart sonarqubesonarqube
1.3.1 Java项目扫描
sonarqube服务器端需要安装Java语言规则插件
sonar.projectKey 指定项目的关键字,sonar.host.url指定服务器地址(可以直接在配置文件中写死),projectName指定项目的名称, projectVersion指定项目的版本(可以用构建时间和构建ID定义),login指定登录用户名,password指定登录用户密码, projectDescription指定项目的描述信息, links.homepage指定项目的主页(超链接), sources指定扫描的目录, sourceEncoding指定扫描时的编码, **java.binaries**指定编译后的类文件目录(必填), **java.test.binaries**指定编译后的测试类目录,**java.surefire.report**指定测试报告目录。
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
1.3.2 Web前端项目扫描

sonar.projectKey=devops-web-servicesonar.projectName=devops-web-servicesonar.projectVersion=1.0sonar.sources=src#sonar.sources=dist/static/jssonar.host.url=http://192.168.1.200:9000sonar.login=adminsonar.password=adminsonar.sourceEncoding=UTF-8
1.3.4 Golang项目扫描

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.gosonar.tests=.sonar.test.inclusions=**/*_test.go
1.4 CI流水线集成
shell 命令行方式
流水线中添加代码扫描阶段
def buildTools = [ "maven" : "/usr/local/apache-maven-3.8.1","gradle": "/usr/local/gradle-6.8.3/","golang": "/usr/local/go","web" : "/usr/local/node-v14.16.1-linux-x64/","sonar" : "/usr/local/sonar-scanner-4.6.0.2311-linux"]pipeline {stages{stage("SonarScan"){steps{script{sh """${buildTools["sonar"]}/bin/sonar-scanner -Dproject.settings=sonar.properties \-Dsonar.login=admin \-Dsonar.password=admin \-Dsonar.host.url=http://192.168.1.200:9000"""}}}}}
Jenkins 插件方式
参考:https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-jenkins/
创建SonaQube的账户token
将token保存到Jenkins凭据中
在Jenkins中安装插件sonarqube scanner。
然后转到”管理Jenkins>系统配置“,向下滚动到SonarQube配置部分,单击Add SonarQube,添加服务器,选择凭据。
使用withSonarQubeEnv DSL引入在Jenkins中配置的sonar环境。
//使用sonar服务器stage("SonarScanForPlugin"){steps{script{withSonarQubeEnv("mysonarserver"){def sonarDate = sh returnStdout: true, script: 'date +%Y%m%d%H%M%S'sonarDate = sonarDate - "\n"sh """${buildTools["sonar"]}/bin/sonar-scanner \-Dsonar.projectKey=${JOB_NAME} \-Dsonar.projectName=${JOB_NAME} \-Dsonar.projectVersion=${sonarDate} \-Dsonar.ws.timeout=30 \-Dsonar.projectDescription="my test project" \-Dsonar.links.homepage=http://www.baidu.com \-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 \#echo \$PATH"""}}}}
FAQ: sonar服务器名称错误,需要与系统设置中配置的一致。
ERROR: SonarQube installation defined in this job (mysonarserver) does not match any configured installation. Number of installations that can be configured: 1.If you want to reassign jobs to a different SonarQube installation, check the documentation under https://redirect.sonarsource.com/plugins/jenkins.html
最终的效果如下:
1.5 SonarQube REST API实践
http://192.168.1.200:9000/web_api
//查找项目api/projects/search?projects=${projectName}"//创建项目api/projects/create?name=${projectName}&project=${projectName}"//更新语言规则集api/qualityprofiles/add_project?language=${language}&qualityProfile=${qualityProfile}&project=${projectName}"//项目授权api/permissions/apply_template?projectKey=${projectKey}&templateName=${templateName}"//更新质量阈api/qualitygates/select?projectKey=${projectKey}&gateId=${gateId}"
HTTP Request Plugin

stage("GetCode"){steps{script{def response = httpRequest authentication: '4675830a-4330-4dd6-9185-cf62161967f0',url: 'http://192.168.1.200:9000/api/projects/search?projects=devops-maven2-service',wrapAsMultipart: falseprint(response.content)}}}
//封装HTTPdef 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: truereturn response}//搜索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 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 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)}//获取质量阈IDdef 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.6 其他日常使用问题
1.6.1 规则的禁用与启用
目的: 掌握默认规则中的一部分规则如何激活和禁用。
进入质量配置页面, 可以看到所有的语言规则配置。在这里可以看到规则的使用情况。
这里假设我要调整Go语言的规则配置, 点击规则数量数字。 

创建新的规则集
点击更多激活规则, 进入规则设置页面。
激活或者下线规则。(活动/挂起)
使用规则: 先在页面配置项目,然后使用SonarScanner扫描。

1.6.2 质量阈的配置
目的: 适用于以质量门禁作为交付关卡。

1.6.3 代码覆盖率统计
找一个具有大量单元测试的项目, 然后集成jacoco插件,生成覆盖率报告,最后由sonar收集。
Maven集成Jacoco
添加jacoco-maven-plugin 和junit插件。
<dependencies><dependency><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.2</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies>
添加插件
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.6.1</version><configuration><skipMain>true</skipMain><skip>true</skip><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.7.5.201505241946</version><executions><execution><id>prepare-agent</id><goals><goal>prepare-agent</goal></goals></execution><execution><id>report</id><phase>prepare-package</phase><goals><goal>report</goal></goals></execution><execution><id>post-unit-test</id><phase>test</phase><goals><goal>report</goal></goals><configuration><dataFile>target/jacoco.exec</dataFile><outputDirectory>target/jacoco-reports</outputDirectory></configuration></execution></executions><configuration><systemPropertyVariables><jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile></systemPropertyVariables></configuration></plugin>
SonarQube安装Jacoco插件
https://github.com/SonarSource/sonar-jacoco/releases/download/1.1.0.898/sonar-jacoco-plugin-1.1.0.898.jar
# 指定代码覆盖率工具为jacocosonar.core.codeCoveragePlugin=jacoco# 指定exec二进制文件存放路径sonar.jacoco.reportPaths=target/jacoco.exec
cd devops-jacoco-service/sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \-Dsonar.projectKey=devops-jacoco-service \-Dsonar.projectName=devops-jacoco-service \-Dsonar.projectVersion=1.0 \-Dsonar.login=admin \-Dsonar.password=admin \-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.test.binaries=target/test-classes \-Dsonar.java.surefire.report=target/surefire-reports \-Dsonar.core.codeCoveragePlugin=jacoco \-Dsonar.jacoco.reportPaths=target/jacoco.exec
1.6.4 多分支代码扫描
https://github.com/mc1arke/sonarqube-community-branch-plugin/releases
将插件放到extensions/plugins 和 lib/common目录中,然后重启sonar。
## 临时方案docker exec -it sonarqube bashcd /opt/sonarqube/lib/commoncp ../../extensions/plugins/sonarqube-community-branch-plugin-1.3.2 ./exitdocker restart sonarqube## 持久化lib目录后[root@zeyang-nuc-service sonarqube]# lssonarqube_conf sonarqube_data sonarqube_extensions sonarqube_lib sonarqube_logs[root@zeyang-nuc-service sonarqube]# cp /root/sonarqube-community-branch-plugin-1.3.2.jar sonarqube_extensions/plugins/[root@zeyang-nuc-service sonarqube]# chmod +x sonarqube_extensions/plugins/sonarqube-community-branch-plugin-1.3.2.jar[root@zeyang-nuc-service sonarqube]#[root@zeyang-nuc-service sonarqube]#[root@zeyang-nuc-service sonarqube]# cp /root/sonarqube-community-branch-plugin-1.3.2.jar sonarqube_lib/common/[root@zeyang-nuc-service sonarqube]# chmod +x sonarqube_lib/common/sonarqube-community-branch-plugin-1.3.2.jar[root@zeyang-nuc-service sonarqube]#docker restart sonarqube

##扫描参数增加 –Dsonar.branch.name=sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \-Dsonar.projectKey=devops-maven2-service \-Dsonar.projectName=devops-maven2-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 \-Dsonar.branch.name=release-1.1.1
FAQ: 需要先把主分支扫描一遍,不然会报错。
ERROR: Error during SonarScanner executionERROR: No branches currently exist in this project. Please scan the main branch without passing any branch parameters.ERROR:ERROR: Re-run SonarScanner using the -X switch to enable full debug logging.

1.6.5 扫描结果关联commitid
提前装好插件:https://github.com/gabrie-allaigre/sonar-gitlab-plugin/tree/4.1.0-SNAPSHOT插件的说明文档查看该插件的Readme文档。
[root@zeyang-nuc-service ~]# cp sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar /data/cicd/sonarqube/sonarqube_extensions/plugins/[root@zeyang-nuc-service ~]# chmod +x /data/cicd/sonarqube/sonarqube_extensions/plugins/sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar[root@zeyang-nuc-service ~]# docker restart sonarqube

-Dsonar.gitlab.failure_notification_mode 值为commit-status表示更改提交状态, 值为nothing不做任何动作。
sonar-scanner -Dsonar.host.url=http://192.168.1.200:9000 \-Dsonar.projectKey=devops-maven2-service \-Dsonar.projectName=devops-maven2-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 \-Dsonar.branch.name=release-1.1.1 \-Dsonar.gitlab.commit_sha=665c36c3d0036942612f950d1dc42a433ec03f6d \-Dsonar.gitlab.ref_name=release-1.1.1 \-Dsonar.gitlab.project_id=3 \-Dsonar.dynamicAnalysis=reuseReports \-Dsonar.gitlab.failure_notification_mode=commit-status \-Dsonar.gitlab.url=http://192.168.1.200 \-Dsonar.gitlab.user_token=Hc-a6dEidbyxgcsTvbEr \-Dsonar.gitlab.api_version=v4
效果

1.6.6 控制代码扫描步骤运行
String skipSonar = "${env.skipSonar}"stage("SonarScan"){when {environment name: 'skipSonar', value: 'false'}}

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安装部署配置
docker pull sonatype/nexus3:3.30.0mkdir -p /data/cicd/nexus3/datachmod 777 -R /data/cicd/nexus3/docker run -itd \--privileged=true --name=nexus3 \-p 8081:8081 \-v /data/cicd/nexus3/data:/nexus-data \sonatype/nexus3:3.30.0
日志查看Nexus是否已启动并准备就绪,请运行以下命令:
docker logs nexus3 -f
在日志中,看到消息:Started Sonatype Nexus OSS 3.30.0-01这意味着Nexus Repository Manager可以使用了。现在转到浏览器并打开.
http://your-ip-addr:8081
安装完成后, 默认的admin账号密码存储在了数据目录,获取初始化密码:
docker exec -i nexus3 cat /nexus-data/admin.password
登录后更新密码 admin/admin123
2.1.3 Nexus制品库搭建
搭建Maven私服(代理仓库)
默认安装nexus后会自动创建的。
私服: 将外网仓库代理到企业内容本地仓库中。 图中的地址可以自定义修改。
搭建制品库(本地仓库)
新建raw类型的仓库
设置仓库的信息
2.1.4 CI流水线中制品库集成
制品规范
按照 业务/服务/版本 层级。
依赖上传
我们需要在nexus中创建一个新的仓库maven-hostd,同时我们需要在maven的配置文件settings.xml中配置maven-hostd认证。如下:
<server><id>maven-hosted</id><username>admin</username><password>admin123</password></server>
注意使用mvn deploy 发布时,server.id == respository.id。
mvn deploy:deploy-file-DgroupId=xxxxxx pom中的groupId-DartifactId=xxxxxx pom中的artifactId-Dversion=xxxxxx pom中的版本号version-Dpackaging=xxxxxx pom中打包方式-Dfile=xxxxxx 本地文件-Durl=xxxxxx 仓库url-DrepositoryId=xxxxxx 对应的是setting.xml(认证)
直接读取pom文件(方便)
mvn deploy:deploy-file \-DgeneratePom=false \-DrepositoryId=maven-hosted \-Durl=http://192.168.1.200:8081/repository/maven-hosted/ \-DpomFile=pom.xml \-Dfile=target/demo-0.0.1-SNAPSHOT.jar
自定义pom信息(灵活)
mvn deploy:deploy-file -Dmaven.test.skip=true \-Dfile=target/demo-0.0.1-SNAPSHOT.jar \-DgroupId=com.example \-DartifactId=demo \-Dversion=1.1.1 \-Dpackaging=jar \-DrepositoryId=maven-hosted \-Durl=http://192.168.1.200:8081/repository/maven-hosted/


FAQ:
[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。
nexusArtifactUploader artifacts: [[ artifactId: 'myapp',classifier: '',file: './target/demo-0.0.1-SNAPSHOT.jar',type: 'jar']],credentialsId: 'cabaa495-918b-4e73-9090-eafd5ac98c1b',groupId: 'com.devops',nexusUrl: '192.168.1.200:8081',nexusVersion: 'nexus3',protocol: 'http',repository: 'maven-hosted',version: '1.1.1'
发布制品
安装Maven Artifact ChoiceListProvider (Nexus)插件
用户选择制品,在应用服务器通过salt、ansible下载制品并部署

2.1.5 Nexus REST API
http://192.168.1.200:8081/#admin/system/api
2.2 Harbor镜像库实践
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
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composecp docker-compose-Linux-x86_64 /usr/local/bin/docker-composechmod +x /usr/local/bin/docker-compose## 测试命令docker-composeDefine and run multi-container applications with Docker.Usage:docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]docker-compose -h|--help
下载release包: https://goharbor.io/docs/2.2.0/install-config/download-installer/
https://github.com/goharbor/harbor/releases

## 解压tar zxf harbor-online-installer-v1.10.4.tgzcd harbor## 编辑配置文件vim harbor.yml----### 修改主机名,注释httpshostname: 192.168.1.200# http related confighttp:# port for http, default is 80. If https enabled, this port will redirect to https portport: 80# https related config#https:# https port for harbor, default is 443# port: 443# The path of cert and key files for nginx#certificate: /your/certificate/path#private_key: /your/private/key/path----## 安装sh install.sh[Step 4]: starting Harbor ...Creating network "harbor_harbor" with the default driverCreating harbor-log ... doneCreating registry ... doneCreating harbor-portal ... doneCreating registryctl ... doneCreating redis ... doneCreating harbor-db ... doneCreating harbor-core ... doneCreating nginx ... doneCreating harbor-jobservice ... done✔ ----Harbor has been installed and started successfully.----
2.2.3 创建镜像仓库

2.2.4 CI流水线中制品库集成
镜像规范
业务/服务:commitId
镜像上传
docker login 192.168.1.200:8088Username: adminPassword:WARNING! Your password will be stored unencrypted in /root/.docker/config.json.Configure a credential helper to remove this warning. Seehttps://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded# docker tag nginx:1.9.1 192.168.1.200:8088/devops/devops-nginx-service:1.9.1# docker tag nginx:1.9.1 192.168.1.200:8088/devops/devops-nginx-service:1.9.2# docker push 192.168.1.200:8088/devops/devops-nginx-service:1.9.2The push refers to repository [192.168.1.200:8088/devops/devops-nginx-service]5f70bf18a086: Layer already exists23923d6d8fc4: Layer already exists2471231f3381: Layer already exists21d3d9e179b7: Layer already exists7dc0e946afc6: Layer already existsa622086a695f: Layer already existsd55f823e63e3: Layer already exists1.9.2: digest: sha256:a42a428525996f3a84d466ee628a074cac568e0e8c99b5d6f7398be342337039 size: 2805
镜像下载
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

