求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
 
   
分享到
使用Ant脚本做WMB项目自动构建部署
 

发布于2013-8-12

 

简介: 本文介绍一种可行的 WebSphere Message Broker(WMB)自动部署方案项目实践,它使用Ant脚本从 Rational Team Concert(RTC)上更新给定 Baseline 的 WMB 项目资源,按需修改节点属性并自动打包并部署到指定的 Broker 服务器。该方案旨在提供给维护团队,部署团队以更便利的方式来更新和部署 WMB 项目;而不依赖于 RTC Client 和 WMB Toolkit IDE 的使用。您将看到示例代码的详细内容,包括支持该方案的 RTC SCM 工具介绍、WMB 的命令介绍,以及关键的 Ant 方法设计和实现。

前言

在大型 WebSphere Message Broker(WMB)项目进入集成测试阶段以后,开发团队迭代的推动进程的时候,测试人员往往会面临每天测试版本不一致的问题;在接下来的 UAT 乃至上线以后,系统的部署往往由对 WMB 技术细节并不非常熟悉的部署团队进行。

从过往的项目经验看,这样的挑战:一、是会花去较多的时间来对非开发团队进行 WMB Toolkit 工具的使用(包括如何导入需要版本的 WMB 项目,如何在 Toolkit 里构建以及发布 bar 文件,等等)培训;二、是对于某些项目,大量 Message Flow 的节点属性针对不同环境和需要在打包时要修改的时候,人工的操作很容易出错。另外由于 WMB7 的 Toolkit 没有集成 Rational Team Concert(RTC)3 的插件,导致同步或维护多个工作空间也常常困扰部署人员,导致错误率上升。

本文将通过示例来展示一个用 Ant 自动部署 WMB 的方案。

设计概述

案例背景

某采用 Rational Team Concert(RTC)作为版本管理平台的 WMB(MB7.0)项目 ABC,目前模块 1 有两个 MessageFlow 工程 MsgFlowProj1 和 MsgFlowProj2,分别对应所需的两个 MessgeSet 工程 MsgSetProj1 和 MsgSetProj2。为该项目创建的 RTC 开发 Stream 名字为 ESB_ABC_Dev_str;在此 Stream 下为代码创建了 Component 名为 ABC_Code_Dev_Comp。该项目位于此 Component 下的 Src 目录,另有 Test 目录给测试人员使用;该项目的版本通过 Baseline 来指定。基本情况如下图所示:

图 1. 示例项目 RTC 结构

部署人员有 DEV 和 SIT 两套环境需要每天维护提供给测试人员,所以在部署的时候除了要不断的根据测试需求下载不同 Baseline 版本的工程代码,而且还需要在编译成 bar 文件之后更改 Trace 节点下的 log 文件的路径,以及设置给 Compute 节点下的数据源(Data Source)名称,以保证部署到不同环境下的消息流能正确运行。目前所有的操作需要通过 RTC 客户端和 WMB Toolkit 来操作,工作量很大且容易出错;随着项目不断增大,此方法将难以保证质量的稳定。

部署人员想要的是:有一个理想的工具方案,我指定 Component 的 Baseline,工具就能正确的获取基于 Baseline 的代码,打包并覆写必须的属性,然后部署到指定服务器里正确执行组中。

嗯,这就是我们所要寻求的方案。

方案概述

本文将介绍的这个 WMB 自动部署方案项目实践,它使用 Ant 脚本从 RTC 上更新指定 baseline 的 WMB 项目资源,自动打包,并按需修改节点属性并部署到指定的 broker 服务器。整个过程模拟人工操作的顺序,易于非开发团队理解;工具各模块力求清晰、独立,便于后期维护和扩展。部署团队不再依赖于操作 RTC 客户端和 WMB Toolkit 的技能需求。

图 2. 方案概况

从上图看出,脚本需要从本地登录到 RTC 服务器,根据配置的内容来取得项目代码,然后用给定的属性来覆盖原始 Message Flow 的节点属性,最后自动连接到 Broker 的服务器,将生成的 bar 文件发布到指定的执行组去。由于脚本的维护基于文本操作,大大降低了操作难度;整个过程,操作人员甚至只需要键入一条命令(如果设计为全自动),就可以完成任务。

为了实现这样的一个方案,接下来会先分别介绍一下 Ant 脚本会主要用到的 RTC SCM 工具和 WMB 的访问命令。

RTC SCM 工具介绍

IBM Rational? Team Concert 软件是一个协作环境,用以帮助个人和团队发挥最佳性能。它提供了基本的软件版本控制、工作空间管理和平行开发支持。这是一个很强大且内涵深刻的 IBM 工具,在此我们仅针对本文主题来讨论其基本概念和管理特点,并介绍 SCM 工具的使用。

RTC 基本概念及操作流程

对于典型的 RTC 版本管理,一般在大型项目中会定义几个 Stream 来用于不同层面的管理,例如 Development Streams, Integration Streams 以及 Production Streams 等。而由于 RTC 管理员往往是用提升操作(promotion)来做版本切割,所以不同级别的 Stream 在文件结构上是一致的。对于某一个特定的 Stream 在使用中各部件的关系,我们用如下的一个模型来说明:

图 3. RTC 版本管理层次结构

上图说明了三个要点,是需要在脚本编写前理解的概念:

在虚线以上的部分,基于一个 Stream 的各个 Workspace,和其包含的 Component,是在服务器上的。

谈论一个 Component 时,一定是在某一个 Workspace 的范围内。

