一.简介

制品是软件开发过程中产生的多种有形副产品之一。广义的制品还包括用例、UML图、设计文档等。而狭义的制品就可以简单地理解为二进制包。虽然有些代码是不需要编译就可以执行的,但是我们还是习惯于将这些可执行文件的集合称为二进制包。本章讨论的是狭义的制品。行业内有时也将制品称为产出物或工件。

最简单的制品管理仓库就是将制品统—放在一个系统目录结构下。但是很少有人这样做,更多的做法是使用现成的制品库。

制品管理涉及两件事情:一是如何将制品放到制品库中;二是如何从制品库中取出制品。由于每种制品的使用方式不一样,因此下面我们分别进行介绍。

二.Jenkins管理制品

从手工打包到自动化打包,再将打好的包放到制品库中。这看似简单,但是要在团队中从无到有地落地其实是一个很漫长的过程,特别是对于存在很多遗留项目的团队。每个团队都应该按照自己当前情况进行调整,有时统一的解决方案不一定适合你。

曾经,笔者所在团队已经将部分项目的编译和单元测试放到Jenkins上执行,然而并没有人力及能力搭建Nexus。但是又期望能将自动打包好的JAR包放到各个环境中使用,以马上从持续集成中获益,怎么办?

这时,archiveArtifacts步骤就派上用场了。它能对制品进行归档,然后你就可以从Jenkins页面上下载制品了。

完成的pipeline如下:

pipeline {
agent any tools {
maven 'mvn-3.5.4'
}
stages {
stage('Build') {
steps {
sh "mvn clean spring-boot: repackage"
}
}
}
post {
always{
archiveArtifacts artifacts: 'target/**/*.jar', fingerprint: true
}
}
}

常用参数:

  • artifacts(必填):字符串类型,需要归档的文件路径,使用Ant风格路径表达式
  • fingerpring(可选):布尔类型,是否对归档的文件进行签名
  • excludes(可选):字符串类型,需要排出的文件路径,使用Ant风格路径表达式
  • caseSensitive(可选):布尔类型,对路径大小写是否敏感
  • onlylfSuccessful(可选):布尔类型,只在构建成功时进行归档
  • 这个步骤并不只用于归档jar包,事实上,它能归档所有类型的制品

三.Nexus

maven上传

nexus搭建好后,就可以使用deploy上传jar或者war包到nexus中。Deploy插件是Apache Maven团队提供的官方插件,能将JAR包及POM文件发布到Nexus中。目前该插件的最新版本是2.8.2,如果不需要自定义Deploy插件配置,则不需要在POM文件中定义。

<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>

使用Deploy插件发布需要以下几个步骤

1.配置发布地址,在Maven项目的POM文件中加入∶

<distributionManagement>
<snapshotRepository>
<id>nexus-snapshot</id>
<name>my nexus snapshot</name>
<url>http://<你的Nexus地址>/repository/maven-snapshots</url>
</snapshotRepository>
<repository>
<id>nexus-release</id>
<name>my nexus release</name>
<url>http://<你的Nexus地址>/repository/maven-releases</url>
</repository>
</distributionManagement>

完成此步骤后,我们就可以通过执行mvn clean deploy进行发布了。Deploy插件会根据Maven项目中定义的version值决定是使用nexus-snapshot仓库还是nexus-release仓库。当version值是以-SNAPSHOT后缀结尾时,则发布到nexus-snapshot仓库

2.配置访问Nexus的用户名和密码才能发布制品,需要在Maven的settings.xml中加入:

<servers>
<server>
<id>nexus-snapshot</id>
<username>admin</username>
<password>admin123</password>
</server>
<server>
<id>nexus-release</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>

jenkins上传

除了可以通过Maven发布JAR包,还可以使用Nexus Platform来插件实现。最新版本的Nexus Platform ( 3.3.20180801-112343.4970c8a )已经同时支持Nexus 2.x和Nexus 3.x,只是它的文档更新不及时,大家都不知道它支持3.x版本了。

在安装好Nexus Platform插件后,根据以下步骤来使用。

1.进入Manage Jenkins→Configure System→Sonatype Nexus页,设置Nexus 3.x的服务器地址

需要注意的是:

  • 在“Credentials”选项处,增加了一个具有发布制品到Nexus中的权限的用户名和密码凭证
  • Server ID字段的值,在Jenkinsfile中会引用

