制品库平台实践-nexus
制品库平台实践-nexus

目录
[TOC]
本节实践
| 实战名称 |
|---|
| 💘 实践:配置Maven代理仓库(测试成功)-2022.6.7 |
| 💘 实践:创建Maven本地仓库(依赖)-2022.6.10(测试成功) |
| 💘 实践:创建Raw本地仓库(制品)(测试成功)-2022.6.10 |
| 💘 实践:使用管理页面上传制品(测试成功)-2023.6.27 |
| 💘 实践:使用mvn命令上传制品(自定义pom信息(灵活))-2022.6.11 |
| 💘 实践:直接读取pom文件(扩展)-2022.6.11(测试成功) |
| 💘 实践:使用Jenkins插件上传制品(把信息写死)(测试成功)-2023.6.28 |
| 💘 实践:使用Jenkins插件上传制品(读取POM文件上传制品)(测试成功)-2023.6.28 |
| 💘 扩展: 可以在Jenkins页面添加参数, 让用户输入后进行发布(测试成功)-2023.6.28 |
| 💘 实践:Jenkins插件获取包路径-2023.6.29(测试成功) |
| 💘 实践:CI综合实践-2023.6.29(测试成功) |
1、Nexus基本功能简介
官网:https://www.sonatype.com/products/nexus-repository?topnav=true 官方文档: https://help.sonatype.com/repomanager3/product-information/release-notes
工作流定义:
- 集成流水线: 提交代码,构建,单测,代码扫描,上传制品【生成制品】
- 发布流水线: 输入版本号, 输入部署环境.(从对应环境的制品库中取制品)
制品类型: 二进制制品, docker镜像
核心技能点:
- 制品库管理规范(创建)
- 上传制品
- 下载制品
从3.x开始,它默认支持许多主流的软件包格式。Docker、Maven、Npm:

仓库类型:
- proxy 代理仓库。
- hosted 私有仓库。
- group 仓库组,将多个仓库组合在一起,通过同一个URL对外提供。
代理仓库 : Maven、Npm等。用于存储外网公共仓库中的插件和依赖,不可进行修改和私自上传。
2、Nexus3安装部署配置
见独立md。
3、Nexus制品库应用实践
1.搭建Maven私服(代理仓库)
默认开发同学在进行开发的时候会使用一些包管理工具,例如:maven、ant、gradle这些都是常见项目编译构建工具 。这些工具可以理解为是一个命令行工具, 本身不会存储任何依赖包,而是通过公网官方的仓库中下载当前项目构建所需要的包。 (内网的速度要比公网快,这会直接影响管道的构建速度)

使用私服,就是在企业内部建立单一的可信源, 例如:我们在公司通过nexus创建一个代理仓库, 将公网仓库中的maven包代理到内网仓库中。 这样整个公司的同学就可以直接访问内网的私服进行下载构建依赖包。(减少了引入不信任依赖的风险)
代理仓库不会一下子把公网仓库中的所有包下载到本地,而是按需缓存。 例如: 此时我需要使用aa这个包, 如果代理仓库中没有, 则请求外部服务器下载这个包并进行缓存。第二次访问的时候,就直接访问代理仓库了。、
安装nexus后,默认存在以下图中的仓库, 这些仓库是官方默认配置好的maven私服。(可以直接使用)

进入其中一个仓库, 可以看到默认的配置。即: 代理公网repo1中的包到本地;

| 💘 实践:配置Maven代理仓库(测试成功)-2022.6.7 |

- 实验环境
1nexus3.39.0-01
2apache-maven-3.8.5
- 实验软件(无)
- 创建
proxy-aliyun-maven仓库:仓库类型选择proxy,制品策略类型选择Release,其他默认。



- 编辑maven构建节点的
settings.xml文件,配置阿里云代理仓库地址
1[root@devops conf]#vim /usr/local/apache-maven-3.8.5/conf/settings.xml
2https://maven.aliyun.com/repository/public

注意:


- 创建完成后如下:

http://172.29.9.101:8081/repository/proxy-aliyun-maven/

- 配置maven软件的配置文件
1[root@devops conf]#vim /usr/local/apache-maven-3.8.5/conf/settings.xml
2<url>http://172.29.9.101:8081/repository/proxy-aliyun-maven/</url>

- 删除本地缓存:
1[root@devops conf]#rm -rf ~/.m2/
2[root@devops conf]#rm -rf /data/maven_build_cache/*
1[root@devops conf]#vim /usr/local/apache-maven-3.8.5/conf/settings.xml

- 测试效果:
来到一个java项目里,使用maven进行测试效果:
1[root@devops devops4-maven-service-master]#pwd
2/root/devops4-maven-service-master
3[root@devops devops4-maven-service-master]#ls
4build.sh mvnw mvnw.cmd pom.xml README.md sonar-project.properties src
5[root@devops devops4-maven-service-master]#mvn clean package

此时会报一个错误的,这里我们要配置下权限:
这种公网的,我们一般不加权限:

再次构建,观察效果:

可以看到能够正常下载。
- 来到这里也是可以看到下载的包:

测试成功。😘
2.搭建制品库(本地仓库 依赖包)
本地仓库:以Maven为例:
- RELEASE类型仓库(存放制品稳定版) 这个里面的包一般是需要手动指定的;
- SNAPSHOT类型仓库(存放制品开发版) 这个里面的包一般是自动生成版本号的;

切记:release类型的仓库只能存放release版本的包。不能将release类型的包上传到snapshot仓库,同理snapshot类型的包也不能上传到release类型的仓库中。
- 新建raw类型的仓库: raw可以理解为普通的文件存储;
raw格式就是一块普通的存储。(制品就传到这种类型的仓库里去)

① 创建Maven本地仓库(依赖)
| 💘 实践:创建Maven本地仓库(依赖)-2022.6.10(测试成功) |

- 创建仓库:

选择hosted类型:

- 定义和配置仓库的信息: 名称、存储、是否允许重新上传:

最后点击Create repositry:

- 观察效果:


- 同理,我们再创建一个
devops4-release的本地仓库:


测试完成。😘
② 创建Raw本地仓库(制品)
| 💘 实践:创建Raw本地仓库(制品)(测试成功)-2022.6.10 |

- 创建仓库:

选择raw(hosted)类型:

填写仓库名,并创建:

- 观察效果:

- 模拟上传一个图片:



测试结束。😘
4、CI流水线中集成制品库
1.使用管理页面上传制品
页面很方便上传,但是有时候不太好用…例如出现上传失败等问题(暂时无法解决,不同版本的nexus有些api不对应的坑)。
| 💘 实践:使用管理页面上传制品(测试成功)-2023.6.27 |
- 我们来创建
maven-devops6-release和maven-devops6-snapshot2个maven仓库


- 这次来手动上传下jenkins agent的
agent.jar包。

- 先来模拟一次报错提示


我们指定jar包Version是1.1.1-SNAPSHOT,但是我们往RELEASE类型的仓库上传,肯定就会报错的啦。
- 我们改变下这里的Version字段内容,然后再次上传,观察下现象



此时,就可以正常上传成功了。
2.使用maven指令上传制品
参考:https://support.sonatype.com/hc/en-us/articles/213465818-How-can-I-programmatically-upload-an-artifact-into-Nexus-2-


如果是0.0.1或者0.0.1-RELEASE,就是RELEASE版本。
🍀 扩展:
如果是maven类型的具有源码的项目, 可以直接使用mvn命令上传,更加方便。
1//上传制品使用maven命令
2def PushArtifactsByMvn(repoName,filePath ){
3 sh """
4 mvn deploy:deploy-file \
5 -DgeneratePom=false \
6 -DrepositoryId="maven-hosted" \
7 -Durl=http://192.168.1.200:8081/repository/"${repoName}" \
8 -DpomFile=pom.xml \
9 -Dfile="${filePath}"
10 """
11}
12
13PushArtifactsByMvn("${params.repoName}","target/${pkg}")
① 方法1:使用mvn命令上传制品(自定义pom信息(灵活))
| 💘 实践:使用mvn命令上传制品(自定义pom信息(灵活))-2022.6.11 |
- 实验环境
1sonatype/nexus3:3.53.0
2apache-maven-3.9.2
实验软件(无)
上传制品之前, 肯定得确定目标仓库是存在的。 如果不存在我们可以新建一个 hosted类型的maven仓库。