本地通过 load 操作,将代码做一份本地的拷贝。

了解了 RTC 的一个层次结构后,我们接下来再简单提一下在一个团队里操作 RTC 版本管理的流程,以遍更充分理解脚本的处理流程。下图显示了一般的 RTC 版本管理的提交、获取的过程:

图 4. RTC 版本管理操作流程

当开发团队提交了 (Check in) 更改或 Baseline 到 Workspace,并递送了 (Deliver) 代码到 Stream 后,负责部署的人员需要从 Stream 上接受(Accept)这个更改到自己的 Workspace,然后再同步接受更改到本地,以完成本地沙盒 (Sandbox) 中代码的更新。对于获取更新的部署人员需要注意,接受(Accept)更改到自己的 Workspace 是在服务器上完成的——而这正是我们获取指定 Baseline 的基础;接下来从本地接受 Workspace 的更改才是获取指定版本的代码。

方案思路整理 1

从图 2所描述的概况来整理一下关于 RTC 操作方面的思路:

登录服务器 --> 获取指定代码 --> 将代码下载到本地。

首先,工具能够登录 / 登出 RTC 服务器以便能完成 Workspace 里的操作,这是前提,也就是方案概况里提及的"登录 / 登出"。

接下来,在登录以后有两种情况:

1. 该 RTC 账户第一次使用此工具,此时应该能够为该账户创建为构建部署而准备的 Workspace,以获取开发团队提交的代码。考虑到操作的简便性,Workspace 的名字在属性文件中指定,对于操作者而言是透明的。

2. 该账户已经创建了专门的 Workspace 用于更新代码,则不需要(且不能够)再次创建一个同名的 Workspace。

当 Workspace 准备好以后,将该 RTC 账户中目前的 Workspace 的 Baseline 替换为所需(所指定)的 Baseline,以完成指定代码版本的获取、更新。这是方案概况里提及的"获取指定版本"。

最后,即是把准备好的代码版本从服务器上的 Workspace 下载到本地。用于保存本地代码的目录名称在属性文件中已经指定;另外从稳妥方面考量,在下载代码之前,工具可以自动先把本地已经存在的工程文件删除,以避免出现遗留的错误工程代码可能影响编译。这是方案概况里提及的"加载到本地"。

好了,根据以上思路的简单整理,我们可以理出本方案关于 RTC 的一些核心操作内容:

登录 / 登出 RTC

为指定的 Stream 创建 Workspace

在 Workspace 上更新指定的 Baseline 代码

在本地获取代码的拷贝

接下来我们来根据以上需求,从 SCM 工具中找到解决办法。

SCM 工具的使用

SCM 命令是一套实现了 RTC 源代码控制的命令行接口,有许多的子命令和参数以提供给用户灵活的脚本访问能力。根据之前的分析,本文所探讨的 SCM 工具主要涉及:登入 / 登出,创建用户 Workspace,更新到指定 Baseline 并下载代码。下面将结合案例背景中提到的示例项目来熟悉以上 RTC SCM 工具的操作。( 有关以下涉及的命令,其具体的语法请参看附录)
login:登入指定的 RTC 服务器,并保存登录信息。

项目使用示例:

scm login –r https://rtc.abc.com:9443/ccm/ -u deploy_team1 –P Dep0Ly –n abcRobot

值得一提的是最后的–n 参数。它指定一个任意昵称 (nickname),用于存储当前登入信息,以便在后续的 SCM 子命令中继续使用。在这里,我们取名为 abcRobot。接下的步骤,会基于这个昵称来操作。

create workspace:创建用户工作空间(Workspace)。

项目使用示例:

scm create workspace –r abcRobot team1_sit_WS   –s ESB_ABC_Dev_str

该行命令是用 SCM 工具为已登录的昵称 abcRobot 的用户创建一个 Workspace,该 Workspace 操作的代码库的 Stream 为 ESB_ABC_Dev_str,名字为 team1_sit_WS。以后的操作将会基于这个 Workspace 来做。

workspace replace-components:将 Component 替换为指定的 Baseline 版本。

项目使用示例:

scm workspace replace-components --all 
--overwrite-uncommitted team1_sit_WS stream team1_sit_WS
–baseline Baseline_For_SIT_23 –r abcRobot

在这个例子中,先假设开发组长曾为 ABC_Code_Dev_Comp 部件创建了一个名为 Baseline_For_SIT_23 这样的 Baseline。通过以上命令,就可以使 abcRobot 昵称用户下的 team1_WS 工作目录替换到此指定的 Baseline。

load:将代码库 Workspace 里面的部件下装载到本地目录。

项目使用示例:

scm load workspace –f –r abcRobot team1_sit_WS ABC_Code_Dev_Comp/Src/MsgFlowProj1 
–d C:/RTC_WS/ABC/Module1

该条命令将会从用户的 team1_sit_WS 工作空间中的 ABC_Code_Dev_Comp 部件里,找到 Src 目录下的 MsgFlowProj1 项目,并把项目的全部内容下载的本地的 C:\RTC_WS\ABC\Module1 目录中。

logout:登出 RTC,并删除保存的登录信息。

项目使用示例:

scm logout –r abcRobot

执行完此条命令后,用户即断开与 RTC 服务器的连接并删除了登录零时信息。

以上即是本文所探讨的方案所设计的 RTC SCM 工具使用方法。综合这些例子我们可以发现:当 RTC 的信息(RTC 结构和用户信息)已经给定的时候,只需要给出某个 Component 的 Baseline,就可以依次用这些脚本命令从服务器上拿到所需的代码。

