Jenkins 流水线把 Maven 制品推到 Nexus 并支持选版本部署

把构建产物散落在各台服务器的 /data/app 目录下,时间一长就没人说得清线上跑的到底是哪次构建。做法不复杂:代码提交后由 Jenkins 打包,制品推给 Nexus 统一存,部署时从 Nexus 的制品列表里挑版本。这条链路配通之后,回滚就变成选一个旧版本号的事。

一、整体流程和 pom.xml

开发者用 SVN 或 Git 提交代码,每个发布版本都会更新 pom.xml 里的版本信息。Pipeline 读取这个 pom 拿到坐标,再用 Nexus 插件把 target 下的包传上去。上传完成后,Nexus 插件能在作业的 Web 界面上列出可下载的包地址,把这个地址交给 shell 脚本去 wget,部署动作就完成了。

pom 里真正被流水线用到的就四个字段:

  • groupId:业务名称简称
  • artifactId:应用名称
  • packaging:打包类型,pom / jar / war
  • version:版本信息
nexus-mvn01

二、要装的插件

  • Pipeline Utility Steps:提供 readMavenPom 之类的能力,在当前工作目录中查找文件。
  • Nexus Artifact Uploader:上传制品到制品库。
  • Maven Artifact ChoiceListProvider (Nexus):读取制品库中的文件列表,用来做参数化构建的下拉选项。
  • Nexus Platform:把 Nexus Repository Manager 和 Nexus Lifecycle 集成进 Jenkins 作业。

三、写 Pipeline

1. 先生成上传步骤的 DSL

不用手写,用 Jenkins 流水线语法生成器(Pipeline Syntax)配置一遍 nexusArtifactUploader,把生成的片段抄出来最省事。

nexus-mvn06
nexus-mvn03

上传要认证,先在凭据管理里加一个能连 Nexus 仓库的用户凭据。

image-289
image-290

加完之后记下这条凭据的唯一标识(ID),DSL 里的 credentialsId 就填它。

nexus-mvn05
nexus-mvn04

2. Pipeline 脚本

pipeline {
    agent  { 
        node { label 'master'} 
    }
#此处省略了多个步骤,直接上传制品的步骤
stages {
 stage ('上传制品') {
            steps {
                script {
                    def nexusDate = sh returnStdout: true, script: 'date +%Y%m%d-%H%M%S'
                    def pom = readMavenPom file: './项目目录/pom.xml' #指定读取的pom文件路径
                     nexusArtifactUploader(artifacts: [[artifactId: "${pom.artifactId}",
                                       classifier: '',
                                       file: "./项目目录/target/${pom.artifactId}-${pom.version}.${pom.packaging}",
                                       type: "${pom.packaging}"]],
                              credentialsId: 'Nexus凭据ID',
                              groupId: "${pom.groupId}",
                              nexusUrl: 'Nexus—IP:8090',
                              nexusVersion: 'nexus3',
                              protocol: 'http',
                              repository: "maven-releases(Nexus仓库名称)",
                              version: "${pom.version}-${nexusDate}-${BUILD_ID}")
                }
            }
        }
        stage('部署') {
            steps {
                script {
                    sh '''
                        ssh ${server_user}@${serverIP} "cd /data/app && wget ${Package}"	#${Package}引用Job参数化构建传的值,然后该值传给由远程目标服务器上的脚本进行引用下载
                    '''
                }
            }
        }
    }
}

几个细节值得说明。版本号这里拼成 ${pom.version}-${nexusDate}-${BUILD_ID},加上时间戳和构建号是为了让同一次 pom 版本的多次构建互不覆盖,否则同名制品会被冲掉,回滚时找不回东西。部署阶段不在 Jenkins 节点上拷文件,而是把下载地址通过 ssh 交给目标机自己 wget,大包传输不把 Jenkins 当流量中转。

Nexus 那边要允许匿名下载,否则目标机上 wget 会直接报 401 被拒绝。

image-56

四、建 Job 和参数化选择制品

先建一个普通的 Pipeline 任务,把上面的脚本贴进去。

image-293

要做「构建时选制品版本」,就勾选参数化构建,参数类型用 Maven Artifact ChoiceListProvider (Nexus),它会把制品库里的文件列成下拉框;凭据沿用前面添加的那条,直接选即可。

image-44
nexus-mvn02
image-295
image-49

之后每次发布就是触发这个 CD 任务、在下拉里选中要部署的版本号。

maven-jenkins

五、踩过的坑

  • nexusUrl 只写 host:port,不要带 http:// 前缀,协议由 protocol 字段单独指定。
  • 上传走 http 时,Nexus 前面挂过 https 反代的话要确认端口和跳转,不然插件报证书或连接错误。
  • 匿名访问只对 release 仓库开,快照仓库或内部仓库别图省事一起放开。
  • wget 下载没有校验步骤容易拿到半截包,脚本里加个存在性判断和大小检查再重启服务。
  • 制品列表越来越长之后,给 Nexus 配上清理策略,否则磁盘迟早被历史包占满。
© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容