- 仓库已经有了, 需要更新maven的配置文件,在settings.xml中添加仓库的认证信息。如下:
1 <server>
2 <id>mymaven</id>
3 <username>admin</username>
4 <password>admin123</password>
5 </server>
1[root@devops ~]#vim /usr/local/apache-maven-3.8.5/conf/settings.xml
2 <server>
3 <id>mymaven</id>
4 <username>admin</username>
5 <password>admin123</password>
6 </server>

- 上传制品前记得先要编译构建下的:
1[root@devops ~]#cd
2[root@devops ~]#cd devops4-maven-service-master
3[root@devops devops4-maven-service-master]#ls
4build.sh mvnw mvnw.cmd pom.xml README.md sonar-project.properties src target
5[root@devops devops4-maven-service-master]#mvn clean package

1[root@devops devops4-maven-service-master]#pwd
2/root/devops4-maven-service-master
3[root@devops devops4-maven-service-master]#ls
4build.sh mvnw mvnw.cmd pom.xml README.md sonar-project.properties src target
5[root@devops devops4-maven-service-master]#ls target/
6classes demo-0.0.1-SNAPSHOT.jar demo-0.0.1-SNAPSHOT.jar.original maven-archiver
- 开始上传:
注意使用mvn deploy 发布时,-DrepositoryId参数的值要与上面配置文件中的<server>标签中的<id>一致。不然会出现401,用户认证失败的问题。
1mvn 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(认证)
Maven上传报错, 401 可以确定是认证的错误。 需要检查认证信息。
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.devops:zeyang:jar:1.1.1 from/to remote-repository (http://192.168.1.200:8081/repository/devops-maven/): authentication failed for http://192.168.1.200:8081/repository/devops-maven/com/devops/zeyang/1.1.1/zeyang-1.1.1.jar, status: 401 Unauthorized -> [Help 1]

替换参数, 执行命令开始上传制品。
1mvn deploy:deploy-file \
2-DgroupId=com.devops \
3-DartifactId=xyy \
4-Dversion=1.1.1-snapshot \
5-Dpackaging=jar \
6-Dfile=target/demo-0.0.1-SNAPSHOT.jar \
7-Durl=http://172.29.9.101:8081/repository/devops4-snapshot/ \
8-DrepositoryId=mymaven

- 我们再次修改下参数观察下效果:
1mvn deploy:deploy-file \
2-DgroupId=com.devops \
3-DartifactId=xyy \
4-Dversion=1.1.1-SNAPSHOT \
5-Dpackaging=jar \
6-Dfile=target/demo-0.0.1-SNAPSHOT.jar \
7-Durl=http://172.29.9.101:8081/repository/devops4-snapshot/ \
8-DrepositoryId=mymaven
9
10
11#注意:默认是会生成pom文件的。
12#如果不想生成pom文件,则可以使用如下选项
13-DgeneratePom=false
这里的
-Dversion=1.1.1-SNAPSHOTSNAPSHOT一定要大写才行的!否则会被认为是release类型的制品,当然也就不能上传到snapshot仓库了。
可以看到,本次上传成功了:

备注:Pom文件就是个坐标。

- 验证:制品已经上传成功了。

测试成功。😘
② 方法2:直接读取pom文件(扩展)
| 💘 实践:直接读取pom文件(扩展)-2022.6.11(测试成功) |
- 实验环境
- 默认项目下是已经有
pom.xml文件了:
1sonatype/nexus3:3.53.0
2apache-maven-3.9.2
- 实验软件(无)
1[root@devops devops4-maven-service-master]#ls
2build.sh mvnw mvnw.cmd pom.xml README.md sonar-project.properties src target
3[root@devops devops4-maven-service-master]#cat pom.xml

- 这里直接使用命令上传:
1mvn deploy:deploy-file \
2-DgeneratePom=true \
3-DrepositoryId=mymaven \
4-Durl=http://172.29.9.101:8081/repository/devops4-snapshot/ \
5-DpomFile=pom.xml \
6-Dfile=target/demo-0.0.1-SNAPSHOT.jar


- 验证:

测试成功。😘
⚠️ FAQ:
release类型的仓库只能上传release版本的包。如果你尝试用snapshot包上传到release类型的仓库时会遇到这些错误的。
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 from/to maven-hosted (http://192.168.1.200:8081/repository/maven-zeyang-test/): transfer failed for http://192.168.1.200:8081/repository/maven-zeyang-test/com/example/demo/0.0.1/demo-0.0.1.jar, status: 400 Repository version policy: SNAPSHOT does not allow version: 0.0.1 -> [Help 1]

解决方法: 1. 更新pom中的版本号 2. 对号入座,上传到对应类型的仓库。
1<groupId>com.example</groupId>
2<artifactId>myapp</artifactId>
3<version>0.0.2-SNAPSHOT</version> //改成0.0.2-RELEASE
3.使用Jenkins插件上传制品
① 方法1:使用Jenkins插件上传制品(把信息写死)
| 💘 实践:使用Jenkins插件上传制品(把信息写死)(测试成功)-2023.6.28 |
- 安装插件:
Nexus Aritifact Uploader

- 使用片段生成器生成DSL:
找一个pipeline项目,生成流水线脚本:

新建一个nexus凭据:


生成代码:
1nexusArtifactUploader artifacts: [[artifactId: 'demo-app', classifier: '', file: 'target/xxx.jar', type: 'jar']], credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad', groupId: 'com.devops6', nexusUrl: '172.29.9.101:8081', nexusVersion: 'nexus3', protocol: 'http', repository: 'maven-devops6-release', version: '1.1.1'
调整下格式:
1nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
2 classifier: '',
3 file: 'target/xxx.jar',
4 type: 'jar']],
5 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
6 groupId: 'com.devops6',
7 nexusUrl: '172.29.9.101:8081',
8 nexusVersion: 'nexus3',
9 protocol: 'http',
10 repository: 'maven-devops6-release',
11 version: '1.1.1'
- 这边来到jenkins的
devops6-maven-service项目里,先跑一次流水线看下有问题没:


可以看到流水线是ok的。
- 我们再来写一下流水线代码:
1stage("PushArtifact"){
2 steps{
3 script{
4 PushArtifactByPlugin()
5 }
6 }
7
8
9}
10def PushArtifactByPlugin(){
11 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
12 classifier: '',
13 file: 'target/demo-0.0.1-SNAPSHOT.jar',
14 type: 'jar']],
15 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
16 groupId: 'com.devops6',
17 nexusUrl: '172.29.9.101:8081',
18 nexusVersion: 'nexus3',
19 protocol: 'http',
20 repository: 'maven-devops6-release',
21 version: '1.1.1'
22}

然后把这个代码放到上面项目的回放里,跑一次:
1@Library("devops06@main") _
2
3//import src/org/devops/Build.groovy
4def build = new org.devops.Build()
5def sonar = new org.devops.Sonar()
6
7currentBuild.displayName = "${env.branchName}-commitID"
8currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
9
10pipeline {
11 agent {label "build"}
12 options {
13 skipDefaultCheckout true
14 }
15
16
17 stages{
18 stage("CheckOut"){
19 steps{
20 script{
21 build.CheckOut()
22 }
23 }
24 }
25
26 stage("Build"){
27 steps{
28 script{
29 build.Build()
30 }
31 }
32
33 }
34
35 stage("CodeScan"){
36 when {
37 environment name: 'skipSonar', value: 'false'
38 }
39
40 steps{
41 script{
42
43 sonar.SonarScannerByPlugin()
44
45 }
46 }
47 }
48
49 stage("PushArtifact"){
50 steps{
51 script{
52 PushArtifactByPlugin()
53 }
54 }
55
56 }
57
58 }
59}
60
61
62def PushArtifactByPlugin(){
63 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
64 classifier: '',
65 file: 'target/demo-0.0.1-SNAPSHOT.jar',
66 type: 'jar']],
67 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
68 groupId: 'com.devops6',
69 nexusUrl: '172.29.9.101:8081',
70 nexusVersion: 'nexus3',
71 protocol: 'http',
72 repository: 'maven-devops6-release',
73 version: '1.1.1'
74}