需要额外说明的一点是,RTC 对于每一个 Workspace 会自动分配一个内部 ID 号。因此对于 RTC 而言 Workspace 的名称并不是作为唯一标识,换句话说 Workspace 是可以重名的。因此如果重复执行了创建 Workspace 的命令,会产生重名的 Workspace。这个操作和结果都合法,但是在用 SCM 工具来替换 Baseline 版本的时候,会抛错提示无法匹配到唯一的 Component。

这里再介绍另外两个个 SCM 子命令,可以用于发现并删除多余的 Workspace。

list workspaces:列出用户名下所有的工作目录。

项目使用示例:

scm list workspaces –r abcRobot

执行此条命令后,以 abcRobot 为昵称的用户所创建的所有 Workspace 将被显示到屏幕,包括 Workspace 的名字和其 ID 编号。这样就可以记录下重复的 Workspace 的 ID。

workspace delete:删除指定的 Workspace。

项目使用示例:

scm workspace delete –r abcRobot 1011

该命令删除 ID 号为 1011 的 Workspace。执行后,以前 ID 为 1011 的 Workspace 将不存在于昵称为 abcRobot 的登录用户信息中。

在后面的讨论章节里面,会进一步讨论有关删除冗余 Workspace 的流程组织和使用。接下来,是时候看看如何处理已经得到的版本代码。

方案思路整理 2

完成了在本地加载正确版本的代码操作以后,再根据图 2的方案概况来连贯一下这之后的操作思路:

构建 --> 更新部署描述 --> 部署到服务器。

当所需代码下载好以后,就可以进行"构建 bar 包"的步骤了。此时在构建工具的属性文件中已经指定了本地代码的工作路径,此路径即为 RTC 加载代码到本地的工作路径。除了路径,还需要考虑在构建中哪些工程是需要的,哪些工作流和消息集是所需的,这些信息一并应该指定在属性文件中。因为在有的架构设计里,并非所有的流都是用于当前项目。

由于开发团队提交的代码并非为部署环境而配置,所以用部分节点和属性的设置需要被修改以确保部署到非开发环境后正确运行,这即是说要"覆盖指定属性"。针对需要被修改的属性,诸如 Trace 节点 log 文件的路径、名称,或是 Data Source 的值等等,应该在属性文件中预先定义,对操作人员透明。到这里其实需要部署的 bar 文件才算是完成了。

最后,是把之前制作好的 bar 文件按要求"部署到执行组"。对于一个特定的 bar 文件部署,首先需要确定其 broker 的信息,包括目标服务器(host、Qmgr 以及端口等)和目标执行组等;另外还包括根据项目需求设置部署超时错误的时间等。和之前的设定一样,这些信息被预先配置在属性文件里,操作时候无需再指定。值得一提的是,当一个 bar 文件需要同时部署到多个 broker 服务器时,需指定多套 broker 信息。

综上,对于准备好了的本地代码有以下核心的操作任务:

根据指定的工程和其包含的消息流、消息集来打包 bar 文件。

根据预先定义的环境属性文件来覆写生成的 bar 文件内的部署描述。

把制作好的 bar 文件部署到指定的服务器上的执行组里。

当然,我们将通过 WMB 提供的操作命令来完成这些任务。

WMB 命令操作介绍

从版本 6.0.2 开始,WMB 提供了很多的工具程序,以让用户能快捷的在 Windows 或 Unix 命令界面来操作 Broker。在 WMB7 里面,这些工具程序包括了 Broker 命令,数据命令、安全命令等 10 大类,达数十个。限于本文讨论的范围,这里介绍其中三个用于打包、覆写属性和发布的三个命令。( 有关以下涉及的命令,其具体的语法请参看附录)

依然根据案例背景所设定的示例项目,下面分别讲解 mqisicreatebar、mqsiapplybaroverride 和 mqsideploy:

1.mqsicreatebar:用来创建包含消息流和字典文件的可部署 bar 包文件。

使用示例:

mqsicreatebar –data C:/RTC_WS/ABC/Module1 –b ABC_Module1_Bar.bar –p MsgFlowProj1 –o MsgFlowProj1\MyABC_flow1.
msgflow MsgSetProj1 \messageSet.msgflow

这条命令将会在去 C:\RTC_WS\ABC\Module1 目录下找到 MsgFlowProj1 工程,并把其中的名为 MyABC_flow1 的消息流和 MsgSetProj1 消息集打包到名为 ABC_Module1_Bar 的 bar 文件中。这个 bar 文件将会生成在当前的目录中。

2.mqsiapplybaroverride:该命令可以用新的值来替换掉已生成的 bar 文件中指定的部署描述符。

使用示例:

mqsiapplybaroverride –b ABC_Module1_Bar.bar –p ABC_Module1_bar.properties

假设需要为前面生成的 bar 文件中的 MyABC_flow1 消息流中的 Trace 节点设置 SIT 的 log 文件名,该文件名在开发人员在消息流中设置的 C:\log\M1\Flow1.txt 改为 SIT Unix 环境下的路径;并针对要求,在使用此命令前已经做了一个属性文件 ABC_Module1_bar.properties 来完成此设定,目前该文件应包含如下内容:

COM.ABC.MyABC_flow1#TraceLog.filePath=/ESBTrace/sit/Module1/Flow1_trace.txt

