Nexus 制品库集成
一、Nexus 是什么?
1.1 使用场景
私有仓库,主要使用场景有两个
- 私服仓库:企业内私有制品仓库服务
- 代理仓库:公网第三方仓库缓存代理
1.2 基本概念
1.2.1 Components 组件
简单理解的话,就是仓库中的每个包,常见的格式包括:jar
、war
、zip
、tar.gz
、exe
、sh
、apk
,如下示例:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
1.2.2 Assets 资产
简单来说即使一个项目的集合,如图所示:
1.2.3 Central Repository 中央仓库
中央仓库(Central Repository)是用于 Java 组件下载的内置存储库,由 Sonatype 管理,每天为数百万的 Maven 用户提供服务。Maven 工具在默认情况下,它就会从预定义的中央存储库检索组件
除了默认的中央存储库,还有其他组织维护其特有的存储库,例如 Redhat、Oracle、Apache 软件基金会,这些存储库通常拥有以下几个属性:
- 组件元数据:存储库中保存所有软件组件的元数据,如名称、版被号、依赖等
- 不可变:一旦组件(及元数据)发布到存储库,那么便具有不可更改特性(行政手段)
- 组件安全:存储库包含 哈希 和 PGP 加密签名,用于验证软件组件的真实性和完整性,并支持通过 HTTPS 安全加密协议下载访问
- 性能:存储库面向全球用户开发,性能自是不必多说(除了网络问题)
1.2.4 Components Coordinate 组件坐标
制品坐标为制品(组件)的唯一标识符,以 Maven 为例,Maven 以 groupId(组ID)
、artifactId(构件ID)
、version(版本号)
、packaging
,这组坐标通常称为 GAV 坐标
**GAV 坐标 **是 Maven 管理依赖关系的基础,我们再认真看下
- groupId:组标识符,通常使用 组标识符 将某一特定组织产生的构件逻辑分组,例如:Apache 软件基金会 发布的组件组标识为
org.apache.maven
- artifactId:组件标识符,用于标识组件
groupId
与artifactId
的组合应是唯一 - version:组件版本号,应遵循组织内版本标识规范
- packaging:描述组件格式,包括任何二进制软件格式的内容,例如:
zip
、rar
、war
、jar
构建工具通过将 GAV(P) 坐标 转换为与 Maven 存储库中对应的 URL,例如:
<repoURL>/org/apache/commons/commons-lang/1.2.0/commons-lang-1.2.0.jar</repoURL>
1.2.5 发布(release)/快照(snapshot)
Maven 存储库包含两种类型的组件,release
、snapshot
,前者代表稳定的静态发布组件、后者代表频繁更新的组件,下面我们仔细看下
- release:代表坚固、稳定、不会随着时间推移而变更的组件,例如:
commons-lang-1.2.0.jar
- snapshot:代表开发过程中的产生的组件,通常包含 版本号 + 时间戳,例如:
commons-lang-1.3.0-20090314.182342-1.jar
二、Nexus 部署
2.1 Docker 部署
启动容器
$ mkdir -p /prodata/nexus-data && chown -R 200 /prodata/nexus-data
$ docker run -d -p 9081:8081 --name nexus -v /prodata/nexus-data:/nexus-data sonatype/nexus3
查看日志
$ docker logs -f nexus
...
2021-12-01 11:30:37,466+0000 INFO [jetty-main-1] *SYSTEM org.eclipse.jetty.server.Server - Started @78725ms
2021-12-01 11:30:37,468+0000 INFO [jetty-main-1] *SYSTEM org.sonatype.nexus.bootstrap.jetty.JettyServer -
-------------------------------------------------
Started Sonatype Nexus OSS 3.37.0-01
-------------------------------------------------
登录平台,默认用户名 admin,密码保存在 /prodata/nexus-data/admin.password
中
访问 WebUI,初始化 Nexus 并重置密码
三、Nexus & Jenkins
3.1 创建 nexus 仓库
接下来,我们让 Jenkins 与 Nexus 联动起来,首先,我们创建一个仓库

