FinOps有望降低企业50%+的云成本! 了解详情
写点什么

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

  • 2012-10-23
  • 本文字数:5002 字

    阅读完需:约 16 分钟

这是持续集成系列的下半部分,如果你还没看过上半部分的话,请点击这里:用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

2012-10-23 00:0010255
用户头像

发布了 197 篇内容, 共 50.5 次阅读, 收获喜欢 20 次。

关注

评论

发布
暂无评论
发现更多内容

区块链架构下 智慧城市发展加速

CECBC

融云猿桌派:35 岁程序员,正值当打之年,尚有星辰大海

融云 RongCloud

程序员

异构注册中心机制在中国工商银行的探索实践

SOFAStack

GitHub 开源 分布式架构 注册中心 工商银行

一文带你了解 Python 中的生成器

踏雪痕

Python 生成器 3月程序媛福利 3月月更

在线正则表达式大全测试

入门小站

工具

在线Javascript美化格式化工具

入门小站

工具

高层次人才一站式服务平台系统开发

a13823115807

“中本聪岛”加密乌托邦

CECBC

黑匣子为什么难成为“云匣子”?

脑极体

java版gRPC实战之二:服务发布和调用

程序员欣宸

Java gRPC

VuePress 博客搭建系列 33 篇正式完结!

冴羽

JavaScript Vue 前端 vuepress 博客搭建

区块链等技术助力北京海关监管

CECBC

服务器防渗透--信息收集

喀拉峻

网络安全

深入浅出 Java FileChannel 的堆外内存使用

Apache IoTDB

前端食堂技术周刊第 30 期:Vercel 支持零配置部署使用 pnpm 项目、React 新文档更新、Angular Roadmap、Remix Stacks

童欧巴

JavaScript 编程 前端 周刊 资讯

数字医疗时代的数据安全如何保障?

CECBC

Flutter 路由及路由拦截跳转404

岛上码农

flutter ios Android开发 移动端 3月月更

Paxos vs. Raft:我们对共识算法达成共识了吗?

多颗糖

分布式系统 raft PAXOS

kubeadm工作原理-kubeadm init原理分析-kubeadm join原理分析

良凯尔

容器 云原生 kubeadm #Kubernetes# Kubernetes 集群

Linux之file命令

入门小站

Linux

开放报名丨《音视频社交新风口》线上峰会,聚焦海外社交生态升级

融云 RongCloud

JS Array数组几个循环实用方法总结

MegaQi

JavaScrip 测试发开 web前端开发

URL的四种形式对比说明

源字节1号

前端开发 后端开发 网站开发

[Day3]-[快慢指针]解决链表问题

方勇(gopher)

LeetCode 数据结构与算法

架构实战营-模块一-作业

CityAnimal

架构实战营 #架构实战营 「架构实战营」

OceanBase 开源负责人纪君祥聊 社区版 2022 Roadmap

OceanBase 数据库

oceanbase OceanBase 开源

360大数据技术专家 程建云:IoTDB在360的落地实践 | Apache IoTDB Talk

Apache IoTDB

时序数据库 IoTDB Apache IoTDB

加密货币监控和区块链分析如何帮助避免加密货币欺诈?

CECBC

基于微信小程序的实验室预约小程序平台详细设计

CC同学

小程序电商业务微服务拆分及微服务基础设施选型

Geek_36cc7c

超分算法在 WebRTC 高清视频传输弱网优化中的应用

融云 RongCloud

PyTorch

  • 需要帮助,请添加网站小助手,进入 InfoQ 技术交流群
用MSBuild和Jenkins搭建持续集成环境(2)_.NET_Mustafa Saeed Haji Ali_InfoQ精选文章