完成该命令后,脚本会用指定在 ABC_Module1_bar.properties 内的值去更新在 bar 包中的相应的部署描述符,即是把 C:\log\M1\Flow1.txt 改为了 /ESBTrace/sit/Module1/Flow1_trace.txt。

3.mqsideploy:该命令用于向指定的 broker 发出部署请求。

使用示例:

mqsideploy –n ABC_SIT.broker –e EG_Module1 –a ABC_Module1_Bar.bar –w 1000

对于 broker 的参数规范,可以由一个文件来指定。此处,针对示例项目,假设已经有如下的 broker 信息文件 ABC_SIT.broker 存在,内容如下:

?xml version="1.0" encoding="UTF-8"?>
<configmgr crlNameList="" domainName="" host="192.168.1.123" listenerPort="1414" queueManager="ABCESBT1" securityExit="" securityExitJar="" sslCipherSuite="NONE"
sslDistinguishedNames="" sslKeyStore="" sslTrustStore="" svrconn="SYSTEM.BKR.CONFIG"/>

完成该命令,脚本会向指定的 broker 发送部署请求,尝试将 ABC_Module1_Bar.bar 部署到名为 EG_Module1 的执行组里面;整个请求过程超时设定为 1000 秒(根据项目要求设置)。

从以上三个命令的示例性使用,已经基本能勾勒出对已有代码进行自动打包部署的框架。

下面的章节会用 Ant 工具来整合前文提及的 RTC 的操作和 WMB 命令行工具,完成并进一步讨论本文所介绍的自动更新部署方案。

创建 Ant 脚本

脚本工作目录的规划

从之前的分析来看,脚本有两个主要的任务部分:①访问 RTC,②使用 WMB 命令。所以 Ant 脚本主要分成两个部分。另外对于单个的模块而言,有独立的工作空间更清晰,并方便后期维护扩展。基于这些基本目的,一个建议性的 Ant 工作目录设计如下:

C:\ABC_Ant :工作根目录
|
|___ \SIT :环境根目录
| |
| |__ \Module1:模块根目录
| | |
| | |__ \bar : 存放生成的 bar 文件
| | |
| | |__ \log : 存放 Ant 运行时的 log 信息文件
| | |
| | |__ \workspace : 从 RTC 获取的代码根目录
| | |
| | |__ {RTC build files}: RTC 任务脚本文件
| | |
| | |__ {Broker build files}:WMB 任务脚本文件
| |
| |__ \Module2
| ……
|___ \UAT
……

对于目录的设置和 RTC 访问信息的存放,可以设计为用一个单独的属性文件来保存。在这里简单的命名这个属性文件为 sys.properties,其内容可以包含如下的信息:

#RTC connection info
rtc.uri=https://rtc.abc.com:9443/ccm
rtc.nickname=abcRobot
rtc.usrname=deploy_team1
rtc.pwd=Dep0Ly

#MB7 installation home
broker.base=C:/Program Files (x86)/IBM/WMBT700/
mqsi.home=C:/Program Files (x86)/IBM/MQSI/7.0/bin/
profile.name=C:/Program Files (x86)/IBM/MQSI/7.0/binmqsiprofile.cmd

#SCM tool home
scm.tool.dir=C:/Applications/RTC-Client-Win-3.0.1/jazz/scmtools/eclipse

以上的 RTC 信息和目录根据实际情况修改好后,下面开始逐步创建 Ant 需要的 XML 构建文件。

RTC 任务脚本创建

RTC 脚本属性文件

首先我们需要为通过 Ant 脚本访问和操作 RTC 提供足够的信息,这些信息放在一个属性文件中。针对示例项目 ABC 的 Module1, 可以建立如下名为 Module1_RTC.properties 的属性文件:

#Ant script loacation
tool.dir=C:/ABC_Ant/SIT/
buildbase.dir=${tool.dir}/Module1

#--------------------|
#RTC scm tool home |
#--------------------|
scm.workspace.dir=${buildbase.dir}/workspace
rtc.prop.file=${tool.dir}/sys.properties

#------------------------------------------|
#The RTC Workspace name of each stream |
#------------------------------------------|
rtc.module1.wsname=team1_sit_WS

#--------------------|
#The RTC Dev streams |
#--------------------|
rtc. module1.strname= ESB_ABC_Dev_str

#--------------------|
#The RTC Components |
#--------------------|
module1.rtc.comp.proj= ABC_Code_Dev_Comp/Src/ MsgFlowProj1 ABC_Code_Dev_Comp/Src/
MsgFlowProj2 ABC_Code_Dev_Comp/Src/ MsgSetProj1 ABC_Code_Dev_Comp/Src/ MsgSetProj2

#--------------------------------------------------------
#| The baselines for deployment |
#| !! Edit the baselines each time before deploying!! |
#--------------------------------------------------------
rtc.module1.deploy.baseline=Baseline_For_SIT_23

RTC 任务脚本

创建好所需的属性文件后,接下来建立名为 Module1_RTC.xml 的构建文件。在这个文件里我们建立 Module1 的 Ant 工程,并引入前面提及的两个属性文件:

<?xml version="1.0"?>
<project name="RTC Operation">
<property file="Module1_RTC.properties" />
<property file="${rtc.prop.file}" />
…………

</project>

并在此 Ant 工程中建立如下三个 Ant 的 target,作为任务调用的模版:

<!-- ******* TEMPLATE START ******** -->
<target name="ws.create.template">
<exec executable="${scm.tool.dir}\scm.exe" failonerror="true" logError="true"
vmlauncher="false" append="true">
<arg line ="create workspace" />
<arg line="-r ${rtc.nickname}" />
<arg value="${_rtc.wsname}" />
<arg line="-s ${_rtc.strname}" />
</exec>
</target>

<target name="ws.update.template" >
<exec executable="${scm.tool.dir}\scm.exe" failonerror="true" logError="true"
vmlauncher="false" append="true" >
<arg line="workspace replace-components" />
<arg line="--all --overwrite-uncommitted" />
<arg value="${_rtc.wsname}" />
<arg line="stream ${_rtc.wsname}" />
<arg line="--baseline ${_rtc.deploy.baseline}" />
<arg line="-r ${rtc.nickname}" />
</exec>
</target>

<target name="ws.load.template">
<exec executable="${scm.tool.dir}\scm.exe" failonerror="true" logError="true"
vmlauncher="false" append="true" >
<arg line="load -f -r ${rtc.nickname}" />
<arg value="${_rtc.wsname}" />
<arg line="${_rtc.comp.proj}"/>
<arg line="-d ${_workspace.dir}" />
</exec>
</target>
<!-- ******* TEMPLATE END ******** -->

从前面的讨论中可以看到,基于本方案的 RTC 操作不外乎这三个。接下来继续在这个构建文件中加入适合 Module1 的 target,以传入在属性文件中定义的值。

<!-- For Module1 implementation Start -->
<target name="ws.create.module1" >
<echo message="Create Module1 SIT workspace" />
<antcall target="ws.create.template" >
<param name="_rtc.wsname" value="${rtc.module1.wsname}"/>
<param name="_rtc.strname" value="${rtc.module1.strname}"/>
</antcall>
</target>

<target name="ws.update.module1" >
<echo message="Replace Module1 with basline: ${rtc.module1.deploy.baseline}" />
<antcall target="ws.update.template">
<param name="_rtc.wsname" value="${rtc.module1.wsname}"/>
<param name="_rtc.deploy.baseline" value="${rtc.module1.deploy.baseline}"/>
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
</antcall>
</target>

<target name="ws.load.module1">
<echo message="Load Module1 from RTC" />
<antcall target="ws.load.template">
<param name="_rtc.wsname" value="${rtc.module1.wsname}"/>
<param name="_rtc.comp.proj" value="${module1.rtc.comp.proj}"/>
<param name="_workspace.dir" value="${scm.workspace.dir}"/>
</antcall>
</target>
<!-- For Module1 implementation End -->

以上代码通过参数的方式把定义在 Module1_RTC.properties 里面的信息传入了模版 target。对于获取新代码的操作,一是要获取新的 Baseline,然后再装载到本地,为了调用方便可以再加上外覆 target 来包装操作:

<!—- Get new code by baseline-->
<target name="loadnew">
<sequential>
<delete dir="${scm.workspace.dir}" />
<mkdir dir="${scm.workspace.dir}" />
<antcall target="ws.update.module1" />
<antcall target="ws.load.module1" />
</sequential>
</target>

最后关于 RTC 的登录和登出,用以下的 Ant targets 来实现:

<!-- For RTC login -->
<target name="loginRTC" >
<echo message="Login to RTC" />
<exec executable="${scm.tool.dir}\scm.exe" failonerror="true" logError="true"
vmlauncher="false" append="true" >
<arg line="login -r ${rtc.uri} -u ${rtc.usrname} -P ${rtc.pwd} -n ${rtc.nickname}"/>
</exec>
</target>

<!-- For RTC logout -->
<target name="logoutRTC">
<exec executable="${scm.tool.dir}\scm.exe" failonerror="true" logError="true"
vmlauncher="false" append="true" >
<arg line ="logout -r ${rtc.nickname}" />
</exec>
</target>

这样,关于 RTC 的访问 Ant 脚本和其所需要的属性文件就基本实现了。下面继续讨论 WMB 命令组织调用的 Ant 脚本编写。

WMB 命令脚本

关于 WMB 的命令脚本,根据前面章节的讲解也是可以分为一个 WMB 的构建 XML 文件,一份该构建文件所需的属性文件;为了清晰的设计和可维护性考虑,把需要重写的部署描述符属性单独列到一份文件中,共三个文件。

WMB 脚本属性文件

该文件需要包含构建和部署的 WMB 项目信息,以及目标 broker 服务器和指定的执行组。根据示例项目 ABC 的设定,这个名为 Module1_build.properties 的属性文件包含以下内容:

#Ant makefiles dir
tool.dir=C:/ABC_Ant/SIT/
buildbase.dir=${tool.dir}/Module1

#bar and log files dir
build.dir=${buildbase.dir}/bars
logfiles.dir=${buildbase.dir}/log
logfile.name=${logfiles.dir}/output.log
app.name=BFE_ABC_Module1

#Source Code workspace
workspace.dir=${buildbase.dir}/workspace
source_location=${workspace.dir}

#MB7 installation home
mb7.info.prof=${tool.dir}/sys.properties

#SIT Broker information
brokerfile.sit.file=${broker.info.dir}/ABC_SIT.broker
module1.eg.name= EG_Module1

#ABC projects definition
module1.local.ws=${workspace.dir}
module1.projects.name= MsgFlowProj1 MsgFlowProj2 MsgSetProj1 MsgSetProj2
module1.mf.proj.pattern=MsgFlowProj*/**/*.msgflow
module1.ms.proj.pattern=MsgSetProj*/**/*.mset
module1.bar.name=${build.dir}/ABC_Module1_Bar.bar
module1.bar.properties=ABC_Module1_bar.properties