3.2 配置 nexus 仓库
拷贝仓库地址
3.3 创建 nexus 用户
3.4 配置 Maven
配置认证
$ vim /usr/local/apache-maven-3.8.3/conf/settings.xml
# ...
<servers>
<server>
<id>maven-hostd</id>
<username>jenkins</username>
<password>jenk1n5</password>
</server>
</servers>
# ...
3.5 测试上传制品
执行命令
$ mvn deploy:deploy-file -Dmaven.test.skip=true \
-Dfile=target/my-app.jar \
-DgroupId=com.mycompany.app \
-DartifactId=my-app \
-Dversion=1.1-SNAPSHOT \
-Dpackaging=jar \
-DrepositoryId=maven-hostd \
-Durl=http://192.144.227.61:9081/repository/maven-hostd
执行效果
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-deploy-plugin:2.7:deploy-file (default-cli) @ my-app ---
Downloading from maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/1.1-SNAPSHOT/maven-metadata.xml
Uploading to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/1.1-SNAPSHOT/my-app-1.1-20211204.082307-1.jar
Uploaded to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/1.1-SNAPSHOT/my-app-1.1-20211204.082307-1.jar (1.9 kB at 4.2 kB/s)
Uploading to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/1.1-SNAPSHOT/my-app-1.1-20211204.082307-1.pom
Uploaded to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/1.1-SNAPSHOT/my-app-1.1-20211204.082307-1.pom (404 B at 1.6 kB/s)
Downloading from maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/maven-metadata.xml
Uploading to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/1.1-SNAPSHOT/maven-metadata.xml
Uploaded to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/1.1-SNAPSHOT/maven-metadata.xml (767 B at 4.7 kB/s)
Uploading to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/maven-metadata.xml
Uploaded to maven-hostd: http://192.144.227.61:9081/repository/maven-hostd/com/mycompany/app/my-app/maven-metadata.xml (281 B at 2.4 kB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.058 s
[INFO] Finished at: 2021-12-04T16:23:09+08:00
[INFO] ------------------------------------------------------------------------
浏览组件
查看组件(制品)详情信息
3.6 Jenkins 集成 Nexus
首先,安装 Nexus Artifact Uploader 插件,使用片段生成器生成 DSL
抽离上传逻辑至共享库:src/org/devops/nexus.groovy
package org.devops
def Upload(nexus_server, credentials_id, repository_id, pom_groupid, pom_artifact, pom_version, pom_packaging){
def artifact_file = "target/${pom_artifact}.${pom_packaging}"
result = nexusArtifactUploader artifacts: [[artifactId: "${pom_artifact}",
classifier: "",
file: "${artifact_file}",
type: "${pom_packaging}"]],
credentialsId: "${credentials_id}",
groupId: "${pom_groupid}",
nexusUrl: "${nexus_server}",
nexusVersion: "nexus3",
protocol: "http",
repository: "${repository_id}",
version: "${pom_version}"
return result
}
Jenkinsfile 流水线定义
@Library('shareLibraryDemo') _
def util_tools = new org.devops.utils()
def toemail = new org.devops.toemail()
def sonar = new org.devops.sonarqube()
def sonarapi = new org.devops.sonarapi()
def nexus = new org.devops.nexus()
String branch_name = "${branch}".split('/')[-1]
String sonarqube_server = "http://192.144.227.61:9000"
String nexus_repo_url = "http://192.144.227.61:9081/repository/maven-hostd"
currentBuild.description = "Trigger by ${committer_name} ${branch_name}"
pipeline {
agent {
node {
label "bj-tencent-lhins-1"
}
}
tools {
jdk 'Openjdk 11.0.13'
maven 'M2'
}
options {
timestamps()
}
stages {
stage('拉取代码') {
steps {
// branches 只拉取特定仓库的分支
// branches: [[name: '*/master'],]:
// 当远程仓库 master 分支提交时,触发 pipeline 拉取 master 分支
// 当远程仓库 develop 分支提交时,仍然触发 pipeline 拉取 master 分支
checkout([$class: 'GitSCM', branches: [
[name: "${branch}"],
], extensions : [], userRemoteConfigs: [
[credentialsId: 'gitee', url: "${env.GIT_URL}"]
]])
}
}
stage("打包应用") {
steps {
script {
util_tools.PrintColorMsg("编译/打包最新代码.", "blue")
sh "mvn package"
util_tools.PrintColorMsg("编译/打包完成.", "green")
}
}
}
stage("上传制品") {
steps {
script {
util_tools.PrintColorMsg("上传构建制品.", "blue")
def jar_name = sh returnStdout: true, script: "cd target;ls *.jar"
jar_name = jar_name - "\n"
def pom = readMavenPom file: 'pom.xml'
pom_groupid = "${pom.groupId}"
pom_artifact = "${pom.artifactId}"
pom_version = "${pom.version}"
pom_packaging = "${pom.packaging}"
println("GAV 坐标:${pom_groupid}-${pom_artifact}-${pom_version}-${pom_packaging}")
nexus_server = "${nexus_repo_url}".split('/')[2]
repository_id = "${nexus_repo_url}".split('/')[-1]
result = nexus.Upload(nexus_server, 'nexus-jenkins-user', repository_id, pom_groupid, pom_artifact, pom_version, pom_packaging)
println("上传结果: ${result}")
util_tools.PrintColorMsg("上传制品完成.", "green")
}
}
}
stage("代码扫描") {
steps {
script {
util_tools.PrintColorMsg("代码扫描,跳过...~", "green")
}
}
}
}
post {
success {
script {
util_tools.PrintColorMsg("构建成功~", "green")
toemail.Email("流水线构建成功了!", committer_email, branch_name)
}
}
failure {
script {
util_tools.PrintColorMsg("构建失败!", "red")
toemail.Email("流水线执行失败了!", committer_email, branch_name)
}
}
aborted {
script {
util_tools.PrintColorMsg("构建取消!", "red")
toemail.Email("流水线被取消了!", committer_email, branch_name)
}
}
always {
script {
util_tools.PrintColorMsg("清理临时产物", "green")
sh "mvn clean"
}
}
}
}
构建日志
Blueocean UI
查看制品
3.7 制品晋级
软件制品是软件企业持续交付的目标产物,其质量是制品交付的重要属性。只有依次通过了代码检查、单元测试、测试(自动化、手工)等多重质量门禁,制品方可由开发库逐步晋级至测试库、待投产库,最终晋级至投产库部署生产
“一次构建,多次部署” 这是单一制品原则,也是“制品晋级”的核心理念,一般是会通过多个制品库(repo)、打标签、增加属性进行标识,但是在流程上需要明确什么时间点,什么动作来触发晋级,制品晋级后供以下一级环境的部署使用
我们梳理下具体流程:
- 持续集成流水线:打包构建制品
- 持续部署流水线:部署测试制品
- 制品晋级流水线:制品晋级(打标、移仓)