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. solr5.5教程-solr.home 配置

    solr/home是solr实例化core核的依据和入口,是必不可少的配置. 1.在web.xml中设置 <env-entry> <env-entry-name>solr/ho ...

  2. Android Malware Analysis

    A friend of mine asked me help him to examine his Android 5.0 smartphone. He did not say what's wron ...

  3. Completely change MACE timestamps?

    Hi, One of my friends Sandy asked me about the possibility of completely change MACE timestamps. As ...

  4. Servlet小试

    Java响应Http请求: 1.创建项目 因为对Java环境不是很熟悉,第一步卡住了好长时间, javax怎么引用, 在Java EE 5 Libraries中的javaee.jar中,项目中怎么引用 ...

  5. javaSE第二十天

    第二十天    254 1:递归(理解)    254 (1)方法定义中调用方法本身的现象    254 (2)递归的注意事项    255 (3)递归的案例:    255 A:递归求阶乘    2 ...

  6. centos6.5_x86_64安装Adobe Flash Player

    对x86_64的CentOS6.5系统,安装FireFox的Adobe Flash Player插件 安装插件,终端下输入命令:#wget http://linuxdownload.adobe.com ...

  7. js 实现获取对象所有键名(key)的方法

    1.for in 循环 并且使用hasOwnProperty 方法 var jsonObject1 = { "name": "xiaoming", " ...

  8. MIPS平台移植apache 2.2.7

    参考文章: http://wenku.baidu.com/view/94e08a20a5e9856a561260e2.html http://httpd.apache.org/docs/2.4/ins ...

  9. Template_Method

    #include <iostream> using namespace std; #define DESTROY_POINTER(ptr) if (ptr) { delete ptr; p ...

  10. vs C#数据库导入EXCLE

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...