http://www.infoq.com/cn/articles/MSBuild-2

 

作者 Mustafa Saeed Haji Ali ,译者 李剑 发布于 2012年10月23日 | 注意: 挥一挥衣袖,带走满满干货,关注活动大本营,时不时发福利呦!3 讨论

 

这是持续集成系列的下半部分,如果你还没看过上半部分的话,请点击这里:用MSBuild和Jenkins搭建持续集成环境(1)

与Jenkins相会

Jenkins在2004年由Kohsuke Kawaguchi创建,最开始的名字叫Hudson。Kawaguchi当时在Sun工作,Sun直到2008年一直为Hudson提供支持,但是当它被Oracle收购以后,Oracle和Hudson的开发者社区出现了分歧。2011年,Oracle宣称了对Hudson商标的所有权,Hudson开发社区于是将Hudson改名叫Jenkins,摆脱了Oracle的干扰,继续开发工作。

第一眼看上去,Jenkins像是一个专为Java项目准备的持续集成工具:有为Maven项目设计的job,有诸多为Java项目提供的默认插件,更不要说那些用Java写的插件了。

但Jenkins其实是一个非常灵活的工具,它可以结合各种版本管理系统和构建工具,用来构建任何类型的项目。在这篇文章中,我们会利用它的灵活性,从Mercurial中pull代码,用MSbuild构建项目。首先,我们需要下载并安装Jenkins,然后安装Mercurial和MSBuild插件。

配置Jenkins

官方网站下载安装程序。它的Windows安装包很简单,会把Jenkins安装成Windows服务。Jenkins的默认的访问路径是http://localhost:8080,请确保8080端口不要被其他应用占用。

安装完毕以后就是装插件。请点击“Manage Jenkins”链接,然后再点击“Manage Plugins”。在“Available”标签页可以查看当前可安装的插件──你需要有一个能上网的环境,才能看到这一页的内容。用filter找到Mercurial和 MSBuild插件,点击插件名称前面的单选框,进行安装。你可以点击“Installed”标签页,来确保这两个插件已经被安装成功了。在安装过程中,你可能会看到提示信息说Jenkins需要重启才能完成安装,请让它重启,等重启完成后再访问“Installed”标签页,看看是不是安装成功。

Mercurial插件还需要做一些配置,才能让Jenkins找到Mercurial的安装路径。回到“Manage Jenkins”这一页上来,点击“Configure System”,找到“Mercurial”这一部分──如果你找不到“Mercurial”的话,就说明Mercurial插件没有装好──点击“Add Mercurial”按钮之后,你需要给这个Mercurial实例起个名字(自己用着越方便越好);还需要输入Mercurial可执行文件的安装路径,这里用的是hg.exe文件的所在目录;最后是可执行文件的名字,就用“INSTALLATION/hg.exe”就好,INSTALLATION这个单词会被前面输入的安装路径替换掉。

创建一个Jenkins Job

点击“Back to Dashboard”,回到Dashboard上来,然后点击“New Job”链接。你会看到一组job类型,选择“Build a free-style software project”,给它命名为“HelloCI-RunUnitTests”,点击OK。

下一步是job配置页面。这一页有很多配置项,而且大多数都带有详细的描述信息,点击右侧的帮助图标就可以看到。我们现在只配置两部分,一是代码库所在位置,二是如何用MSBuild构建项目。

找到“Source Code Management”,选择Mercurial。在“Mercurial Version”输入框中输入先前在“Configure System”中配置的Mercurial名称。然后在Repository URL中输入Mercurial版本库的URL(也可以是一个文件系统的路径)。最后在Branch中输入你想跟踪的分支名。

接下来到“Build”这部分。点击“Add build step”按钮后,下拉框中就会出现一系列的step类型以供选择,其中便包括“Build a Visual Studio project or solution using MSBuild”,如果你没看到这个选项,就说明MSBuild插件没有正确安装。

点击“Build a Visual Studio project or solution using MSBuild”之后,在“MSBuild Build File”输入框中输入构建脚本的名字:HelloCI.msbuild。我们想让Jenkins执行“RunUnitTests”这个Target ,如果你没有把DefaultTargets属性设成RunUnitTests的话,可以在“Command Line Arguments”中输入“/t:RunUnitTests”,其中/t是/target的简写。

