这几天尝试用Jenkins/Hudson创建pipeline,发现网上的信息很少,所以写一篇跟大家分享。
在开始之前,得告诉你被我的标题给忽悠了,不是Jenkins/Hudson,只是Jenkins!如果你还在用Hudson,那么我建议你立即切换到Jenkins。理由就不说了,看看这个投票就行。(此中,我吃尽了苦头)
接下来,就让我们一步一步用Jenkins搭建真正的pipeline吧。
第一步
第一步,我们先创建一个最简单的pipeline。所谓pipeline,顾名思义,就是一个流水线,由多个步骤(steps)组成。每走完一步,就来到下一步。用Build Pipeline Plugin就可以很方便地实现。
实现的效果如下图:
上例中,UnitTest是我们的初始任务。UnitTest结束之后,自动触发AC Test。如果通过了AC Test,团队可以有选择地部署到任意测试环境。
在配置这个插件时,最重要的就是选择Initial Job。
然后,在每一个step(job)中选择downstream step。可以是自动触发(Build Other Projects),也可以选择手动触发(Manually Execute Downstream Project)。
第二步
第一步中我们实现了一个流水线,但这个只是看上去的流水线而已。在工厂的流水线中,历经流水线上游到下游的,应该是同一个产品。但上例中显然不是,Unit Test和Acceptance Test所运行的可能是不同版本的代码。
要让几个step的代码运行在同一个版本,可以使用一个叫做Parameterized Trigger Plugin。如下图:
选择把Subversion revision传到下面的steps,则接下来的Steps都会checkout同一个版本的代码。但这个也有限制,就是这些Steps必须有相同的subversion URL配置。
另外,你应该还注意到我们还传了另一个参数:PL_BUILD_NUMBER。这个参数会另有用途。
除了希望保持相同版本,我们很可能希望重用upstream step生成的artifact。比如,在AC Test step会生成一些artifacts,这些artifacts经过测试之后,希望可以用于Deploy步骤。一方面,这会节省重新构建artifact的时间;另一方面,这些artifact是已经经过测试的,是可用的,而重新构建生成的却是未经测试的,可用与否未知。(虽然他们应该是一样的,但谁知道呢。。)我们可以使用ArtifactDepolyerPlugin实现。
如上图,我们把构建生成的war包放到一个指定的目录。在Remote Directory中,我们使用了Parameterized Trigger中指定的环境变量:PL_BUILD_NUMBER。在Deploy步骤中,我们就可以到相应的目录下寻找要部署的war包以及配置文件等。(不用担心,当你在第一步传了某个参数后,后面的所有steps都可以拿到这个参数)
第三步
在上例中,Unit Test和Acceptance Test虽然运行在同一个版本的代码之上,但它们并不真正工作在同一份代码中,而且它们之间没有复用任何东西。比如,Unit Test已经compile过代码,但在AC Test步骤中还是要Compile。如果我们希望几个step工作在同一份代码之上,而且后面的step可以享用前面step的成果,可以使用Clone Workspace SCM plugin:
在upstream step中,比如Unit Test,把整个workspace打包。在downstream step中,比如Acceptance Test中,clone workspace,如下图:
在上图配置中指定parent project: Unit Test。如果我们使用了Clone Workspace,那么就没必要在steps之间传递Subversion revision了。
第四步
通过前三步,我们已经实现了一个实际意义上的pipeline。但还可以做一些增强。
首先,我们可以使用统一的build number来指定一个pipeline上的所有step。需要用到Build Name Setter Plugin (以及它所依赖的Token Marco Plugin)来为所有steps指定相同的名字,如下图:
另外,我们还可以加一个check来检查是否这些steps都运行在同一个workspace,这里需要用到Conditional BuildStep Plugin。可以使用的方法有多种,比如在upstream step中在workspace里生成一个跟此次build相关的特定名称的文件,然后在downstream step中使用这个plugin来检查这个文件是否存在,这样就可保证所有steps运行在同一份代码中了。
小结
到目前为止,我们已经使用Jenkins创建了一个真正的pipeline。最后是个很好的时机来回顾下,一个真正的pipeline需要满足什么条件。
-
一个pipeline有多个步骤,每个步骤都有不同的目的。比如在此例中,pipeline由Unit Test,Acceptance Test和QA Deploy三个步骤组成,分别代表一个构建的不同阶段。通常,这种分级构建是为了得到一个更加快速的反馈。详情可参见《持续交付》。
-
上游步骤通过之后,可以选择自动或者手动触发下游的步骤。
-
一个流水线的所有步骤工作在同一版本的代码上,甚至同一份代码上。
-
可以复用上游步骤的成果,也就是可以不重复执行在上游步骤中执行过的任务。
-
生成一次artifacts,在后面所有步骤中使用同一份artifacts。
-
统一流水线的所有步骤的名字,或者至少可以帮助识别这些step是工作在同一份代码上。