可以看到,上传制品成功了:


- 下载制品,点击链接,下载就ok了。

测试成功。😘
② 方法2:使用Jenkins插件上传制品(读取POM文件上传制品)
| 💘 实践:使用Jenkins插件上传制品(读取POM文件上传制品)(测试成功)-2023.6.28 |
- 在
devops6-maven-servicegitlab项目里编辑下pom.xml文件,添加packaging选项并提交。
1<packaging>jar</packaging>

- 编写pipeline代码
1@Library("devops06@main") _
2
3//import src/org/devops/Build.groovy
4def build = new org.devops.Build()
5def sonar = new org.devops.Sonar()
6
7currentBuild.displayName = "${env.branchName}-commitID"
8currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
9
10pipeline {
11 agent {label "build"}
12 options {
13 skipDefaultCheckout true
14 }
15
16
17 stages{
18 stage("CheckOut"){
19 steps{
20 script{
21 build.CheckOut()
22 }
23 }
24 }
25
26 stage("Build"){
27 steps{
28 script{
29 build.Build()
30 }
31 }
32
33 }
34
35 stage("CodeScan"){
36 when {
37 environment name: 'skipSonar', value: 'false'
38 }
39
40 steps{
41 script{
42
43 sonar.SonarScannerByPlugin()
44
45 }
46 }
47 }
48
49 stage("PushArtifact"){
50 steps{
51 script{
52 //PushArtifactByPlugin()
53 PushArtifactByPluginPOM()
54 }
55 }
56
57 }
58
59 }
60}
61
62def PushArtifactByPlugin(){
63 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
64 classifier: '',
65 file: 'target/demo-0.0.1-SNAPSHOT.jar',
66 type: 'jar']],
67 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
68 groupId: 'com.devops6',
69 nexusUrl: '172.29.9.101:8081',
70 nexusVersion: 'nexus3',
71 protocol: 'http',
72 repository: 'maven-devops6-release',
73 version: '1.1.1'
74}
75
76def PushArtifactByPluginPOM(){
77 POM = readMavenPom file: 'pom.xml'
78 println(POM)
79 println("GroupID: ${POM.groupId}")
80 println("ArtifactID: ${POM.artifactId}")
81 println("Version: ${POM.version}")
82 println("Packaging: ${POM.packaging}")
83
84 env.artifactId = "${POM.artifactId}"
85 env.packaging = "${POM.packaging}"
86 env.groupId = "${POM.groupId}"
87 env.art_version = "${POM.version}"
88 env.art_name = "${env.artifactId}-${env.art_version}.${env.packaging}"
89 nexusArtifactUploader artifacts: [[artifactId: "${env.artifactId}",
90 classifier: '',
91 file: "target/${env.art_name}",
92 type: "${env.packaging}"]],
93 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
94 groupId: "${env.groupId}",
95 nexusUrl: '172.29.9.101:8081',
96 nexusVersion: 'nexus3',
97 protocol: 'http',
98 repository: 'maven-devops6-release',
99 version: "${env.art_version}"
100}

- 在回放里运行


发现报错:
将项目里的pom文件改成RELEASE版本。
将

改成

然后再次运行:

又一次报错,提示:status: 400 Repository does not allow updating assets: maven-devops6-release
应该是nexus3仓库里之前已经存在了这个包。
我们这里再改下version:

再次运行:


这次就运行成功了。

- 然后写到共享库里,再次运行测试


构建成功。
- 也可以修改上面这个版本,利用函数传参来演示
pipeline代码:
1@Library("devops06@main") _
2
3//import src/org/devops/Build.groovy
4def build = new org.devops.Build()
5def sonar = new org.devops.Sonar()
6
7currentBuild.displayName = "${env.branchName}-commitID"
8currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
9
10pipeline {
11 agent {label "build"}
12 options {
13 skipDefaultCheckout true
14 }
15
16
17 stages{
18 stage("CheckOut"){
19 steps{
20 script{
21 build.CheckOut()
22 }
23 }
24 }
25
26 stage("Build"){
27 steps{
28 script{
29 build.Build()
30 }
31 }
32
33 }
34
35 stage("CodeScan"){
36 when {
37 environment name: 'skipSonar', value: 'false'
38 }
39
40 steps{
41 script{
42
43 sonar.SonarScannerByPlugin()
44
45 }
46 }
47 }
48
49 stage("PushArtifact"){
50 steps{
51 script{
52 //PushArtifactByPlugin()
53 // PushArtifactByPluginPOM()
54 pomData = readMavenPom file: 'pom.xml'
55
56 buName = "${JOB_NAME}".split("-")[0]
57 repoName = "maven-${buName}-release"
58 file = "target/${pomData.artifactId}-${pomData.version}.${pomData.packaging}"
59 PushArtifactByPluginPOM(pomData.artifactId, file, pomData.packaging, pomData.groupId, repoName, pomData.version)
60 }
61 }
62
63 }
64
65 }
66}
67
68def PushArtifactByPlugin(){
69 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
70 classifier: '',
71 file: 'target/demo-0.0.1-SNAPSHOT.jar',
72 type: 'jar']],
73 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
74 groupId: 'com.devops6',
75 nexusUrl: '172.29.9.101:8081',
76 nexusVersion: 'nexus3',
77 protocol: 'http',
78 repository: 'maven-devops6-release',
79 version: '1.1.1'
80}
81
82
83// def PushArtifactByPluginPOM(){
84// POM = readMavenPom file: 'pom.xml'
85// println(POM)
86// println("GroupID: ${POM.groupId}")
87// println("ArtifactID: ${POM.artifactId}")
88// println("Version: ${POM.version}")
89// println("Packaging: ${POM.packaging}")
90
91// env.artifactId = "${POM.artifactId}"
92// env.packaging = "${POM.packaging}"
93// env.groupId = "${POM.groupId}"
94// env.art_version = "${POM.version}"
95// env.art_name = "${env.artifactId}-${env.art_version}.${env.packaging}"
96// nexusArtifactUploader artifacts: [[artifactId: "${env.artifactId}",
97// classifier: '',
98// file: "target/${env.art_name}",
99// type: "${env.packaging}"]],
100// credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
101// groupId: "${env.groupId}",
102// nexusUrl: '172.29.9.101:8081',
103// nexusVersion: 'nexus3',
104// protocol: 'http',
105// repository: 'maven-devops6-release',
106// version: "${env.art_version}"
107// }
108
109//函数方式
110def PushArtifactByPluginPOM(artifactId, file, type, groupId, repoName, version){
111 println(artifactId)
112 //demo
113 println("${file}, ${type}, ${groupId}, ${repoName}, ${version}")
114 //target/demo-0.0.1-SNAPSHOT.jar, jar, com.example, devops4-release, 0.0.1-SNAPSHOT
115 nexusArtifactUploader artifacts: [[artifactId: artifactId,
116 classifier: '',
117 file: file,
118 type: type]],
119 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
120 groupId: groupId,
121 nexusUrl: '172.29.9.101:8081',
122 nexusVersion: 'nexus3',
123 protocol: 'http',
124 repository: repoName,
125 version: version
126}


再次运行:



发现这个方法也是ok的。(haha,函数方式感觉nb一点,那这里就采用函数方式了哦。😂)
然后把这部分代码放到共享库里,再次测试下:



符合预期。
此时共享库里玩转代码如下:
PushArtifact.groovy文件:
1package org.devops
2
3def PushArtifactByPlugin(){
4 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
5 classifier: '',
6 file: 'target/demo-0.0.1-SNAPSHOT.jar',
7 type: 'jar']],
8 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
9 groupId: 'com.devops6',
10 nexusUrl: '172.29.9.101:8081',
11 nexusVersion: 'nexus3',
12 protocol: 'http',
13 repository: 'maven-devops6-release',
14 version: '1.1.1'
15}
16
17// def PushArtifactByPluginPOM(){
18// POM = readMavenPom file: 'pom.xml'
19// println(POM)
20// println("GroupID: ${POM.groupId}")
21// println("ArtifactID: ${POM.artifactId}")
22// println("Version: ${POM.version}")
23// println("Packaging: ${POM.packaging}")
24
25// env.artifactId = "${POM.artifactId}"
26// env.packaging = "${POM.packaging}"
27// env.groupId = "${POM.groupId}"
28// env.art_version = "${POM.version}"
29// env.art_name = "${env.artifactId}-${env.art_version}.${env.packaging}"
30// nexusArtifactUploader artifacts: [[artifactId: "${env.artifactId}",
31// classifier: '',
32// file: "target/${env.art_name}",
33// type: "${env.packaging}"]],
34// credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
35// groupId: "${env.groupId}",
36// nexusUrl: '172.29.9.101:8081',
37// nexusVersion: 'nexus3',
38// protocol: 'http',
39// repository: 'maven-devops6-release',
40// version: "${env.art_version}"
41// }
42
43//函数方式
44def PushArtifactByPluginPOM(artifactId, file, type, groupId, repoName, version){
45 println(artifactId)
46 //demo
47 println("${file}, ${type}, ${groupId}, ${repoName}, ${version}")
48 //target/demo-0.0.1-SNAPSHOT.jar, jar, com.example, devops4-release, 0.0.1-SNAPSHOT
49 nexusArtifactUploader artifacts: [[artifactId: artifactId,
50 classifier: '',
51 file: file,
52 type: type]],
53 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
54 groupId: groupId,
55 nexusUrl: '172.29.9.101:8081',
56 nexusVersion: 'nexus3',
57 protocol: 'http',
58 repository: repoName,
59 version: version
60}
Jenkinsfile文件:
1@Library("devops06@main") _
2
3//import src/org/devops/Build.groovy
4def build = new org.devops.Build()
5def sonar = new org.devops.Sonar()
6def pushartifact = new org.devops.PushArtifact()
7
8currentBuild.displayName = "${env.branchName}-commitID"
9currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
10
11pipeline {
12 agent {label "build"}
13 options {
14 skipDefaultCheckout true
15 }
16
17
18 stages{
19 stage("CheckOut"){
20 steps{
21 script{
22 build.CheckOut()
23 }
24 }
25 }
26
27 stage("Build"){
28 steps{
29 script{
30 build.Build()
31 }
32 }
33
34 }
35
36 stage("CodeScan"){
37 when {
38 environment name: 'skipSonar', value: 'false'
39 }
40
41 steps{
42 script{
43
44 sonar.SonarScannerByPlugin()
45
46 }
47 }
48 }
49
50 stage("PushArtifact"){
51 steps{
52 script{
53 //PushArtifactByPlugin()
54 // PushArtifactByPluginPOM()
55 pomData = readMavenPom file: 'pom.xml'
56
57 buName = "${JOB_NAME}".split("-")[0]
58 repoName = "maven-${buName}-release"
59 file = "target/${pomData.artifactId}-${pomData.version}.${pomData.packaging}"
60 pushartifact.PushArtifactByPluginPOM(pomData.artifactId, file, pomData.packaging, pomData.groupId, repoName, pomData.version)
61 }
62 }
63
64 }
65
66 }
67}
测试完成。😘
扩展: 可以在Jenkins页面添加参数, 让用户输入后进行发布
| 💘 扩展: 可以在Jenkins页面添加参数, 让用户输入后进行发布(测试成功)-2023.6.28 |

测试过程如下:
- 改写代码:

1@Library("mylib@main") _ //加载共享库
2import org.devops.* // 导入库
3
4def checkout = new Checkout() //New实例化
5def build = new Build()
6def unittest = new UnitTest()
7def sonar = new Sonar()
8def gitcli = new GitLab()
9
10//env.buildType = "${JOB_NAME}".split("-")[1]
11
12//流水线
13pipeline {
14 agent { label "build" }
15
16 options {
17 skipDefaultCheckout true
18 }
19
20 stages{
21 stage("Checkout"){
22 steps{
23 script {
24 println("GetCode")
25 checkout.GetCode("${env.srcUrl}", "${env.branchName}")
26 }
27 }
28 }
29
30 stage("Build"){
31 steps{
32 script{
33 println("Build")
34 //build.CodeBuild("${env.buildType}")
35 sh "${env.buildShell}"
36
37 }
38 }
39 }
40
41 /*stage("UnitTest"){
42 steps{
43 script{
44 unittest.CodeTest("${env.buildType}")
45 }
46 }
47 }*/
48
49 stage("CodeScan"){
50 when {
51 environment name: 'skipSonar', value: 'false'
52 }
53 steps{
54 script{
55 profileName = "${JOB_NAME}".split("-")[0]
56 sonar.Init("${JOB_NAME}", "java", profileName)
57
58
59 //commit-status
60 commitID = gitcli.GetCommitID()
61 groupName =profileName
62 projectID = gitcli.GetProjectID("${JOB_NAME}", groupName)
63 sonar.CodeScan("${env.branchName}", commitID, projectID)
64 }
65
66 }
67 }
68
69 stage("PushArtifact"){
70 steps{
71 script{
72 // 读取pom文件获取坐标信息
73 // pomData = readMavenPom file: 'pom.xml'
74 // println(pomData)
75 // println(pomData.getClass())
76 buName = "${JOB_NAME}".split("-")[0]
77 repoName = "${buName}-snapshot"
78 file = "target/${env.artifactId}-${env.version}.${env.packaging}"
79 // 用户输入获取坐标信息
80 PushArtifactByNexusPlugin(env.artifactId, file, env.packaging ,env.groupId, repoName, env.version)
81 }
82 }
83
84
85 }
86
87 }
88}
89
90
91def PushArtifactByNexusPlugin(artifactId, file, type, groupId, repoName, version){
92 println(artifactId)
93 //demo
94 println("${file}, ${type}, ${groupId}, ${repoName}, ${version}")
95 //target/demo-0.0.1-SNAPSHOT.jar, jar, com.example, devops4-release, 0.0.1-SNAPSHOT
96 nexusArtifactUploader artifacts: [[artifactId: artifactId,
97 classifier: '',
98 file: file,
99 type: type]],
100 credentialsId: '2b44f51a-2374-4275-aeed-b720f4fbf937',
101 groupId: groupId,
102 nexusUrl: '172.29.9.101:8081',
103 nexusVersion: 'nexus3',
104 protocol: 'http',
105 repository: repoName,
106 version: version
107}
- 在流水线里添加字符参数和选项参数:


- 开始构建:

观察效果:

可以看到制品被成功上传到制品库了:

测试结束。😘
Jenkins插件获取包路径
发布其实就是下载制品,然后将制品发送到目标主机,最后通过脚本或者指令启动程序。
这个其实没多大意义。
| 💘 实践:Jenkins插件获取包路径-2023.6.29(测试成功) |
- 实验环境
1gitlab-ce:15.0.3-ce.0
2jenkins:2.346.3-2-lts-jdk11
3sonarqube:9.9.0-community
4nexus3:3.53.0
- 实验软件(无)
下面是下载制品的示例:
1curl http://192.168.1.200:8081/repository/devops-maven/com/example/demo/1.1.10/demo-1.1.10.jar -o app.jar -uadmin:admin123
或者:
- 安装插件
Maven Artifact ChoiceListProvider (Nexus)

- 创建一个流水线

创建选项参数,选择扩展选项参数,并配置:


- 点击构建,就出现效果了
用户选择制品后, 点击构建。此时可以想象,Jenkins下载这个包, 然后通过salt、ansible进行发布部署。

测试结束。😘
GitLabCI
| 💘 实践:GitLabCI的Nexus的CI/CD(测试成功)-2022.6.21 |
1.Nexus
1.pushartifact:
2 tags:
3 - "${RUNNER_TAG}"
4 stage: pushartifact
5 rules:
6 - if: '$RUN_TYPE == "CI"'
7 when: always
8 - when: never
9 script:
10 |-
11 if [[ ${PROJECT_TYPE} == "java" ]];then
12 pkgName=`ls target/ | grep -e "jar$"`
13 cd target/
14 newPkgName=${CI_PROJECT_NAME}-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}.jar
15 filePath=${CI_PROJECT_ROOT_NAMESPACE}/${CI_PROJECT_NAME}/${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}
16 #Dir /buName/serviceName/version/serviceName-version.xxx
17 mv ${pkgName} ${newPkgName}
18 curl -X POST "http://192.168.1.200:8081/service/rest/v1/components?repository=devops4-local" \
19 -H "accept: application/json" \
20 -H "Content-Type: multipart/form-data" \
21 -F "raw.directory=${filePath}" \
22 -F "raw.asset1=@${newPkgName};type=application/java-archive" \
23 -F "raw.asset1.filename=${newPkgName}" -u admin:admin123
24 else
25 echo "PROJECT_TYPE ERROR [java]"
26 fi
📍 本次测试过程