设置完成后,单击“Test connection”按钮测试设置是否正确。

2.在Jenkinsfile中加入nexusPublisher步骤

stage('Build') {
steps {
sh "mvn clean test package"
nexusPublisher(
nexusInstanceId: 'nexus3',
nexusRepositoryId: 'maven-releases',
packages: [
[
$class: "MavenPackage',
mavenAssetList: [
[classifier: '',
extension: '',
filePath: './target/server-1.0-SNAPSHOT.jar'
]
],//end of mavenAssetList
mavenCoordinate: [
artifactId: 'server',
groupId: 'codes.showme',
packaging: 'jar', version: '1.0'
]
] //end of packages])
])
}
}

下面简单介绍一下nexusPublisher的参数。

  • nexusInstanceld :在Jenkins中配置Nexus 3.x时的Server lD
  • nexusRepositoryld :发布到Nexus服务器的哪个仓库
  • mavenCoordinate : Maven包的坐标,packaging值与Maven中的packaging值一致,可以是jar、war、pom、hpi等。
  • mavenAssetList:要发布的文件,如果是pom.xml,则extension必须填“xml”

在实际工作中,笔者并不常使用此插件。原因如下:

1.每个Maven项目都可能不同,必须为每个Maven项目写nexusPublisher方法

2.对于多模块的Maven项目,nexusPublisher的参数写起来十分啰唆

但是介绍这个插件还是有必要的,一是大家可以根据实际情况进行选择;二是可以了解Jenk-ins与Nexus的集成程度。

管理Docker镜像

在Jenkins机器安装Docker,在Nexus的仓库列表页Administration->repository->repositories

单机“docker(hosted)”,进入Docker私有仓库创建页

在创建过程中,需要指定Docker私有仓库提供HTTP服务的端口为8595,私有仓库地址为:http://<ip>:8595

创建Docker私有仓库凭证,将镜像推送到Docker私有仓库是需要用户名和密码的。我们不能将密码明文写在Jenkinsfile中,所以需要创建一个“Username withpassword”凭证。

当私有仓库创建好后,我们就可以构建Docker镜像并发布到仓库中了。

假设Dockerfile 与Jenkinsfile在同一个目录下,我们看一下Jenkinsfile的内容。

pipeline {
agent any
environment {
registry = "http://192.168.0.101:8595"
registryCredential = 'dockernexus'
}
stages {
stage('Build') {
steps {
withDockerRegistry([
credentialsId: "${registryCredential}",
url: "${registry}"]) { sh "docker build . -t ${registry} /hello:v2"
sh "docker push ${registry}/hello:v2"
}
}
}
}
}

withDockerRegistry步骤做的事情实际上就是先执行命令∶

docker login-u admin-p*******http://192.168.0.101:8595

其间,所生成的config.json文件会存储在工作空间中。然后再执行闭包内的命令。将镜像推送到Nexus中后,在Nexus中可以看到信息

由于是私有的非安全(HTTP)的仓库,所以需要配置Docker的daemon.json

{
"insecure-registries":["<私有仓库的地址>"],
"registry-mirrors":["https://registry.docker-cn.com"]
}

同时,为加速基础镜像的下载,设置了国内Docker镜像

管理raw

进入Administration→Repository→Repositories页,单击“raw ( hosted )”,进入raw仓库创建页,输入仓库名称“raw-example”,单击“Create repository”按钮,确认后创建成功。

该仓库的地址是:<你的Nexus地址>/repository/raw-examplel

使用HTTP客户端就可以将制品上传到raw仓库中,使用curl命令

1.在Jenkins上添加“Username with password”凭证

2.在Jenkinsfile中加入上传制品的步骤

pipeline {
agent any
environment {
nexusRawUsernamePassword = credentials('nexusRaw')
}
stages {
stage('Build') {
steps {
sh "curl --user '${nexusRawUsernamePassword}' --upload-file ./readme.md http://10.33.193.82:8081/repository/raw-example/${BUILD_NUMBER}/readme.md"
}
}
}
}

为简单起见,我们直接使用构建号作为目录名称来区分每次上传的制品。curl命令的格式为:

curl --user '<username:password>' --upload-file <待上传制品的路径〉〈将制品保存到Nexus上的全路径>

将制品保存到Nexus上的全路径∶如果目录不存在,Nexus将会自动创建。