需要一提的是,在 module1.project.name 这个属性中,所有用于示例项目 Module1 的工程名字在这里全部给出,并用空格分割。另外可以看出这里用于指定消息流的属性 module1.mf.proj.pattern 和字典信息属性 module1.ms.proj.pattern 是两个带通配符的模式值,这样设计的好处在于,当模块项目扩展时能最大限度的保证此脚本的重用性。具体的使用将在后面加以进一步解释。

部署描述符覆写属性文件

针对消息流里的某些节点的属性,例如 Compute 的 Data source 或是 Trace 的 File path,在部署的时候需要修改为适合部署环境的值。在本例中,假设 MsgFlowProj1 项目中的 MyABC_flow1 消息流有一个 Trace 节点需要修改路径,然后在 MsgFlowProj2 项目中有一个 Compute 节点需要修改数据源名称。为此,我们建立一个 Module1_bar.properties 的属性文件以维护此描述符信息:

#For SIT environment
COM.ABC.MyABC_flow1#TraceLog.filePath=/ESBTrace/sit/Module1/Flow1_trace.txt
COM.ABC.MyABC_flow2#AcessData.dataSource=WMBSIT

完成了上面的属性文件,接下来开始创建用于打包和部署 bar 包文件的 Ant 构建脚本。

项目构建部署脚本

相对于操作 RTC 的脚本而言,构建 WMB 项目涉及到访问本地资源的问题。这里的一个难点在于让脚本灵活获取项目路径和 WMB 命令参数要求之间的矛盾。从前面关于 WMB 命令 mqsicreatebar 的使用示例可以看出,所有需要加入构建的项目文件都要在这个命令的参数中给出完整的项目路径,如果把全部的路径固定在脚本中,维护性是很差的,可读性也不强。为了解决这个矛盾,就是刚才我们定义模式(pattern)属性的原因。

建立一个名为 Module1_build.xml 的构建文件,然后为 Module1 创建 Ant 工程信息,并引入上文提及的属性文件:

<?xml version="1.0"?>
<project name="Module1 Broker Operation">
<property file="Module1_build.properties" />
<property file="${mb7.info.prof}" />
...
</project>

首先在这个构建文件中要完成的任务是获取所需要的项目文件:

<!-- Extracts all required broker files from the build workspace -->
<fileset dir="${module1.local.ws}" id="module1.files">
<include name="${module1.mf.proj.pattern}" />
<include name="${module1.ms.proj.pattern}" />
<exclude name="*.metadata/**/*" />
</fileset>

这里用到了 Ant 的 fileset 命令,传入了属性中定义的模式参数,最后可以得到所要构建的项目的所有文件的完整系统路径。但这不是合法的 WMB 构建命令参数。接下来继续使用 Ant 的 pathconvert 命令把 fileset 获取的文件列表进行"裁剪":

<!-- Strip the build directory from the file path -->
<pathconvert pathsep=" " property="module1.objects" refid="module1.files">
<map from="${module.local.ws}/" to="" />
</pathconvert>

这样把项目名称之前的目录信息取掉,便得到了所需的参数项目文件列表信息,并存放于 module1.objects 这个 Ant 属性里面。接下来就可以开始创建构建和部署的 Ant 任务了。

在这个构建文件中创建以下三个 Ant 的 target 作为调用的模版,分别用于构建,覆写属性和部署:

<!-- ******* TEMPLATE START ******** -->
<!-- Target to build the broker archive using mqsicreatebar -->
<target name="mqsicreatebar.build_bar.template">
<echo message="Building Broker Archive file : ${_bar.name} " />
<echo message="With the objects: ${_build.objects}" />
<exec executable="${broker.base}\mqsicreatebar.exe" failonerror="true"
logError="true" vmlauncher="false" append="true" error="${logfile.name}"
output="${logfile.name}">
<arg line="-data ${_workspace.dir}" />
<arg line="-b ${_bar.name}" />
<arg line="-p ${_projects.name}" />
<arg line="-o ${_build.objects}" />
</exec>
<echo message="Completed building Broker Archive file - ${_bar.name} " />
</target>

<!-- Target to override bar properties -->
<target name="mqsicreatebar.override_bar.template">
<echo message=" -- Changing bar properties... -- " />
<exec executable="${broker.base}\mqsiapplybaroverride.exe" failonerror="true"
logError="true" vmlauncher="false" append="true" error="${logfile.name}"
output="${logfile.name}">
<arg line="-b ${_bar.name}" />
<arg line="-p ${_bar.properties}" />
</exec>
<echo message="Completed ovrriding Broker Archive file properties - ${_bar.name} "
/>
</target>

<!-- Target to deploy bar file to broker -->
<target name="mqsicreatebar.autodeploy.template">
<echo message="Auto deploy to broker: ${_bar.name} " />
<exec executable="${mqsi.home}\mqsideploy.exe" spawn="false" failonerror="true"
logError="true" vmlauncher="false" append="false" error="${logfile.name}"
output="${logfile.name}">
<arg line="-n ${_broker.prof.file}" />
<arg line="-e ${_eg.name}" />
<arg line="-a ${_bar.name}" />
<arg line="-m -w 1000" />
</exec>
<echo message="Completed deploying Broker Archive file - ${_bar.name} " />
</target>
<!-- ******* TEMPLATE END ******** -->