- 先跑一次流水线,看下效果:

报错了:

这里之前是配置过用户名和密码的了:



后面还要看下这个容器:……要重装下的!!!!

- 这里先把代码扫描给跳过:

再跑一次流水线:

- 现在开始写代码:
找一下gitlabci的预定义环境变量



此时,在RELEASE-1.1.1里加一些代码,并提交:



符合预期。
- 此时有个问题,那么jenkins里再跑一次CD,会下载哪个包呢?

可以看到拿的是最新那个包。
以上完整代码如下:
1.pipelineInit:
2 tags:
3 - "${RUNNER_TAG}"
4 stage: .pre
5 variables:
6 GIT_CHECKOUT: "true" ##局部开启作业的代码下载
7 script:
8 - ls -l
9
10.cibuild:
11 tags:
12 - "${RUNNER_TAG}"
13 stage: build
14 script:
15 - echo "${BUILD_SHELL}"
16 - ${BUILD_SHELL}
17 artifacts:
18 paths:
19 - ${ARTIFACT_PATH}
20
21.citest:
22 tags:
23 - "${RUNNER_TAG}"
24 stage: test
25 script:
26 - echo "${TEST_SHELL}"
27 - ${TEST_SHELL}
28 # artifacts:
29 # reports:
30 # junit: ${TEST_REPORTS}
31
32.codescan:
33 tags:
34 - "${RUNNER_TAG}"
35 stage: codescan
36 script:
37 |-
38 /usr/local/sonar-scanner/sonar-scanner-4.7.0.2747-linux/bin/sonar-scanner \
39 -Dsonar.login=${SONAR_USER} \
40 -Dsonar.password=${SONAR_PASSWD} \
41 -Dsonar.projectVersion=${CI_COMMIT_BRANCH}\
42 -Dsonar.branch.name=${CI_COMMIT_BRANCH} \
43 -Dsonar.gitlab.commit_sha=${CI_COMMIT_SHA} \
44 -Dsonar.gitlab.ref_name=${CI_COMMIT_BRANCH} \
45 -Dsonar.gitlab.project_id=${CI_PROJECT_ID} \
46 -Dsonar.dynamicAnalysis=reuseReports \
47 -Dsonar.gitlab.failure_notification_mode=commit-status \
48 -Dsonar.gitlab.url=http://172.29.9.101 \
49 -Dsonar.gitlab.user_token=${GITLAB_TOKEN} \
50 -Dsonar.gitlab.api_version=v4
51
52.pushartifact:
53 tags:
54 - "${RUNNER_TAG}"
55 stage: pushartifact
56 script:
57 |-
58 if [[ ${PROJECT_TYPE} == "java" ]];then
59 pkgName=`ls target/ | grep -e "jar$"`
60 cd target/
61
62 #Dir /buName/serviceName/version/serviceName-version.xxx
63 mv ${pkgName} ${CI_PROJECT_NAME}-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}.jar
64 curl -X POST "http://172.29.9.101:8081/service/rest/v1/components?repository=devops4-local" \
65 -H "accept: application/json" \
66 -H "Content-Type: multipart/form-data" \
67 -F "raw.directory=/${CI_PROJECT_ROOT_NAMESPACE}/${CI_PROJECT_NAME}/${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}"/ \
68 -F "raw.asset1=@${CI_PROJECT_NAME}-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}.jar;type=application/java-archive" \
69 -F "raw.asset1.filename=${CI_PROJECT_NAME}-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}.jar" -u admin:admin123
70 else
71 echo "PROJECT_TYPE ERROR [java]"
72 fi
1include:
2 - project: 'devops4/devops4-gitlablib-service'
3 ref: main
4 file:
5 - '/jobs/CI.yaml'
6
7workflow:
8 rules:
9 - if: $CI_PIPELINE_SOURCE == "web"
10 when: always
11 - if: $CI_COMMIT_BEFORE_SHA == "0000000000000000000000000000000000000000"
12 when: never
13 - when: always
14
15variables:
16 GIT_CHECKOUT: "false" ## 全局关闭作业代码下载
17 BUILD_SHELL: "sh -x build.sh" ## 构建命令
18 TEST_SHELL: "/usr/local/apache-maven-3.8.5/bin/mvn test " ## 测试命令
19 ARTIFACT_PATH: "target/*jar" ## 制品路径
20 # TEST_REPORTS: "target/surefire-reports/TEST-*.xml" ##测试报告
21 RUNNER_TAG: "builder"
22 PROJECT_TYPE: "java"
23
24stages:
25 - build
26 - test
27 - pushartifact
28 # - codescan
29
30pipelineInit:
31 extends:
32 - .pipelineInit
33
34cibuild:
35 extends:
36 - .cibuild
37
38citest:
39 extends:
40 - .citest
41
42# codescan:
43# extends:
44# - .codescan
45pushartifact:
46 extends:
47 - .pushartifact
48
- 这里在把之前的jenkins的CD代码优化下:

符合预期:

- gitlabCI完成了,如何完成CD呢?
这里改造下代码:
如何限制作业的运行?

配置代码:

运行测试:



符合预期。
- 现在开始写CD:
把这一部分拿过来:


配置如下:



运行测试:

此时发现,他把代码给下载下来了,但是我们不需要下载代码,这个该如何优化下呢?
我们可以借助这里来配置下:

但是这里已经全局关闭了代码下载的,为什么CD里还会再下一次代码呢:

我们这里再配置下,并观察效果:

经观察,这里还是会下载代码的:……

至此,GITLABCI的CI/CD实验结束。😘
2.GitLab Package【扩展】

1curl --header "PRIVATE-TOKEN: apF1R9s9JJBYJzLF5mYd" \
2 --upload-file sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar \
3 "http://192.168.1.200/api/v4/projects/33/packages/generic/devops03-maven-service/0.0.1/sonar-gitlab-plugin-4.1.0-SNAPSHOT.jar?status=default"
1.pushartforgitlab:
2 tags:
3 - build
4 stage: pushartifact
5 script:
6 |-
7 if [[ ${PROJECT_TYPE} == "java" ]];then
8 newPkgName=${CI_PROJECT_NAME}-${CI_COMMIT_SHA}.jar
9 pkgName=`ls target/ | grep -e "jar$"`
10 cd target/
11 mv ${pkgName} ${newPkgName}
12 curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
13 --upload-file ${newPkgName} \
14 "http://192.168.1.200/api/v4/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_SHA}/${newPkgName}?status=default"
15 else
16 echo "PROJECT_TYPE ERROR [java]"
17 fi
5、Nexus REST API
http://172.29.9.101:8081/#admin/system/api

NexusAPI调试方法
进入设置页面, 找到System > API , 即可进入API调试页面。

调试API /v1/components, 点击Try it out才能填写信息。

Maven格式仓库
- 填写信息



- 点击
Execute

此时,包就上传到nexus仓库了,然后可以拷贝代码,放到流水线里集成。

1curl -X 'POST' \
2 'http://172.29.9.101:8081/service/rest/v1/components?repository=maven-devops6-release' \
3 -H 'accept: application/json' \
4 -H 'Content-Type: multipart/form-data' \
5 -H 'NX-ANTI-CSRF-TOKEN: 0.6366498537413283' \
6 -H 'X-Nexus-UI: true' \
7 -F 'maven2.groupId=com.devops6' \
8 -F 'maven2.artifactId=demo-app' \
9 -F 'maven2.version=1.20.1' \
10 -F 'maven2.generate-pom=true' \
11 -F 'maven2.packaging=jar' \
12 -F 'maven2.asset1=@agent.jar' \
13 -F 'maven2.asset1.extension=jar'
Raw格式仓库
==上传jar包==
- 填写参数信息


- 点击
执行操作, 204表示成功。 我们可以复用这里的CURL指令, 最后封装到Jenkins流水线当中。