点击“Save”或“Apply”保存之后,这个job一旦被触发,就可以pull代码下来,编译项目,执行单元测试。我们先来手工触发一次,看看配置是否正确。先回到Dashboard,这时可以在屏幕中央看到我们的job。点击job名字,然后在左侧的链接中找到“Build Now”链接,点击它,Jenkins就会开始执行。在这组链接的下方有一个“Build History”列表,它显示的是这个job的所有构建历史,当第一次构建开始运行的时候,你会在列表中看到一个进度条,同时还有一个小圆球显示构建状态。圆球闪烁表示构建正在进行中,它停止闪烁的时候一般会是红色或蓝色,红色表示构建失败,蓝色表示成功。

如果这个job能够访问Mercurial版本库,找到了HelloCI.msbuild脚本,“RunUnitTest”执行成功,这个圆球应该会变蓝。这时候你也就顺利完成了第一个Jenkins构建。如果构建失败,请点击“Build History”对应的编号查看详细信息,然后点击“Console Output”,就可以看到Jenkins所执行的每一个命令和对应结果,从中可以分析出构建失败的原因。

触发构建

构建成功以后,下一步要做的就是让Jenkins检测版本库的变化,一旦有代码提交,Jenkins就要pull代码并执行构建。有好几种方法可以做到这一点。最简单的就是让Jenkins定时构建,但是如果在这一段时间内没有代码提交,这次构建反而是浪费。另一种方式是让Jenkins定时轮询,看看版本库中是否有代码提交。这种方法的缺点是当有了代码提交以后,Jenkins要等到下一个轮询周期才能执行构建。当然,你也可以让Jenkins每分钟都轮询一次,尽可能缩短等待时间,但我们还有另一种更优雅的方案──给Mercurial版本库中放一个post-commit的钩子,这样一旦版本库接受了新代码,它都会通知Jenkins,让它立刻开始构建。

这个方法需要在.hg目录下的配置文件中(.hgrc)添加一个钩子。在这个钩子里面,你需要让Mercurial访问下面这个网址:http://localhost:8080/job/JOBNAME/build?delay=0sec(JOBNAME需要替换成真实的job名称),让Jenkins启动构建。但不幸的是,Windows下没有类似Linux wget这样可以进行HTTP请求的工具。我自己写了行Ruby代码来做这项工作。你也可以用Powershell来创建一个System.Net.WebClient的实例,然后调用DownloadString方法。读者朋友可以自己完成这项工作,权当练习吧。

如果你不愿意用这个方法,就还用轮询吧。回到job配置页面,在“Build Trigger”区域选择“Poll SCM”,在“Schedule”输入框中输入轮询周期。它采用的语法格式是cron的风格。如果要每分钟轮询一次,就输入“1 * * * *”。你可以点击输入框右侧的帮助按钮,查看轮询周期的语法介绍。

构建流水线

Jenkins可以在某个构建成功结束之后启动其他job。于是就有了构建流水线,它的概念就是一个job成功之后触发其他job。触发者叫做上游job,被触发者被称作下游job。

构建流水线的应用场景有很多:让耗时较长的测试在单元测试结束之后执行;运行静态代码检查;把构建结果部署到试机环境(staging)或者产品环境中。我们下面来演示一下这个功能,让Jenkins在构建结束后启动web服务器,运行HelloCI这款应用。

我们只需要做三件事情:HelloCI-RunUnitTests job成功之后触发一个新job;把HelloCI-RunUnitTests的构建结果拷贝出来;启动web服务器。在开始之前,你还需要安装Copy Artifacts插件。回到Manage Plugins页面,参考之前安装Mercurial插件的方法安装Copy Artifacts。在看到重启的提示信息时重启Jenkins。