有了以上三个模版 target,接下来就创建针对 Module1 的 Ant 任务以传入在属性文件中定义好的信息:

<!--Task to create bar file -->
<target name="build" description="">
<sequential>
<antcall target="mqsicreatebar.build_bar.template" >
<param name="_bar.name" value="${module1.bar.name}"/>
<param name="_build.objects" value="${module1.objects}"/>
<param name="_workspace.dir" value="${module1.local.ws}"/>
<param name="_projects.name" value="${module1.projects.name}"/>
</antcall>
<antcall target="override" />
</sequential>
</target>

<!-- Override BAR file properties -->
<target name="override" description="">
<antcall target="mqsicreatebar.override_bar.template" >
<param name="_bar.name" value="${module1.bar.name}"/>
<param name="_bar.properties" value="${module1.bar.properties}"/>
</antcall>
</target>

<!-- Deploy bar file to SIT -->
<target name="deploy.sit" description="">
<antcall target="mqsicreatebar.autodeploy.template" >
<param name="_bar.name" value="${module1.bar.name}"/>
<param name="_broker.prof.file" value="${brokerfile.sit.file}"/>
<param name="_eg.name" value="${module1.eg.name}"/>
</antcall>
</target>

在 build 这个 target 里,是顺序的调用了构建 bar 包的模版 target 和覆写属性的 target,所以生成的 bar 包文件就是已经达到可以部署的要求。

小结

至此已完成主要的 Ant 脚本设计和编写。回顾这一章讨论的内容,针对示例 ABC 项目的 Module1 应该完成如下脚本和属性文件:

sys.properties:存放 RTC 信息,WMB 和 SCM 工具路径信息

Module1_RTC.properties:保存相关项目模块的 RTC 结构信息

Module1_RTC.xml:对于 RTC 的访问和操作的 Ant 任务

Module1_build.properties:有关需要构建模块的项目具体信息,服务器信息以及执行组

Module1_bar.properties:存放需要覆写的可配置部署描述符属性集合

Module1_build.xml:调用 WMB 的命令以自动构建和部署指定项目

关于 Ant 任务的调用各个项目有不同的规划,本文也分享一种验证过的实施方案,将在下面的维护和扩展讨论章节中提及。

实施、维护和扩展讨论

有关实施

这套工具的开发最初应该有开发人员负责,并提交给开发组长来验证,然后提交到 RTC 来做版本控制。开发团队可以写文档,或现场协助部署人员安装好软件,并下载可用的自动部署工具脚本文件。

在使用这套工具的时候,首先开发组长应该对 Baseline 的提交负责,并只会部署人员 Baseline 的名称。从测试的结果来看,该 Baseline 不能包含空格,否则工具会视为无效的基线名称。部署人员得到需要部署的部件极其 Baseline 名称后,动手在 Module1_RTC.properties 里找到 rtc.module1.deploy.baseline 属性,替换属性值为需要的 Baseline。

在把自动脚本递交给部署人员之前,再建立一些简单的批处理文件作为工具入口程序,从实践上看是更有效率的方式。例如在本例的 C: \ABC_Ant\SIT\Module1 目录中,再建立一个名为 build.bat 的批处理文件,其内容可以包含如下代码:

@ECHO OFF
IF "%1" == "" goto err
IF "%1" == "login" goto login
IF "%1" == "logout" goto logout
IF "%1" == "createWS" goto create
IF "%1" == "load" goto load
IF "%1" == "bar" goto buildbar
IF "%1" == "deploySIT" goto deploysit
goto err

:login
ant –buildfile Module1_RTC.xml loginRTC
goto end

:logout
ant –buildfile Module1_RTC.xml logoutRTC
goto end

:create
ant -buildfile Module1_RTC.xml ws.create.module1
goto end

:load
ant -buildfile Module1_RTC.xml loadnew
goto end

:buildbar
ant -buildfile Module1_build.xml build
goto end

:deploysit
ant -buildfile Module1_build.xml deploy.sit
goto end

:err
ECHO ---------------------------------------------------
ECHO Please use the following parameter:
ECHO 1. login : to login RTC
ECHO 2. Logout: to logout RTC
ECHO 3. createWS : to create workspace in RTC
ECHO 4. load : to load projects from RTC
ECHO 5. bar : to build the projects into bar file
ECHO 6. deploySIT : to deploy bar file to SIT server
ECHO ---------------------------------------------------
goto end

:end
ECHO End of command.

有了这个入口程序,当部署人员更新了 Baseline 的信息以后,只需要在工作目录依次执行:

build login
build createWS
build load
build bar

就可以得到所需要的 bar 包文件,然后再执行 :

build deploySIT

就可以把这个 bar 包部署到指定的 broker 服务器的工作流,最后执行:

build logout

以退出 RTC 连接,完成工作。需要注意的是:build createWS 应该只在首次运行时使用,以后不用也不能再运行此命令,否则需要手动删除冗余的重名 Workspace 以确保 RTC 匹配成功。

关于维护

随着项目的发展,维护是必不可少的。目前这个示例项目比较理想简单;但是在真实项目中可能遇到例如客户要求增加新的测试服务器,更改 / 合并执行组等等,这个时候开发团队应该在开发完成后第一时间修改响应的脚本,通常这类修改工作量很小。