==上传图片==
- 填写参数:


- 点击
Excute上传:

1curl -X 'POST' \
2 'http://172.29.9.101:8081/service/rest/v1/components?repository=devops6' \
3 -H 'accept: application/json' \
4 -H 'Content-Type: multipart/form-data' \
5 -H 'NX-ANTI-CSRF-TOKEN: 0.6366498537413283' \
6 -H 'X-Nexus-UI: true' \
7 -F 'raw.directory=/devops/demo' \
8 -F 'raw.asset1=@xyyhg.png;type=image/png'
- 观察效果:

上传制品成功。
上传制品
- curl -u admin:admin123 如果Nexus开启了认证需要配置认证信息才能正常访问。(不同的包的类型不同)
1##PNG
2curl -X POST "http://192.168.1.200:8081/service/rest/v1/components?repository=myrepo" \
3-H "accept: application/json" \
4-H "Content-Type: multipart/form-data" \
5-F "raw.directory=/tmp" \
6-F "raw.asset1=@默认标题_自定义px_2020-10-01-0.png;type=image/png" \
7-F "raw.asset1.filename=默认标题_自定义px_2020-10-01-0.png"
8
9
10## tar.gz & ZIP
11curl -X POST "http://192.168.1.200:8081/service/rest/v1/components?repository=myrepo" \
12-H "accept: application/json" \
13-H "Content-Type: multipart/form-data" \
14-F "raw.directory=/tmp" \
15-F "raw.asset1=@nexus-3.30.0-01-unix.tar.gz;type=application/x-gzip" \
16-F "raw.asset1.filename=aaa.tar.gz"
17
18
19curl -X POST "http://192.168.1.200:8081/service/rest/v1/components?repository=myrepo" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "raw.directory=/tmp" -F "raw.asset1=@waypoint_0.1.5_linux_amd64.zip;type=application/x-gzip" -F "raw.asset1.filename=waypoint_0.1.5_linux_amd64.zip"
20
21
22## Jar file
23curl -X POST "http://192.168.1.200:8081/service/rest/v1/components?repository=myrepo" \
24-H "accept: application/json" \
25-H "Content-Type: multipart/form-data" \
26-F "raw.directory=/tmp" \
27-F "raw.asset1=@aopalliance-1.0.jar;type=application/java-archive" \
28-F "raw.asset1.filename=aopalliance-1.0.jar"
- 上传制品(maven类型的制品):
1 curl -X POST "http://192.168.1.200:8081/service/rest/v1/components?repository=devops-maven" \
2 -H "accept: application/json" \
3 -H "Content-Type: multipart/form-data" \
4 -F "maven2.groupId=com.newdevops" \
5 -F "maven2.artifactId=devopsapp" \
6 -F "maven2.version=1.1.5" \
7 -F "maven2.packaging=jar" \
8 -F "maven2.asset1=@demo-0.0.1-SNAPSHOT.jar;type=application/java-archive" \
9 -F "maven2.asset1.extension=demo-0.0.1-SNAPSHOT.jar" \
10 -u admin:admin123
下载制品
cURL:
1curl -u admin:admin123 http://192.168.1.200:8081/repository/anyops/com/anyops/a
2nyops-devops-service/1.1.1/anyops-devops-service-1.1.1.jar -o anyops-devops-service-1.1.1.jar
Wget:
1wget --http-user=admin --http-passwd=admin123 http://192.168.1.200:8081/repos
2itory/anyops/com/anyops/anyops-devops-service/1.1.1/anyops-devops-service-1.1.1.jar
6、CI综合实践
| 💘 实践:CI综合实践-2023.6.29(测试成功) |
- 实验环境
1gitlab-ce:15.0.3-ce.0
2jenkins:2.346.3-2-lts-jdk11
3sonarqube:9.9.0-community
4nexus3:3.53.0
- 实验软件
链接:https://pan.baidu.com/s/1lxP-jO5gHKsvoNaJi7PE6A?pwd=0820
提取码:0820
2023.6.29-实践:CI综合实践(测试成功)

==制品仓库规范==
在开始引入制品的时候,就应该制定制品库的管理和使用规范。 有了标准化的规范之后, 就很容易实现自动化。(为什么有些工作无法做成自动化? -无标准)
版本号: 1.2.3 主次修
1主版本号:表示项目的重大架构变更。 2次版本号:表示较大范围的功能增加和变化。 3修订版本号:表示重大Bug的修复。 4里程碑版本:表示某一个版本的里程碑。仓库名称: 每个项目组一个仓库 devops6

应用:
- 应用1: devops6-maven-service
- 应用2: devops6-gradle-service
包名: 应用名称-版本号-类型
- 应用1: devops6-maven-service-1.2.3.jar
- 应用2: devops6-gradle-service-1.2.3.jar
仓库目录结构: /应用名称/版本号/包名
- 应用1: /devops6-maven-service/1.2.3/devops6-maven-service-1.2.3.jar
- 应用2: /devops6-gradle-service/1.2.3/devops6-gradle-service-1.2.3.jar
创建nexus制品仓库
- 创建一个
raw类型的仓库存放制品


创建Jenkins作业
这里复用之前的项目。

项目仓库创建版本分支
- 基于main分支创建一个版本分支

- 然后在Jenkins上修改选项参数
branchName,添加RELEASE-1.1.1内容


编写Jenkins代码
1@Library("devops06@main") _
2
3//import src/org/devops/Build.groovy
4def build = new org.devops.Build()
5def sonar = new org.devops.Sonar()
6
7currentBuild.displayName = "${env.branchName}-commitID"
8currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
9
10env.branchName = "RELEASE-6.1.1"
11println(env.branchName)
12
13pipeline {
14 agent {label "build"}
15 options {
16 skipDefaultCheckout true
17 }
18
19
20 stages{
21 stage("CheckOut"){
22 steps{
23 script{
24 build.CheckOut()
25 }
26 }
27 }
28
29 stage("Build"){
30 steps{
31 script{
32 build.Build()
33 }
34 }
35
36 }
37
38 stage("CodeScan"){
39 when {
40 environment name: 'skipSonar', value: 'false'
41 }
42
43 steps{
44 script{
45
46 sonar.SonarScannerByPlugin()
47
48 }
49 }
50 }
51
52 stage("PushArtifact"){
53 steps{
54 script{
55 //PushArtifactByPlugin()
56 //PushArtifactByPluginPOM()
57
58 // init package info
59 appName = "${JOB_NAME}" //devops6-maven-service
60 repoName = appName.split('-')[0] //devops6
61 appVersion = "${env.branchName}".split("-")[-1] // RELEASE-1.1.1 1.1.1
62 targetDir="${JOB_NAME}/${appVersion}"
63
64
65 // 通过pom文件获取包名称
66 POM = readMavenPom file: 'pom.xml'
67 env.artifactId = "${POM.artifactId}"
68 env.packaging = "${POM.packaging}"
69 env.groupId = "${POM.groupId}"
70 env.art_version = "${POM.version}"
71 sourcePkgName = "${env.artifactId}-${env.art_version}.${env.packaging}"
72
73 pkgPath = "target"
74 targetPkgName = "${appName}-${appVersion}.${env.packaging}"
75 PushNexusArtifact(repoName, targetDir, pkgPath, sourcePkgName,targetPkgName)
76
77 }
78 }
79
80 }
81
82 }
83}
84
85//通过nexus api上传制品--综合实践
86def PushNexusArtifact(repoId, targetDir, pkgPath, sourcePkgName,targetPkgName){
87 //nexus api
88 withCredentials([usernamePassword(credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad', \
89 passwordVariable: 'PASSWD',
90 usernameVariable: 'USERNAME')]) {
91 sh """
92 curl -X 'POST' \
93 "http://172.29.9.101:8081/service/rest/v1/components?repository=${repoId}" \
94 -H 'accept: application/json' \
95 -H 'Content-Type: multipart/form-data' \
96 -F "raw.directory=${targetDir}" \
97 -F "raw.asset1=@${pkgPath}/${sourcePkgName};type=application/java-archive" \
98 -F "raw.asset1.filename=${targetPkgName}" \
99 -u ${USERNAME}:${PASSWD}
100 """
101 }
102}
103
104
105//通过jenkins的nexus插件上传制品
106def PushArtifactByPlugin(){
107 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
108 classifier: '',
109 file: 'target/demo-0.0.1-SNAPSHOT.jar',
110 type: 'jar']],
111 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
112 groupId: 'com.devops6',
113 nexusUrl: '172.29.9.101:8081',
114 nexusVersion: 'nexus3',
115 protocol: 'http',
116 repository: 'maven-devops6-release',
117 version: '1.1.1'
118}
119
120// 通过jenkins的nexus插件上传制品(读取pom文件)
121// def PushArtifactByPluginPOM(){
122// POM = readMavenPom file: 'pom.xml'
123// println(POM)
124// println("GroupID: ${POM.groupId}")
125// println("ArtifactID: ${POM.artifactId}")
126// println("Version: ${POM.version}")
127// println("Packaging: ${POM.packaging}")
128
129// env.artifactId = "${POM.artifactId}"
130// env.packaging = "${POM.packaging}"
131// env.groupId = "${POM.groupId}"
132// env.art_version = "${POM.version}"
133// env.art_name = "${env.artifactId}-${env.art_version}.${env.packaging}"
134// nexusArtifactUploader artifacts: [[artifactId: "${env.artifactId}",
135// classifier: '',
136// file: "target/${env.art_name}",
137// type: "${env.packaging}"]],
138// credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
139// groupId: "${env.groupId}",
140// nexusUrl: '172.29.9.101:8081',
141// nexusVersion: 'nexus3',
142// protocol: 'http',
143// repository: 'maven-devops6-release',
144// version: "${env.art_version}"
145// }
146
147// 通过jenkins的nexus插件上传制品(读取pom文件)-函数方式
148def PushArtifactByPluginPOM(artifactId, file, type, groupId, repoName, version){
149 println(artifactId)
150 //demo
151 println("${file}, ${type}, ${groupId}, ${repoName}, ${version}")
152 //target/demo-0.0.1-SNAPSHOT.jar, jar, com.example, devops4-release, 0.0.1-SNAPSHOT
153 nexusArtifactUploader artifacts: [[artifactId: artifactId,
154 classifier: '',
155 file: file,
156 type: type]],
157 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
158 groupId: groupId,
159 nexusUrl: '172.29.9.101:8081',
160 nexusVersion: 'nexus3',
161 protocol: 'http',
162 repository: repoName,
163 version: version
164}
- 运行,观察效果:


测试是ok的。
- 将代码集成到共享库

Jenkinsfile文件
1@Library("devops06@main") _
2
3//import src/org/devops/Build.groovy
4def build = new org.devops.Build()
5def sonar = new org.devops.Sonar()
6def artifact = new org.devops.Artifact()
7
8currentBuild.displayName = "${env.branchName}-commitID"
9currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
10
11env.branchName = "RELEASE-6.1.1"
12println(env.branchName)
13
14pipeline {
15 agent {label "build"}
16 options {
17 skipDefaultCheckout true
18 }
19
20
21 stages{
22 stage("CheckOut"){
23 steps{
24 script{
25 build.CheckOut()
26 }
27 }
28 }
29
30 stage("Build"){
31 steps{
32 script{
33 build.Build()
34 }
35 }
36
37 }
38
39 stage("CodeScan"){
40 when {
41 environment name: 'skipSonar', value: 'false'
42 }
43
44 steps{
45 script{
46
47 sonar.SonarScannerByPlugin()
48
49 }
50 }
51 }
52
53 stage("PushArtifact"){
54 steps{
55 script{
56 //PushArtifactByPlugin()
57 //PushArtifactByPluginPOM()
58
59 // init package info
60 appName = "${JOB_NAME}" //devops6-maven-service
61 repoName = appName.split('-')[0] //devops6
62 appVersion = "${env.branchName}".split("-")[-1] // RELEASE-1.1.1 1.1.1
63 targetDir="${JOB_NAME}/${appVersion}"
64
65
66 // 通过pom文件获取包名称
67 POM = readMavenPom file: 'pom.xml'
68 env.artifactId = "${POM.artifactId}"
69 env.packaging = "${POM.packaging}"
70 env.groupId = "${POM.groupId}"
71 env.art_version = "${POM.version}"
72 sourcePkgName = "${env.artifactId}-${env.art_version}.${env.packaging}"
73
74 pkgPath = "target"
75 targetPkgName = "${appName}-${appVersion}.${env.packaging}"
76 artifact.PushNexusArtifact(repoName, targetDir, pkgPath, sourcePkgName,targetPkgName)
77 }
78 }
79
80 }
81
82 }
83}
Artifact.groovy文件
1package org.devops
2
3
4//通过nexus api上传制品--综合实践
5def PushNexusArtifact(repoId, targetDir, pkgPath, sourcePkgName,targetPkgName){
6 //nexus api
7 withCredentials([usernamePassword(credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad', \
8 passwordVariable: 'PASSWD',
9 usernameVariable: 'USERNAME')]) {
10 sh """
11 curl -X 'POST' \
12 "http://172.29.9.101:8081/service/rest/v1/components?repository=${repoId}" \
13 -H 'accept: application/json' \
14 -H 'Content-Type: multipart/form-data' \
15 -F "raw.directory=${targetDir}" \
16 -F "raw.asset1=@${pkgPath}/${sourcePkgName};type=application/java-archive" \
17 -F "raw.asset1.filename=${targetPkgName}" \
18 -u ${USERNAME}:${PASSWD}
19 """
20 }
21}
22
23
24//通过jenkins的nexus插件上传制品
25def PushArtifactByPlugin(){
26 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
27 classifier: '',
28 file: 'target/demo-0.0.1-SNAPSHOT.jar',
29 type: 'jar']],
30 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
31 groupId: 'com.devops6',
32 nexusUrl: '172.29.9.101:8081',
33 nexusVersion: 'nexus3',
34 protocol: 'http',
35 repository: 'maven-devops6-release',
36 version: '1.1.1'
37}
38
39// 通过jenkins的nexus插件上传制品(读取pom文件)
40// def PushArtifactByPluginPOM(){
41// POM = readMavenPom file: 'pom.xml'
42// println(POM)
43// println("GroupID: ${POM.groupId}")
44// println("ArtifactID: ${POM.artifactId}")
45// println("Version: ${POM.version}")
46// println("Packaging: ${POM.packaging}")
47
48// env.artifactId = "${POM.artifactId}"
49// env.packaging = "${POM.packaging}"
50// env.groupId = "${POM.groupId}"
51// env.art_version = "${POM.version}"
52// env.art_name = "${env.artifactId}-${env.art_version}.${env.packaging}"
53// nexusArtifactUploader artifacts: [[artifactId: "${env.artifactId}",
54// classifier: '',
55// file: "target/${env.art_name}",
56// type: "${env.packaging}"]],
57// credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
58// groupId: "${env.groupId}",
59// nexusUrl: '172.29.9.101:8081',
60// nexusVersion: 'nexus3',
61// protocol: 'http',
62// repository: 'maven-devops6-release',
63// version: "${env.art_version}"
64// }
65
66// 通过jenkins的nexus插件上传制品(读取pom文件)-函数方式
67def PushArtifactByPluginPOM(artifactId, file, type, groupId, repoName, version){
68 println(artifactId)
69 //demo
70 println("${file}, ${type}, ${groupId}, ${repoName}, ${version}")
71 //target/demo-0.0.1-SNAPSHOT.jar, jar, com.example, devops4-release, 0.0.1-SNAPSHOT
72 nexusArtifactUploader artifacts: [[artifactId: artifactId,
73 classifier: '',
74 file: file,
75 type: type]],
76 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
77 groupId: groupId,
78 nexusUrl: '172.29.9.101:8081',
79 nexusVersion: 'nexus3',
80 protocol: 'http',
81 repository: repoName,
82 version: version
83}
- 运行,观察结果




符合预期。😘
如何自动识别项目的分支名选择进行构建
- Jenkins安装
Git Parameters插件

- 我们在
devops6-maven-service上基于main分支创建版本分支RELEASE-6.2.1

- 编辑Jenkins项目
devops6-maven-service,添加一个Git Parameter参数。