3.在Nexus中,我们看到readme.md文件已经上传成功

在Jenkins pipeline中获取原始制品时,我们同样使用curl命令。

sh "curl --user '${nexusRawUsernamePassword}' -o readme.md http://10.33.193.82:8081/repository/raw-example/2/readme.md"

四.拷贝制品

在某些场景下,我们需要从另一个pipeline中拷贝制品,Copy Artifact插件 可以帮助我们实现

steps {
copyArtifacts(
projectName: "core",
selector: lastSuccessful(true)
)
}

从core项目中拿到最后一次构建成功的制品

参数:

  • projectname :字符串类型,Jenkins job或pipeline名称
  • selector : BuildSelector类型,从另一个pipeline中拷贝制品的选择器,默认拷贝最后一个制品
  • parameters :字符串类型,使用逗号分隔的键值对字符串( name1=value1 , name2=value2 ),用于过滤从哪些构建中拷贝制品
  • filter:字符串类型,Ant风格路径表达式,用于过滤需要拷贝的文件
  • excludes:字符串类型,Ant风格路径表达式,用于排除不需要拷贝的文件
  • target:字符串类型,拷贝制品的目标路径,默认为当前pipeline的工作目录
  • optional:布尔类型,如果为true,则拷贝失败,但不影响本次构建结果
  • fingerprintArtifacts:布尔类型,是否对制品进行签名,默认值为true
  • resultVariableSuffix :上例中,无法得知我们到底拿的是core项目的哪次构建的制品。Copy Artifact插件的设计是将其构建次数放到一个环境变量中。这个环境变量名就是在COPYARTIFACT BUILDNUMBER后拼上resultVariableSuffix,比如resultVariableSuf fix值为corejob,那么就在pipeline 中通过变量COPYARTIFACT BUILDNUMBER corejob拿到源pipeline的构建次数了。

除projectname参数是必填的外,其他参数都是可选的。

常用的获取选择器的方法

  • lastSuccessful:最后―次构建成功的制品。方法签名为lastSuccessful ( boolean stable )。stable为true表示只取构建成功的制品,为false表示只要构建结果比UNSTABLE好就行。
  • specific:指定某一次构建的制品。方法签名为specific(StringbuildNumber)。buildNum ber表示指定取第n次构建的制品
  • lastCompleted:最后一次完成构建的制品,不论构建的最终状态如何。方法签名为lastCompleted()
  • latestSavedBuild:最后一次被标记为keep forever的构建的制品。方法签名为latestSavedBuild()

五.版本号

谈到制品,就必须谈到版本号的管理。版本号的制定并没有所谓的行业标准。比如谷歌浏览器当前版本号为70.0.3538.110 ; Ubuntu操作系统当前版本号为18.10;由美国计算机教授高德纳(DonaldErvin Knuth )编写的功能强大的排版软件TEX系统的版本号不断趋近于T,类似于这样:3.1415926。

GitHub提出了一种具有指导意义、统一的版本号表示规则,称为Semantic Versioning (语义化版本表示)。这也被人们称为三段式版本号。有了这套规则,用户一看版本号,就大概能猜到一个软件两个版本之间的可能变化。

语义化版本格式为:主版本号.次版本号.修订号。版本号递增规则如下:

  • 主版本号:当作了不兼容的API修改时。
  • 次版本号:当作了向下兼容的功能性新增时。·修订号:当作了向下兼容的问题修正时。
  • 修订号:当作了向下兼容的问题修正时

先行版本号及版本编译元数据可以加到“主版本号.次版本号.修订号”的后面,作为延伸。以下是常用的修饰词。

  • alpha :内部版本
  • beta :测试版本
  • rc:即将作为正式版本发布
  • lts :长期维护