当项目进入下一阶段,比如 UAT 抑或是准备到 PROD 环境时,从实践的结果看维护多套脚本要比在一套脚本上增加新的 target 更快捷也更容易维护。这就是本文所讨论的 Ant 脚本都使用了"模版模式"的原因。当有 UAT 阶段需求或是最后项目上线时的 PROD 部署,只需要拷贝已经完成的 SIT 部署脚本,将有 SIT 特征的参数替换为 UAT 或 PROD 参数即可。模版的使用保证了增加新一套脚本的便捷性,这在进度较紧的项目中能省去不少时间。

值得提醒的是有关于部署人员在 RTC 账户里创建了重复 Workspace 的问题。当 build createWS 命令被第二次运行时,重复的 Workspace 会被创建。这个时候需要使用之前介绍 RTC SCM 工具使用时所提到过的显示和删除工作空间的命令。一般而言,可以建立一个名为 cleanws.bat 内容如下的批处理文件以简化调用:


@ECHO OFF
IF "%1" == "" goto err
IF "%1" == "list" goto listws
IF "%1" == "delete" goto delete

:listws
scm list workspaces -r abcRobot
goto end

:delete
ECHO Start to delete the workspace with no. %2
scm workspace delete -r mbbrtc %2
ECHO Workspace has been deleted.
goto listws

:err
ECHO Please use the following parameter:
ECHO 1. list : to list all the workspaces
ECHO 2. delete (no.) to delete the specified workspace.
goto end

:end
ECHO End of command.

出现重复 Workspace 以后,部署人员通过这个批处理只需要执行:

cleanws list

就可以看到有重名的 Workspace 的 ID,比如显示发现 1020 和 1021 两个 Workspace 是同样的名字,则删除任意一个均可。即,运行:

cleanws delete 1021

此重复的 Workspace 即可被删除,接下来的脚本便可正确运行。

扩展讨论

在真实的项目中,可能出现的情况和需求各种各样,在此谨举个例子抛砖引玉。

注意到目前为止,我们所讨论的自动部署功能在发布 bar 包时都会先清空目标执行组下的所有消息流,然后再把 bar 包部署上去。这样可能会导致两个问题:1. 共享执行组的已有工作流可能会被错误的删除;2. 无法实现部分部署。

导致这个问题的原因是在脚本调用 mqisideploy 命令的时候,有一个 -m 的参数用于控制是否清除已有消息流。这样只需要增加一个 target 不使用此参数即可:

<!-- Patch flow or messageset without cleaning -->
<target name="mqsicreatebar.autopatch.template">
<echo message="Auto deploy to broker: ${_bar.name} " />
<exec executable="${mqsi.home}\mqsideploy.exe" spawn="false" failonerror="true"
logError="true" vmlauncher="false" append="false" error="${errfile.name}"
output="${logfile.name}">
<arg line="-n ${_broker.prof.file}" />
<arg line="-e ${_eg.name}" />
<arg line="-a ${_bar.name}" />
<arg line="-w 1000" />
</exec>
<echo message="Completed deploying Broker Archive file - ${_bar.name} " />
</target>

相应的增加调用时候的外覆 target,就可以实现补丁功能,在此就不具体罗列了。

局限性

对于用 RTC 来做项目代码版本管理,基于不同的项目可能有不同的管理方式。本方案所探讨的这种实践,实际上是在"以 Stream 管理项目,以 Baseline 来管理版本"的一种 RTC 实施方案。对于有些项目而言,RTC 的实施是"以 Stream 来管理版本的",也就是为每一个版本创建一个 Stream。针对此种 RTC 管理方式,目前所探讨的方案不能立刻使用,因为版本获取上略微有所不同。

其实基于 Stream 为版本管理在版本获取上更为简单。一种变通的方法则是,把本方案里关于"替换 Baseline"的部分改为"获取所有最新"。实现上,用 SCM 的 accept 命令来代替这里的 workspace replace-components 即可。其 Ant 的 target 如:

<target name="ws.accept.template">
<exec executable="${scm.tool.dir}\scm.exe" failonerror="true" logError="true"
vmlauncher="false" append="true" >
<arg line="accept -r ${rtc.nickname}" />
<arg line="-s ${_rtc.strname}" />
<arg line="-t ${_rtc.wsname}" />
</exec>
</target>

其他细节和改动就不在这里赘述了。

结束语

关于 WMB 项目的自动部署,本文介绍了有关 RTC SCM 工具和 WMB 命令行的一些必要知识,同时展示了自动部署方案的实现。该方案源自于实际项目经验,具有很强的可操作性,随着项目的实施,能正规化 WMB 项目的开发流程,同时提高生产效率。

相关文章

每日构建解决方案
如何制定有效的配置管理流程
配置管理主要活动及实现方法
构建管理入门
相关文档

配置管理流程
配置管理白皮书
CM09_C配置管理标准
使用SVN进行版本控制
相关课程

配置管理实践
配置管理方法、工具与应用
多层次集成配置管理
产品发布管理
 
分享到
 
 
   


软件配置管理的问题、目的
软件配置管理规范
CQWeb 7.1性能测试与调优指南
为什么需要使用ClearCase
ClearCase与RTC的集成
利用ClearQuest 进行测试管理
更多...   


产品发布管理
配置管理方法、实践、工具
多层次集成配置管理
使用CC与CQ进行项目实践
CVS与配置管理
Subversion管理员


配置管理实践(从组织级到项目级)
通号院 配置管理规范与应用
配置管理日构建及持续集成
丹佛斯 ClearCase与配置管理
中国移动 软件配置管理
中国银行 软件配置管理
天津华翼蓝天科技 配置管理与Pvcs