默认什么都不过滤的话,保存后,点击参数化构建,现象如下:

可以看到构建分支上回出现所有分支。
这里过滤下,只允许出现版本分支:


- 再次编辑共享库代码,重新修改下分支名
1//使用git 参数需要格式化
2env.branchName = "${env.branchName}" - "origin/"
3println(env.branchName)

- 再次运行流水线,观察效果


代码扫描:

CI上传制品:

测试结束。😘
完整共享库代码

Jenkinsfile文件
1@Library("devops06@main") _
2
3//import src/org/devops/Build.groovy
4def build = new org.devops.Build()
5def sonar = new org.devops.Sonar()
6def artifact = new org.devops.Artifact()
7
8
9//使用git 参数需要格式化
10env.branchName = "${env.branchName}" - "origin/"
11println(env.branchName)
12
13currentBuild.displayName = "${env.branchName}-commitID"
14currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
15
16pipeline {
17 agent {label "build"}
18 options {
19 skipDefaultCheckout true
20 }
21
22
23 stages{
24 stage("CheckOut"){
25 steps{
26 script{
27 build.CheckOut()
28 }
29 }
30 }
31
32 stage("Build"){
33 steps{
34 script{
35 build.Build()
36 }
37 }
38
39 }
40
41 stage("CodeScan"){
42 when {
43 environment name: 'skipSonar', value: 'false'
44 }
45
46 steps{
47 script{
48
49 sonar.SonarScannerByPlugin()
50
51 }
52 }
53 }
54
55 stage("PushArtifact"){
56 steps{
57 script{
58 //PushArtifactByPlugin()
59 //PushArtifactByPluginPOM()
60
61 // init package info
62 appName = "${JOB_NAME}" //devops6-maven-service
63 repoName = appName.split('-')[0] //devops6
64 appVersion = "${env.branchName}".split("-")[-1] // RELEASE-1.1.1 1.1.1
65 targetDir="${JOB_NAME}/${appVersion}"
66
67
68 // 通过pom文件获取包名称
69 POM = readMavenPom file: 'pom.xml'
70 env.artifactId = "${POM.artifactId}"
71 env.packaging = "${POM.packaging}"
72 env.groupId = "${POM.groupId}"
73 env.art_version = "${POM.version}"
74 sourcePkgName = "${env.artifactId}-${env.art_version}.${env.packaging}"
75
76 pkgPath = "target"
77 targetPkgName = "${appName}-${appVersion}.${env.packaging}"
78 artifact.PushNexusArtifact(repoName, targetDir, pkgPath, sourcePkgName,targetPkgName)
79 }
80 }
81
82 }
83
84 }
85}

Artifact.groovy文件
1package org.devops
2
3
4//通过nexus api上传制品--综合实践
5def PushNexusArtifact(repoId, targetDir, pkgPath, sourcePkgName,targetPkgName){
6 //nexus api
7 withCredentials([usernamePassword(credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad', \
8 passwordVariable: 'PASSWD',
9 usernameVariable: 'USERNAME')]) {
10 sh """
11 curl -X 'POST' \
12 "http://172.29.9.101:8081/service/rest/v1/components?repository=${repoId}" \
13 -H 'accept: application/json' \
14 -H 'Content-Type: multipart/form-data' \
15 -F "raw.directory=${targetDir}" \
16 -F "raw.asset1=@${pkgPath}/${sourcePkgName};type=application/java-archive" \
17 -F "raw.asset1.filename=${targetPkgName}" \
18 -u ${USERNAME}:${PASSWD}
19 """
20 }
21}
22
23
24//通过jenkins的nexus插件上传制品
25def PushArtifactByPlugin(){
26 nexusArtifactUploader artifacts: [[artifactId: 'demo-app',
27 classifier: '',
28 file: 'target/demo-0.0.1-SNAPSHOT.jar',
29 type: 'jar']],
30 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
31 groupId: 'com.devops6',
32 nexusUrl: '172.29.9.101:8081',
33 nexusVersion: 'nexus3',
34 protocol: 'http',
35 repository: 'maven-devops6-release',
36 version: '1.1.1'
37}
38
39// 通过jenkins的nexus插件上传制品(读取pom文件)
40// def PushArtifactByPluginPOM(){
41// POM = readMavenPom file: 'pom.xml'
42// println(POM)
43// println("GroupID: ${POM.groupId}")
44// println("ArtifactID: ${POM.artifactId}")
45// println("Version: ${POM.version}")
46// println("Packaging: ${POM.packaging}")
47
48// env.artifactId = "${POM.artifactId}"
49// env.packaging = "${POM.packaging}"
50// env.groupId = "${POM.groupId}"
51// env.art_version = "${POM.version}"
52// env.art_name = "${env.artifactId}-${env.art_version}.${env.packaging}"
53// nexusArtifactUploader artifacts: [[artifactId: "${env.artifactId}",
54// classifier: '',
55// file: "target/${env.art_name}",
56// type: "${env.packaging}"]],
57// credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
58// groupId: "${env.groupId}",
59// nexusUrl: '172.29.9.101:8081',
60// nexusVersion: 'nexus3',
61// protocol: 'http',
62// repository: 'maven-devops6-release',
63// version: "${env.art_version}"
64// }
65
66// 通过jenkins的nexus插件上传制品(读取pom文件)-函数方式
67def PushArtifactByPluginPOM(artifactId, file, type, groupId, repoName, version){
68 println(artifactId)
69 //demo
70 println("${file}, ${type}, ${groupId}, ${repoName}, ${version}")
71 //target/demo-0.0.1-SNAPSHOT.jar, jar, com.example, devops4-release, 0.0.1-SNAPSHOT
72 nexusArtifactUploader artifacts: [[artifactId: artifactId,
73 classifier: '',
74 file: file,
75 type: type]],
76 credentialsId: '3404937d-89e3-4699-88cf-c4bd299094ad',
77 groupId: groupId,
78 nexusUrl: '172.29.9.101:8081',
79 nexusVersion: 'nexus3',
80 protocol: 'http',
81 repository: repoName,
82 version: version
83}

疑问
==疑问:本来已经配置了禁止重新部署,但是好像没生效哎……==
有同名的制品的话,流水线可以跑成功,也不报错。但是制品是不会上传的。–可能是bug吧。。。


nexus仓库可以看到,这里的制品生成日期是没变的:

这里也是禁止重新部署的:

FAQ
Deployment Policy含义



这个问题就和docker镜像里的标签latest很像。
这里有个问题: 一般,RELEASE仓库里必须要变更版本号,不然是不允许上传的。 开启了这个Aloow redeploy,表示它可以覆盖之前的版本。 当你覆盖了,其他应用在引用的时候,可能会出现失败的情况,所以一般我们都把它disable掉。

常见制品库
==① Nexus==
开源的解决方案,nexus肯定是我们首选的,(nexus制品库还是非常稳定的)。
nexus也有企业版本。
软件交付物 == 制品
依赖包
依赖包也是可以通过nexus去管理。
yum也是可以由nexus来管理。
加速编译构建的一种方式:
凡是mirrors、镜像源相关的,我们都可以通过nexus代理仓库(proxy)来代理公网源来加速编译构建。
Maven私服仓库是企业里用的最多的一个了。
nexus本身是支持docker镜像和nexus的,只不过企业里我们一般会搭建harbor来管理docker镜像和helm包的。
nexus也支持和ldap做集成。
jenkins本身也支持收集制品的功能,但不建议这么做,因为jenkins已经够重了;
制品:晋级策略 制品库:解决重复编译,构建的问题;

==② JFROG==
在大厂里也用的比较多,商业版本里,这个JFORG也用的比较多。

关于我
我的博客主旨:
- 排版美观,语言精炼;
- 文档即手册,步骤明细,拒绝埋坑,提供源码;
- 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!
🍀 微信二维码 x2675263825 (舍得), qq:2675263825。

🍀 微信公众号 《云原生架构师实战》

🍀 csdn https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

🍀 博客 www.onlyyou520.com

🍀 知乎
https://www.zhihu.com/people/foryouone

🍀 语雀
https://www.yuque.com/books/share/34a34d43-b80d-47f7-972e-24a888a8fc5e?# 《不服来怼:宇宙中最好用的云笔记!》

最后
好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!