语义化版本号的好处是除了方便人类识别,也方便软件识别。比如Ansible提供的版本比较器的使用:{{ansible distribution version isversion ( '12.04','>=')}。这也是很多开源软件使用语义化版本号的原因。

但是,语义化版本号真的适用于所有的场景吗?不一定。我们需要根据版本号的作用来确定软件版本号的格式。说白了,你希望别人一眼从版本号里看出什么,你就怎么确定版本号。

那么,谁看这个版本号?软件的真正使用者根本不关心软件版本号。不过,现实中各种App强制大版本,对于市场营销的确有好处。企业软件的销售人员是要看版本号的。他必须知道不同版本之间的功能区别,以更好地完成其工作。

移动端App的产品经理是要看版本号的。他必须知道当前最新版本与上一个版本的区别,以及市面上都运行了哪些版本。当用户提交Bug时,产品经理可以根据用户所装的版本进行决策。

程序员是要看版本号的。版本号意味着软件运行时的源码版本。有了这个对应关系,对于查Bug、了解线上业务逻辑的运行都是非常有用的。

对于版本号的不同诉求,决定了它的作用。笔者总结,可以从以

下两个角度来设计版本号。

1.方便表达。对于更接近使用者的软件,更倾向于这个角度,比如三段式版本号。所以,推荐前端应用使用三段式版本号。

2.方便找出制品与源码的关系。对于更接近软件源码的人,更倾向于这个角度,比如Go CD的版本号:18.10.0( 7703-42d1cbe661161b5400289ead86c0447c84af8cOa )。除了三段式版本号,还会有构建次数及相应的代码提交ID。推荐后端服务使用Go CD的这种版本号格式。

现实中,如何设计版本号才能做到既方便表达,又方便找出制品与源码的关系呢?采用内外部版本号策略就可以了。对外部,可以使用1.0.1这样的版本号;对内部,可以使用1.0.1.20180911.12.42d1cbe66116这样的版本号。最后要做的事情就是,想办法将内外部版本对应上就可以了。

Version Number

Version Number ( https"//plugins.jenkins.io/versionnumber )是一款用于生成版本号的插件,它提供了VersionNumber步骤。

具体使用方法如下:

script {
def version = VersionNumber versionPrefix: "${JOB_NANE}-", versionNumberString: 'v1.1.1.${BUILDS_ALL_TIME}'
echo "${version}"
}

注意:BUILDS ALL TIME只是占位符,并不是Jenkins或VersionNumber插件提供的环境变量。

VersionNumber步骤支持以下参数。

  • versionNumberString :字符串类型,版本号格式,用于生成版本号。只能使用单引号,以防格式中的占位符被转义。版本号格式支持多种占位符。
  • versionPrefix:字符串类型,版本号的前缀
  • projectStartDate :字符串类型,项目开始时间,格式为yyyy-MM-dd,用于计算项目开始后的月数和年数

    -worstResultForlncrement :字符串类型,如果本次构建状态比上一次构建状态更糟糕,则BUILDS_TODAY、BUILDS_THIS_WEEK、BUILDS_THIS_MONTH、BUILDS_THIS_YEAR占位符的值不会增加。worstResultForlncrement可以设置的值有sUCCESs.UNSTABLE、FAILURE、ABORTED、NOT_BUILT(默认)。此参数较少使用

versionNumberString参数使用占位符生成版本号。部分占位符本身支持参数化。接下来分别介绍它们

  • BUILD DATEFORMATTED∶格式化的构建日期,支持参数化,如${BUILD DATE FORMATTED , "yyyy-MM-dd"}
  • BUILD DAY:构建日期,支持×和XX参数。比如是12月2日,${BUILD DAY}将返回2,${BUILD DAY,X}将返回2,${BUILDDAY,XX}将返回03
  • BUILD WEEK:今年构建的星期数,支持X和XX参数
  • BUILD MONTH:今年构建的月数,支持X和XX参数
  • BUILD YEAR:今年构建的年份

比如构建的时间为2018-12-02,那么BUILD_DAY的值为2,BUILD_WEEK的值为49,BUILD_MONTH的值为12,BUILD_YEAR的值为2018。

接下来是一组和构建数相关的占位符:BUILDS TODAY、BUILDS THIS WEEK、 BUILDS THIS MONTH、BUILDS THISYEAR,它们分别表示当天、本星期、本月、本年完成的构建数。BUILDS ALL TIME表示自从项目开始后完成的总构建数。

MONTHS SINCE PROJECT START和YEARS SINCE PROJECT START分别表示自项目开始日期起已过去的日历月数和年数。

Jenkins制品管理的更多相关文章

  1. Jenkins的制品管理

    Jenkins的制品管理 制品是什么? 也叫产出物或工件.制品是软件开发过程中产生的多种有形副产品之一.广义的制品包括用例.UML图.设计文档等.而狭义的制品就可以简单地理解为二进制包.虽然有些代码是 ...

  2. [转]Jenkins使用 管理节点

    现在我们已经搭建好了基本的Jenkins环境,在这一集里,我们说一说如何管理节点. 进入“系统管理”中的“管理节点”. 创建Windos系统的奴隶节点 先创建一台安装了Win7系统的虚拟机,作为Jen ...

  3. Jenkins用户组管理

    Jenkins用户组管理 转载2015-06-10 21:44:24 标签:jenkinsrolestrategypluginusergroupcitools 一.安装插件 安装RoleStrateg ...

  4. 【Devops】【docker】【CI/CD】Jenkins源代码管理 添加gitlab项目地址,报错Failed to connect to repository : Error performing command: ls-remote -h git@192.168.92.130:8090/root/swapping.git HEAD

    Jenkins源代码管理 添加gitlab项目地址 报错如下: Failed to connect to repository : Error performing command: ls-remot ...

  5. jenkins中管理用户

    jenkins中管理用户: 管理用户权限

  6. Jenkins源代码管理(SVN)

    Subversion 安装插件 1.首先将本地的自动化用例打包上传svn 2.配置jenkins源代码管理(每次执行jenkins时,会自动check-out配置地址中的代码到Jenkins的工作空间 ...

  7. jenkins插件管理提示“update information obtained:不可用ago”

    jenkins插件管理遇到两个错误 (1)插件管理页面提示:There were errors checking the update sites:IOException:Unable to tunn ...

  8. Jenkins 源代码管理(SVN)

    Subversion 安装插件 1.首先将本地的自动化用例打包上传 svn 2.配置 jenkins 源代码管理(每次执行 jenkins 时,会自动 check-ou t配置地址中的代码到 Jenk ...

  9. Jenkins凭证管理

    目录 一.简介 二.管理凭证 三.常用凭证 保密文本 账号密码 保密文件 账号秘钥 四.优雅使用凭证 保密文本 账号密码 保密文件 五.凭证插件 集成HashiCorp Vault pipeline ...

随机推荐

  1. Debug代码调试

    Debug代码调试 第一步在代码左侧先点一个红点 第二步右键选择Debug运行 第三步点击Step Into按键分步进行 练习题: s2 = 'python python python python ...

  2. 微软商店打不开的教程(错误代码0x80131500)

    1 打开win+R 输入`inetcpl.cpl` 2 点击高级 3  勾选上`使用TLS 1.2`或者点击还原默认设置就可以啦 4 然后就可以打开啦

  3. 【数据结构】【图文】【oj习题】 图的拓扑排序(邻接表)

    拓扑排序: 按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系,由此所得顶点的线性序列称之为拓扑有序序列.显然对于有回路的有向图得不 ...

  4. 【Microsoft Azure 的1024种玩法】二.基于Azure云平台的安全攻防靶场系统构建

    简介 本篇文章将基于在Microsoft Azure云平台上使用Pikachu去构建安全攻防靶场,Pikachu使用世界上最好的语言PHP进行开发,数据库使用的是mysql,因此运行Pikachu需要 ...

  5. [loj2504]小H爱染色

    以下考虑直接对所有$F(A)$求和,并给出两种做法-- 做法1: 枚举答案$A$,对应方案数为${n-A\choose m}^{2}-{n-A-1\choose m}^{2}$,即答案为$\sum_{ ...

  6. [atARC103D]Robot Arms

    合法的必要条件是每个点两维坐标和奇偶性相同,同时这也是充分条件 令$d_{i}=\{2^{0},2^{1},...,2^{m-1}\}$,归纳其可以走到任意满足$|x|+|y|<2^{m}$的$ ...

  7. android测试之monkey测试

    1.首先安装SDK包 2.配置环境变量 3.打开CMD命令窗口,查看是否安装成功 命令:adb version 4.要做monkey测试的安卓包名,获取方式如下(必须启动要获取报名的app) 1.ad ...

  8. Java设计模式之(十一)——享元模式

    1.什么是享元模式? Use sharing to support large numbers of fine-grained objects efficiently. 享元模式(Flyweight ...

  9. 快来使用Portainer让测试环境搭建飞起来吧

    Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台操作.Swarm集群和服 ...

  10. Codeforces 356E - Xenia and String Problem(哈希)

    Codeforces 题面传送门 & 洛谷题面传送门 首先显然一个 gray 串的长度只可能是 \(2^k-1\),其中 \(k\in\mathbb{Z}\). 考虑将一个字符改成另外一个字符 ...