创建新job之前,我们需要告诉HelloCI-RunUnitTests job,让它把构建产物保存下来,以供新job使用。回到HelloCI-RunUnitTests job的配置界面,找到“Post-build Action”,选中“Archive the artifacts”,页面上就会出现一个文本框:“Files to archive”。我们要存档的目录有两份,一份是BuildArtifacts目录,一份是packages目录,后者是为了让我们能够访问NuGet package。如果要指定某个目录以及目录下所有内容,就需要在目录后面跟一个斜杠和两个星号。不同的目录或文件之间用逗号分割。在这里我们输入的是“BuildArtifacts/**,packages/**”。

现在创建一个新job,起名叫“HelloCI-StartWebServer”。在配置页面上“Build Triggers”那一节里选中“Build after other projects are built”,把之前那个job配置成要触发当前job的项目。

接下来给job添加一个build step,让这个job所做的第一件事情就是拷贝之前job所保存的构建产物。这里要用到“Copy artifacts from another project”这个step(它是由Copy Artifacts插件提供的)。我们只需要填入HelloCI-RunUnitTests job的名字就可以。

最后还要添加一个build step,让它启动web server。这里用的是“Execute Windows batch command”,我们用Visual Studio提供的Cassini来运行应用。Cassini可以在“C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.EXE”找到。运行Cassini很简单,把web应用存放的路径作为参数传给它就行,如果没有指定端口号的话,它就会使用默认的端口号80。

“Execute Windows batch command”step需要一个可以在BuildArtifacts和packages拷贝后的目录下执行的命令。我们把下面这个命令复制到“Command”输入框中:

"C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\WebDev.WebServer40.
EXE" /port:9876 /path BuildArtifacts/_PublishedWebsites/HelloCI.Web/.

这个命令可以启动Cassini,把它指向拷贝过来的应用,然后在9876端口启动服务器。

所有的配置都已就绪。试着修改一下代码然后提交。Jenkins应该能够监听到变化,运行HelloCI-RunUnitTests。如果代码编译成功,所有测试均以通过,Jenkins应该开始运行HelloCI-StartWebServer job,把HelloCI-RunUnitTests的构建产物拷贝过来,在9876端口启动Cassini。如果这一切都运行无误,我们的持续集成系统就搭好了。

结尾

MSBuild和Jenkins可讲的地方还很多。比如说可以从持续集成走向持续部署。你所需要的只是一个job,让它把构建产物部署到生产环境(译者注:持续部署殊非易事,作者有些夸大其词,读者请勿轻信)。ASP.NET的应用就更简单了,用一个job把构建产物复制到某个目录下就行。这样一来,只要所有的测试全都通过,这个Jenkins job就可以把最新特性发布到生产环境上去。

如果你还没做好准备走那么远,也可以用一下Promoted Build plugin,它可以在某个构建达到了一个特定的标准之后,把它标记为“推荐使用”。一个人或几个人手工审核过一个构建,也算得是达到了推荐标准。有了Promoted Build plugin,人们做出的修改就可以自动发布到开发服务器上,所有的新功能都集中呈现。开发经理而后可以把某个特定的构建推荐到试机环境中。QA团队或其他干系人可以进行验收(其方式就是推荐试机环境上的构建),然后这个构建就可以由Jenkins部署到产品环境上。

John Ferguson Smart曾写过一本很出色的书,叫做“Jenkins: The Definitive Guide”。这本书除了讲述Jenkins的功能之外,还描述了怎么保证Jenkins的安全,怎样检测资源使用(如磁盘占用),怎样进行分布式构建,直到设置通知系统,让用户在构建开始、成功、失败的时候得到通知。这本书由O'Reilly出版,购买地址在此。如果你对Jenkins还不太了解的话,本书就属于必看的一本。

拥有一个自动化的构建部署系统,就跟要看重测试,要使用版本控制系统一样重要。我希望你已经熟练掌握了如何设置持续集成系统,可以开始着手集成自己的系统。

一开始不要太激进,一心想着把所有事情都做好。你可以一点一点来。你终会享受到胜利果实的。当Jenkins通知你某个构建失败的时候,你发现bug的时机就提前了;当你再也不用记忆每一步部署的操作时,你就有了一整套系统化的部署流程。而更重要的是,你有了更多时间去做更重要的事情,比如开发有价值的特性,或是为新项目做准备,也可以提前下班回家,再也不用为即将到来的上线担忧。

关于作者

Mustafa Saeed Haji Ali居住在Somaliland的Hargeisa。他是个程序员,最常用的是ASP.NET MVC。Mustafa喜欢测试,喜欢用Javascript框架,如KnockoutJS、AngularJS、SignalR。他热衷于传播最佳实践。

查看英文原文:Continuous Integration with MSBuild and Jenkins – Part 2

用MSBuild和Jenkins搭建持续集成环境(2)的更多相关文章

  1. 用MSBuild和Jenkins搭建持续集成环境(1)

     http://www.infoq.com/cn/articles/MSBuild-1 你或其他人刚刚写完了一段代码,提交到项目的版本仓库里面.但等一下,如果新提交的代码把构建搞坏了怎么办?万一出现编 ...

  2. 用MSBuild和Jenkins搭建持续集成环境(1)[收集]

    你或其他人刚刚写完了一段代码,提交到项目的版本仓库里面.但等一下,如果新提交的代码把构建搞坏了怎么办?万一出现编译错误,或者有的测试失败了,或者代码不符合质量标准所要求的底限,你该怎么办? 最不靠谱的 ...

  3. 用MSBuild和Jenkins搭建持续集成环境 - 转

    http://www.infoq.com/cn/articles/MSBuild-1 http://www.infoq.com/cn/articles/MSBuild-2 MSBuild是在.NET ...

  4. MSBuild和Jenkins搭建持续集成环境

    http://www.2cto.com/os/201409/334323.html http://my.oschina.net/anxuyong/blog/353897 http://www.cnbl ...

  5. 采用Jenkins搭建持续集成环境

    Jenkins介绍 Jenkins是一个CI工具.它可以根据设定持续定期编译,运行相应代码:运行UT或集成测试:将运行结果发送至邮件,或展示成报告... 这样做的最终目的是: 让项目保持健康的状态.如 ...

  6. JavaWeb+SVN+Maven+Tomcat +jenkins搭建持续集成环境和自动部署

    https://blog.csdn.net/wh52788/article/details/80900477 https://blog.csdn.net/liyong1028826685/articl ...

  7. 基于 Jenkins 快速搭建持续集成环境

      什么是持续集成 随着软件开发复杂度的不断提高,团队开发成员间如何更好地协同工作以确保软件开发的质量已经慢慢成为开发过程中不可回避的问题.尤其是近些年来,敏捷(Agile) 在软件工程领域越来越红火 ...

  8. 使用Maven+Nexus+Jenkins+Svn+Tomcat+Sonar搭建持续集成环境(二)

    前言     上一篇随笔Maven+Nexus+Jenkins+Svn+Tomcat+Sonar搭建持续集成环境(一)介绍maven和nexus的环境搭建,以及如何使用maven和nexus统一管理库 ...

  9. 基于 Jenkins 快速搭建持续集成环境--转

    源地址:http://www.ibm.com/developerworks/cn/java/j-lo-jenkins/ 持续集成是一种软件开发实践,对于提高软件开发效率并保障软件开发质量提供了理论基础 ...

随机推荐

  1. WP_图片管理机制/异步读取网络图片

    项目有这样的需求, 要求窗口加载一揽子图片,为了不让UI阻塞太久,采用异步读取后绑定显示的方案. 图片的下载应该采用并发的过程(等待网络响应会很耗时,一张一张的下载,等待时间太长) 图片的下载不能占用 ...

  2. Jquery动画效果--地铁站名指示等效果

    源码参考:源码爱好者--jQuery仿地铁线路指示灯效果,经修改和美化,特此记录一下. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tra ...

  3. c#高效比对大量图片

    比较图片的方法 以前传统的比较方式是遍历图片中的每一个像素,然后进行比对.这样的比对在少量图片的比对上虽然效率低一点,但是也没有什么不好.但是在大量图片比对的时候,过长的反应时间和对服务器比较高的消耗 ...

  4. 数据包判断是否丢包 ping+tracert+mtr

    1.用咱们最常用的Ping命令来查看是不是真的丢包了 这里可以看到数据包发送了4个,返回了4个,丢失=0  证明没有丢失 也有可能中间路由做了策略不给ICMP的回应 这样就ping没法判断了  正常情 ...

  5. iOS中UIKit——UIDataDetectors(数据检测器)它将电话、邮件、网址等变为链接

    1.它用于UITextView和UIWebView,属性名为:dataDetetorTypes 2.此属性可以设定使符合电话.邮件.网址.符合格式的日期等文字变为链接文字. 3.电话号码点击后拨出电话 ...

  6. freefilesync 7 使用

    官方下载地址:http://www.freefilesync.org/download.php 1.打开FreeFileSync 设置左右的文件夹,设置过滤规则,设置同步方式(双向.单向),执行同步 ...

  7. (function ( ){})( ) 与 (function ( ){}( )) 有什么区别?

    js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别? 转自:http://www.jb51.net/article/75089.htm ...

  8. IT新人论成长

    说自己是新人,其实自己也不新了,2012年毕业,辗转3个城市,现在在上海一家公司,工资不到5K. 在来现在公司之前,我从事web后台开发,采用MVC模式,虽然做了不少的网站,但感觉自己的水平还是在底层 ...

  9. 12.python中的列表

    先看列表是如何创建的: a = ['scolia', 123] b = list('scolia',123) 同样有两种创建方式,但一般用第一种. 列表和元祖最大的不同就是列表是可以修改的. 老规矩, ...

  10. Python脚本控制的WebDriver 常用操作 <十二> send_keys模拟按键输入

    下面将使用WebDriver中的send_keys来模拟键盘按键输入 测试用例场景 send_keys方法可以模拟一些组合键操作: ctrl+a ctrl+c ctrl+v 等. 另外有时候我们需要在 ...