您的位置:首页 > 其它

【Hello CC.NET】巧用模板简化配置

2013-08-24 14:16 351 查看
  从 《【Hello CC.NET】CC.NET 实现自动化集成》 到 《【Hello CC.NET】自动化发布时 Web.config 文件维护》 ,大神在评论里提到的方案还没有一一去研究对比,调研的 deadline 已经逼近,CC.NET 的落地提上日程。

  经过两周的努力,终于成功部署了两个项目,由于两个项目的人员配置/开发流程/项目架构不一样,部署的方案也有些差异。过程中碰到这样那样的坑,都是用最快想到的笨方法填坑,然后继续往下走。落地的姿势并不完美,但总算有了一些看得到的成果。   

  落地面临的第一个问题是,ccnet.config 配置比较繁复:太多的 hardcode;相同的 xml 节点内容比较多,尤其在配置多个项目的时候,策略变更时,需要改动的地方比较多。本文将讲述 ccnet.config 模板化的思路。

  

  目标

提取全局性的配置,避免到处 Hardcode

简化各个节点的配置,便于维护

  1.全局变量

<cc:define CIWebSite="http://vm-caihaihua/CCNET/"/>
<cc:define CIDirectory="C:\CI\"/>
<cc:define MsBuildPath="C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"/>
<cc:define MsTestPath="C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe"/>
<cc:define SVNPath="C:\Program Files (x86)\VisualSVN Server\bin\svn.exe"/>
<cc:define FCReplacerPath="C:\CI\Tools\FCReplacer.exe"/>
<cc:define DFCopierPath="C:\CI\Tools\DFCopier.exe"/>
<cc:define name="MsBuildXmlLogger">
<logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</cc:define>


  

变量名称描述
CIWebSiteCC.NET配套网站的地址http://vm-caihaihua/CCNET/
CIDirectory工作目录C:\CI\
MsBuildPathMsBuild 程序的地址C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
MsTestPathMsTest 程序的地址C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe
SVNPathSvn 程序的地址C:\Program Files (x86)\VisualSVN Server\bin\svn.exe
FCReplacerPathFCReplacer 程序的地址C:\CI\Tools\FCReplacer.exe
DFCopierPathDFCopier 程序的地址C:\CI\Tools\DFCopier.exe
MsBuildXmlLogger日志 Logger 的配置<logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
 

  2.默认值

<!-- 默认配置 -->
<cc:define QueuePriority="1"/>
<cc:define KeepLastXBuilds="300"/>
<!-- Email 相关 -->
<cc:define EmailDomain="company.com"/>
<cc:define EmailSendHost="smtp.live.com"/>
<cc:define EmailSendPort="25"/>
<cc:define EmailUseSSL="FALSE"/>
<cc:define EmailSendUser="ci"/>
<cc:define EmailSendPassword="********"/>
<cc:define CIEmailUser="ci"/>
<cc:define PMEmailUser="pm_1"/>
<cc:define name="EmailTesterList">
<user group="tester" name="tester_1" address="tester_1@$(EmailDomain)"/>
<user group="tester" name="tester_2" address="tester_2@$(EmailDomain)"/>
</cc:define>
<!-- Trigger 相关 -->
<cc:define ModificationTriggerIntervalSeconds="300"/>
<cc:define ModificationDelaySeconds="60"/>
<cc:define ProjectTriggerIntervalSeconds="30"/>
<cc:define ProjectTriggerStatus="Success"/>
<cc:define DailyBuildTriggerTime="18:00"/>
<!-- SVN 相关 -->
<cc:define SVNUsername="ci"/>
<cc:define SVNPassword="********"/>
<cc:define SvnCleanCopy="FALSE"/>
<cc:define name="SourceControl">
</cc:define>
<!-- Task 相关 -->
<cc:define TestTimeout="1800"/>
<cc:define CopyTimeout="60"/>
<cc:define ReplaceTimeout="60"/>
<cc:define BuildConfiguration="DEBUG"/>
<cc:define PublishConfiguration="RELEASE"/>


    

变量名称描述
QueuePriority项目在队列中的优先级1
KeepLastXBuilds保留最后的 X 个构建结果300
EmailDomain公司邮箱域名company.com
EmailSendHost邮箱服务器地址smtp.live.com
EmailSendPort邮箱服务器端口25
EmailUseSSL是否启用 SSLTRUE
EmailSendUser发送邮箱的帐号ci
EmailSendPassword发送邮箱账户的密码******
CIEmailUserCI 维护人员的邮箱账户ci
PMEmailUser部门经理的邮箱账户pm_1
EmailTesterList测试人员邮箱列表<user group="tester" name="tester_1" address="tester_1@$(EmailDomain)"/>

<user group="tester" name="tester_2" address="tester_2@$(EmailDomain)"/>

ModificationTriggerIntervalSeconds源代码监测的频率(秒)300
ModificationDelaySeconds源代码变更触发构建任务的延迟时间(秒)60
ProjectTriggerIntervalSeconds依赖项目的状态监测频率(秒)30
ProjectTriggerStatus依赖项目的设定状态SUCCESS
DailyBuildTriggerTime每日构建的时间点18:00
SVNUsernameSVN 帐号ci
SVNPasswordSVN 帐号的密码******
SvnCleanCopy下载源代码前是否先删除本地源代码FALSE
SourceControl源代码管理的配置
TestTimeout运行测试的超时时间(秒)1800
CopyTimeout拷贝文件的超时时间(秒)60
ReplaceTimeout替换文件内容的超时时间(秒)60
BuildConfiguration编译的配置DEBUG
PublishConfiguration发布网站的配置RELEASE
  

  

  3.通知模板

<cc:define name="EmailPublisher">
<email mailhost="$(EmailSendHost)" mailport="$(EmailSendPort)"
mailhostUsername="$(EmailSendUser)@$(EmailDomain)" mailhostPassword="$(EmailSendPassword)"
from="$(EmailSendUser)@$(EmailDomain)"
useSSL="$(EmailUseSSL)" includeDetails="true">
<!--邮件标题配置-->
<subjectPrefix>$(EmailSubject)</subjectPrefix>
<subjectSettings>
<!-- Success/Broken/StillBroken/Fixed/Exception-->
<subject buildResult="Success" value="${CCNetProject} Build result"/>
<subject buildResult="Fixed" value="${CCNetProject} Build result"/>
<subject buildResult="Broken" value="${CCNetProject} Build result"/>
<subject buildResult="StillBroken" value="${CCNetProject} Build result" />
<subject buildResult="Exception" value="${CCNetProject} Build result" />
</subjectSettings>
<!--收件人配置-->
<converters>
<rcgexConverter find="$" replace="@$(EmailDomain)"/>
</converters>
<modifierNotificationTypes>
<notificationType>Failed</notificationType>
<notificationType>Fixed</notificationType>
</modifierNotificationTypes>
<users>
<user group="pm" name="$(PMEmailUser)" address="$(PMEmailUser)@$(EmailDomain)"/>
<user group="ci" name="$(CIEmailUser)" address="$(CIEmailUser)@$(EmailDomain)"/>
<user group="tl" name="$(TeamLeader)" address="$(TeamLeader)@$(EmailDomain)"/>
<cc:EmailTesterList/>
</users>
<groups>
<group name="pm">
<notifications>
<!--Always/Success/Change/Fixed/Failed/Exception -->
<notificationType>Change</notificationType>
</notifications>
</group>
<group name="ci">
<notifications>
<notificationType>Exception</notificationType>
</notifications>
</group>
<group name="tl">
<notifications>
<notificationType>Success</notificationType>
<notificationType>Fixed</notificationType>
<notificationType>Failed</notificationType>
</notifications>
</group>
<group name="developer">
<notifications>
<notificationType>Success</notificationType>
<notificationType>Fixed</notificationType>
<notificationType>Failed</notificationType>
</notifications>
</group>
<group name="tester">
<notifications>
<notificationType>Fixed</notificationType>
</notifications>
</group>
</groups>
</email>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
EmailDomain公司邮箱域名company.comN
EmailSendHost邮件服务器的地址smtp.live.comN
EmailSendPort邮件服务器的端口25N
EmailUseSSL是否使用 SSL(取决于邮件服务器的配置)TRUEN
EmailSendUser邮件通知的发送帐号CIN
EmailSendPassword邮件通知的发送帐号的密码******N
PMEmailUser部门经理的邮箱帐号pm_1N
CIEmailUserCI 环境维护人员的邮箱帐号ciN
TeamLeader项目组负责人的邮箱帐号,各个项目组配置不同 Y
EmailSubject邮件通知的前缀 Y
  

  例子:  

<publishers>
<!--邮件通知-->
<cc:EmailPublisher/>
</publishers>


  4.触发器模板

  (1)源代码检测:每隔一段时间检查源代码,如果有变更,则触发构建过程

<!-- Triggers:ModificationTrigger/DailyBuildTrigger/ProjectTrigger-->
<cc:define name="ModificationTrigger">
<!--源码修改触发-->
<intervalTrigger seconds="$(ModificationTriggerIntervalSeconds)" buildCondition="IfModificationExists" />
</cc:define>


  模板变量:

变量名称描述默认值是否必填
ModificationTriggerIntervalSeconds源码监测频率(秒)600N
  

  例子:

<triggers>
<cc:ModificationTrigger/>
</triggers>


  (2)每日构建:每天到设定的时间点触发构建过程

<cc:define name="DailyBuildTrigger">
<!--每日构建-->
<scheduleTrigger time="$(DailyBuildTriggerTime)" buildCondition="ForceBuild">
<weekDays>
<!--<weekDay>Sunday</weekDay>-->
<weekDay>Monday</weekDay>
<weekDay>Tuesday</weekDay>
<weekDay>Wednesday</weekDay>
<weekDay>Thursday</weekDay>
<weekDay>Friday</weekDay>
<!--<weekDay>Saturday</weekDay>-->
</weekDays>
</scheduleTrigger>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
DailyBuildTriggerTime每日构建的时间点18:00N
  

  例子:

<triggers>
<cc:DailyBuildTrigger/>
</triggers>


  (3)项目依赖:每隔一段时间检查指定项目的构建结果,如果等于指定值,则触发构建过程

<cc:define name="ProjectTrigger">
<projectTrigger serverUri="tcp://vm-caihaihua:21234/CruiseManager.rem" project="$(ListenToProject)">
<triggerStatus>$(ProjectTriggerStatus)</triggerStatus>
<innerTrigger type="intervalTrigger" seconds="$(ProjectTriggerIntervalSeconds)" buildCondition="ForceBuild" />
<!--<triggerFirstTime>True</triggerFirstTime>-->
</projectTrigger>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
ProjectTriggerIntervalSeconds监测依赖项目的频率(秒)30N
ProjectTriggerStatus设定的构建结果SUCCESSN
ListenToProject依赖的项目名称Y
  

  例子:

<triggers>
<cc:ProjectTrigger ListenToProject="TestProject-Servcies"/>
</triggers>


  5.源代码管理模板

<!-- SourceControl: SVNSourceControl -->
<cc:define name="SVNSourceControl">
<sourcecontrol type="svn">
<trunkUrl>$(SVNTrunkURL)</trunkUrl>
<executable>$(SVNPath)</executable>
<workingDirectory>$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<username>$(SVNUsername)</username>
<password>$(SVNPassword)</password>
<revert>True</revert>
<cleanCopy>$(SvnCleanCopy)</cleanCopy>
<cleanUp>True</cleanUp>
<deleteObstructions>True</deleteObstructions>
</sourcecontrol>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
SVNUsernameSvn 账户,需要项目的 checkout 权限
ciN
SVNPasswordSvn 账户的密码
******N
SvnCleanCopy下载源代码前是否先删除本地源代码FALSEN
SVNTrunkURL项目的 Svn 路径
Y
  例子:

<project>
<cc:SVNSourceControl SVNTrunkURL="https://vm-caihaihua/svn/testproject/services/trunk/"
SvnCleanCopy="False"/>
</project>


  6.任务模板

  (1)文件内容替换

  

<cc:define name="Replace">
<exec>
<executable>$(FCReplacerPath)</executable>
<buildArgs>
<cc:Files/>
<cc:Rules/>
</buildArgs>
<buildTimeoutSeconds>$(ReplaceTimeout)</buildTimeoutSeconds>
<successExitCodes>0</successExitCodes>
</exec>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
ReplaceTimeout替换的超时时间(秒)60N
Files需要替换的文件列表Y
Rules替换的规则
Y
  例子:

<tasks>
<!-- Config -->
<cc:Replace>
<cc:define name="Files">
/file=$(CIDirectory)$(WorkingDirectory)WcfService\Web.config
/file=$(CIDirectory)$(WorkingDirectory)ManagerTest\App.config
/file=$(CIDirectory)$(WorkingDirectory)WcfServiceTest\App.config
</cc:define>
<cc:define name="Rules">
/from=Catalog=(?![^;\s']*_log[;\s']+)(=?[^;\s']*)/to=Catalog=testproject_trunk
/from=Source=(=?.*?)(=?[;\s']+)/to=Source=vm-caihaihua$2
/from=http://(=?[^\/]+)/(=?\w+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$2.svc
/from=http://(=?.*?)/(?!SSO)(=?[^\/]+)/(=?\w+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$3.svc
/from=http://(=?.*?)/SSO/(=?\w+).svc/to=http://vm-caihaihua/testproject_trunk_ci/SSO/$2.svc
</cc:define>
</cc:Replace>
</tasks>


  (2)项目编译

<cc:define name="Build">
<msbuild>
<executable>$(MsBuildPath)</executable>
<buildArgs>/t:build /p:configuration=$(BuildConfiguration)</buildArgs>
<cc:MsBuildXmlLogger/>
<workingDirectory>$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<projectFile>$(SolutionPath)</projectFile>
</msbuild>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
BuildConfiguration编译的配置DEBUGN
SolutionPath项目的相对路径Y
  例子:

<tasks>
<!-- Build -->
<cc:Build SolutionPath="TestProjectService.sln"/>
</tasks>


  (3)网站发布

  

<cc:define name="Publish">
<msbuild>
<executable>$(MsBuildPath)</executable>
<workingDirectory>$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<projectFile>$(SolutionPath)</projectFile>
<buildArgs>
/t:ResolveReferences;Compile
/t:_CopyWebApplication
/p:Configuration=$(PublishConfiguration)
/p:WebProjectOutputDir=$(CIDirectory)$(To)
/p:OutputPath=$(CIDirectory)$(To)\bin
</buildArgs>
</msbuild>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
PublishConfiguration编译的配置RELACEN
SolutionPath项目的相对路径Y
To目标文件夹的相对路径Y
  例子:

<tasks>
<!-- Publish -->
<cc:Publish SolutionPath="WcfService\WcfService.csproj"
To="$(PublishDirectory)WcfService" />
</tasks>


  (4)文件拷贝

<cc:define name="Copy">
<exec>
<executable>$(DFCopierPath)</executable>
<buildArgs>
/from=$(CIDirectory)$(From)
/to=$(CIDirectory)$(To)
</buildArgs>
<buildTimeoutSeconds>$(CopyTimeout)</buildTimeoutSeconds>
<successExitCodes>0</successExitCodes>
</exec>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
CopyTimeout拷贝的超时时间(秒)60N
From需要拷贝的文件夹的相对路径Y
To目标文件夹的相对路径Y
  例子:

<tasks>
<!-- Copy-->
<cc:Copy From="$(WorkingDirectory)WcfService
To="$(PublishDirectory)WcfService"/>
</tasks>


  (5)自动化测试

<cc:define name="RunTest">
<exec>
<executable>$(MSTestPath)</executable>
<baseDirectory>$(CIDirectory)$(WorkingDirectory)</baseDirectory>
<buildArgs>/testcontainer:$(TestContainerPath)</buildArgs>
<buildTimeoutSeconds>$(TestTimeout)</buildTimeoutSeconds>
</exec>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
TestTimeout测试的超时时间(秒)1800N
TestContainerPath测试列表的相对路径Y
  例子:

<tasks>
<!--Run Test-->
<cc:RunTest TestContainerPath="ManagerTest\bin\Debug\ManagerTest.dll"/>
<cc:RunTest TestContainerPath="WcfServiceTest\bin\Debug\WcfServiceTest.dll"/>
</tasks>


  7.项目模板

<cc:define name="Project">
<project name="$(ProjectName)" queue="$(Queue)" queuePriority="$(QueuePriority)">
<webURL>$(CIWebSite)server/local/project/$(ProjectName)/ViewProjectReport.aspx</webURL>
<!--标签-->
<labeller type="dateLabeller"/>
<artifactDirectory>$(CIDirectory)$(ArtifactDirectory)</artifactDirectory>
<!--项目的目录-->
<workingDirectory >$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<!--自动运行时间间隔-->
<triggers>
<cc:TriggerList/>
</triggers>
<!--对源码修改延迟处理时间间隔-->
<modificationDelaySeconds>$(ModificationDelaySeconds)</modificationDelaySeconds>
<maxSourceControlRetries>5</maxSourceControlRetries>
<!--源代码管理(SVN)-->
<cc:SourceControl/>
<state type="state" directory="$(CIDirectory)$(StateDirectory)"/>
<publishers>
<modificationHistory onlyLogWhenChangesFound="true"/>
<statistics/>
<xmllogger/>
<artifactcleanup cleanUpMethod="KeepLastXBuilds" cleanUpValue="$(KeepLastXBuilds)" />
<!--邮件通知-->
<cc:EmailPublisher/>
</publishers>
<tasks>
<cc:TaskList/>
</tasks>
</project>
</cc:define>


  模板变量:

变量名称描述默认值是否必填
QueuePriority项目在队列里的优先级1N
KeepLastXBuilds保存最后的 X 个构建结果300N
ModificationDelaySeconds源代码变更触发构建任务的延迟时间60N
SourceControl源代码配置N
Queue项目从属的队列Y
ProjectName项目名称Y
StateDirectory构建日志的保存目录Y
WorkingDirectory项目的工作目录,即源代码的保存路径Y
ArtifactDirectory构建结果的存放目录Y
TriggerList触发器配置列表Y
TaskList任务列表Y
  

  例子:

  TestProject 包括 Wcf Service 项目和 AdminWeb 项目

  (1)Wcf Service

  a. 自动化部署

自动获取源代码

源代码监测及每日构建

修改配置文件中的数据库连接字符串及服务引用地址

Debug 编译整个解决方案

Release 发布 Service 到 CI 环境

  b. 自动化测试

与a使用同一个工作目录(即源代码)

监测自动化部署过程,如果成功则触发自动化测试

运行 ManagerTest 和 ServiceTest

  (2) AdminWeb

自动化部署

自动获取源代码

源代码监测及每日构建

修改配置文件中的数据库连接字符串及服务引用地址

Debug 编译整个解决方案

Release 发布 AdminWeb 到 CI 环境

<!-- TestProject: Service 项目 -->
<queue name="TestProject" duplicates="ApplyForceBuildsReAdd" />
<cc:Project ProjectName="TestProject-Servcies"
Queue="TesProjectt"
WorkingDirectory="TestProject\SourceCode\service_trunk\"
ArtifactDirectory="TestProject\Artifact\service\"
StateDirectory="TestProject\State\"
PublishDirectory="TestProject\Publish\"
EmailSubject="[CI-TestProjectService]"
ModificationDelaySeconds="30"
TeamLeader="caihaihua">
<cc:define name="SourceControl">
<cc:SVNSourceControl SVNTrunkURL="https://vm-caihaihua/svn/testproject/services/trunk/"
SvnCleanCopy="False"/>
</cc:define>
<cc:define name="TriggerList">
<cc:ModificationTrigger/>
<cc:DailyBuildTrigger/>
</cc:define>
<cc:define name="TaskList">
<!-- Config -->
<cc:Replace>
<cc:define name="Files">
/file=$(CIDirectory)$(WorkingDirectory)WcfService\Web.config
/file=$(CIDirectory)$(WorkingDirectory)ManagerTest\App.config
/file=$(CIDirectory)$(WorkingDirectory)WcfServiceTest\App.config
</cc:define>
<cc:define name="Rules">
/from=Catalog=(?![^;\s']*_log[;\s']+)(=?[^;\s']*)/to=Catalog=service_trunk_ci
/from=Source=(=?.*?)(=?[;\s']+)/to=Source=localhost$2
/from=http://(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$2.svc
/from=http://(=?.*?)/(?!SSO)(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$3.svc
/from=http://(=?.*?)/SSO/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/SSO/$2.svc
</cc:define>
</cc:Replace>
<!-- Build -->
<cc:Build SolutionPath="TestProjectService.sln"/>
<!-- Publish -->
<cc:Copy From="$(WorkingDirectory)WcfService"
To="$(PublishDirectory)WcfService"/>
</cc:define>
</cc:Project>
<cc:Project ProjectName="TestProjectServcies-Test"
Queue="TestProject"
QueuePriority="2"
WorkingDirectory="TestProject\SourceCode\service_trunk\"
ArtifactDirectory="TestProject\Artifact\test\"
StateDirectory="TestProject\State\"
EmailSubject="[CI-TestProjectServcie-Test]"
ModificationDelaySeconds="30"
TeamLeader="caihaihua">
<cc:define name="TriggerList">
<cc:ProjectTrigger ListenToProject="TestProject-Servcies"/>
</cc:define>
<cc:define name="TaskList">
<!--Run Test-->
<cc:RunTest TestContainerPath="ManagerTest\bin\Debug\ManagerTest.dll"/>
<cc:RunTest TestContainerPath="WcfServiceTest\bin\Debug\WcfServiceTest.dll"/>
</cc:define>
</cc:Project>

<!-- TestProject: AdminWeb 项目 -->
<cc:Project ProjectName="TestProject-AdminWeb"
Queue="TestProject"
WorkingDirectory="TestProject\SourceCode\admin_trunk\"
ArtifactDirectory="TestProject\Artifact\admin\"
StateDirectory="TestProject\State\"
PublishDirectory="TestProject\Publish\"
EmailSubject="[CI-TestProject-AdminWeb]"
TeamLeader="caihaihua">
<cc:define name="SourceControl">
<cc:SVNSourceControl SVNTrunkURL="https://vm-caihaihua/svn/testproject/adminweb/trunk/"/>
</cc:define>
<cc:define name="TriggerList">
<cc:ModificationTrigger/>
<cc:DailyBuildTrigger/>
</cc:define>
<cc:define name="TaskList">
<!-- Config -->
<cc:Replace>
<cc:define name="Files">
/file=$(CIDirectory)$(WorkingDirectory)AdminWeb\Web.config
</cc:define>
<cc:define name="Rules">
/from=http://(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$2.svc
/from=http://(=?.*?)/(?!SSO)(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$3.svc
/from=http://(=?.*?)/SSO/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/SSO/$2.svc
</cc:define>
</cc:Replace>
<!-- Build -->
<cc:Build SolutionPath="AdminWeb.sln"/>
<!-- Publish -->
<cc:Publish SolutionPath="AdminWeb\AdminWeb.csproj"
To="$(PublishDirectory)AdminWeb" />
</cc:define>
</cc:Project>


完整的 ccnet.config:

<cruisecontrol xmlns:cc="urn:ccnet.config.builder">
<!-- 全局配置 -->
<cc:define CIWebSite="http://vm-caihaihua/CCNET/"/>
<cc:define CIDirectory="C:\CI\"/>
<cc:define MsBuildPath="C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"/>
<cc:define MsTestPath="C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe"/>
<cc:define SVNPath="C:\Program Files (x86)\VisualSVN Server\bin\svn.exe"/>
<cc:define FCReplacerPath="C:\CI\Tools\FCReplacer.exe"/>
<cc:define DFCopierPath="C:\CI\Tools\DFCopier.exe"/>
<cc:define name="MsBuildXmlLogger">
<logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</cc:define>

<!-- Publishers:EmailPublisher-->
<cc:define name="EmailPublisher">
<email mailhost="$(EmailSendHost)" mailport="$(EmailSendPort)"
mailhostUsername="$(EmailSendUser)@$(EmailDomain)" mailhostPassword="$(EmailSendPassword)"
from="$(EmailSendUser)@$(EmailDomain)"
useSSL="$(EmailUseSSL)" includeDetails="true">
<!--邮件标题配置-->
<subjectPrefix>$(EmailSubject)</subjectPrefix>
<subjectSettings>
<!-- Success/Broken/StillBroken/Fixed/Exception-->
<subject buildResult="Success" value="${CCNetProject} ${CCNetBuildDate} Build result"/>
<subject buildResult="Fixed" value="${CCNetProject} ${CCNetBuildDate} Build result"/>
<subject buildResult="Broken" value="${CCNetProject} ${CCNetBuildDate} Build result"/>
<subject buildResult="StillBroken" value="${CCNetProject} ${CCNetBuildDate} Build result" />
<subject buildResult="Exception" value="${CCNetProject} ${CCNetBuildDate} Build result" />
</subjectSettings>lo
<!--收件人配置-->
<converters>
<regexConverter find="$" replace="@$(EmailDomain)"/>
</converters>
<modifierNotificationTypes>
<notificationType>Failed</notificationType>
<notificationType>Fixed</notificationType>
</modifierNotificationTypes>
<users>
<user group="pm" name="$(PMEmailUser)" address="$(PMEmailUser)@$(EmailDomain)"/>
<user group="ci" name="$(CIEmailUser)" address="$(CIEmailUser)@$(EmailDomain)"/>
<user group="tl" name="$(TeamLeader)" address="$(TeamLeader)@$(EmailDomain)"/>
<cc:EmailTesterList/>
</users>
<groups>
<group name="pm">
<notifications>
<!--Always/Success/Change/Fixed/Failed/Exception -->
<notificationType>Change</notificationType>
</notifications>
</group>
<group name="ci">
<notifications>
<notificationType>Exception</notificationType>
</notifications>
</group>
<group name="tl">
<notifications>
<notificationType>Success</notificationType>
<notificationType>Fixed</notificationType>
<notificationType>Failed</notificationType>
</notifications>
</group>
<group name="developer">
<notifications>
<notificationType>Success</notificationType>
<notificationType>Fixed</notificationType>
<notificationType>Failed</notificationType>
</notifications>
</group>
<group name="tester">
<notifications>
<notificationType>Fixed</notificationType>
</notifications>
</group>
</groups>
</email>
</cc:define>

<!-- Triggers:ModificationTrigger/DailyBuildTrigger/ProjectTrigger-->
<cc:define name="ModificationTrigger">
<!--源码修改触发-->
<intervalTrigger seconds="$(ModificationTriggerIntervalSeconds)" buildCondition="IfModificationExists" />
</cc:define>
<cc:define name="DailyBuildTrigger">
<!--每日构建-->
<scheduleTrigger time="$(DailyBuildTriggerTime)" buildCondition="ForceBuild">
<weekDays>
<!--<weekDay>Sunday</weekDay>-->
<weekDay>Monday</weekDay>
<weekDay>Tuesday</weekDay>
<weekDay>Wednesday</weekDay>
<weekDay>Thursday</weekDay>
<weekDay>Friday</weekDay>
<!--<weekDay>Saturday</weekDay>-->
</weekDays>
</scheduleTrigger>
</cc:define>
<cc:define name="ProjectTrigger">
<projectTrigger serverUri="tcp://Server12:21234/CruiseManager.rem" project="$(ListenToProject)">
<triggerStatus>$(ProjectTriggerStatus)</triggerStatus>
<innerTrigger type="intervalTrigger" seconds="$(ProjectTriggerIntervalSeconds)" buildCondition="ForceBuild" />
<!--<triggerFirstTime>True</triggerFirstTime>-->
</projectTrigger>
</cc:define>

<!-- SourceControl: SVNSourceControl -->
<cc:define name="SVNSourceControl">
<sourcecontrol type="svn">
<trunkUrl>$(SVNTrunkURL)</trunkUrl>
<executable>$(SVNPath)</executable>
<workingDirectory>$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<username>$(SVNUsername)</username>
<password>$(SVNPassword)</password>
<revert>True</revert>
<cleanCopy>$(SvnCleanCopy)</cleanCopy>
<cleanUp>True</cleanUp>
<deleteObstructions>True</deleteObstructions>
</sourcecontrol>
</cc:define>

<!-- Tasks: Replace/Build/Publish/Copy/RunTest -->
<cc:define name="Replace">
<exec>
<executable>$(FCReplacerPath)</executable>
<buildArgs>
<cc:Files/>
<cc:Rules/>
</buildArgs>
<buildTimeoutSeconds>$(ReplaceTimeout)</buildTimeoutSeconds>
<successExitCodes>0</successExitCodes>
</exec>
</cc:define>
<cc:define name="Build">
<msbuild>
<executable>$(MsBuildPath)</executable>
<buildArgs>/t:build /p:configuration=$(BuildConfiguration)</buildArgs>
<cc:MsBuildXmlLogger/>
<workingDirectory>$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<projectFile>$(SolutionPath)</projectFile>
</msbuild>
</cc:define>
<cc:define name="Publish">
<msbuild>
<executable>$(MsBuildPath)</executable>
<workingDirectory>$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<projectFile>$(SolutionPath)</projectFile>
<buildArgs>
/t:ResolveReferences;Compile
/t:_CopyWebApplication
/p:Configuration=$(PublishConfiguration)
/p:WebProjectOutputDir=$(CIDirectory)$(To)
/p:OutputPath=$(CIDirectory)$(To)\bin
</buildArgs>
</msbuild>
</cc:define>
<cc:define name="Copy">
<exec>
<executable>$(DFCopierPath)</executable>
<buildArgs>
/from=$(CIDirectory)$(From)
/to=$(CIDirectory)$(To)
</buildArgs>
<buildTimeoutSeconds>$(CopyTimeout)</buildTimeoutSeconds>
<successExitCodes>0</successExitCodes>
</exec>
</cc:define>
<cc:define name="RunTest">
<exec>
<executable>$(MSTestPath)</executable>
<baseDirectory>$(CIDirectory)$(WorkingDirectory)</baseDirectory>
<buildArgs>/testcontainer:$(TestContainerPath)</buildArgs>
<buildTimeoutSeconds>$(TestTimeout)</buildTimeoutSeconds>
</exec>
</cc:define>

<!-- 通用配置(模板) -->
<cc:define name="Project">
<project name="$(ProjectName)" queue="$(Queue)" queuePriority="$(QueuePriority)">
<webURL>$(CIWebSite)server/local/project/$(ProjectName)/ViewProjectReport.aspx</webURL>
<!--标签-->
<labeller type="dateLabeller"/>
<artifactDirectory>$(CIDirectory)$(ArtifactDirectory)</artifactDirectory>
<!--项目的目录-->
<workingDirectory >$(CIDirectory)$(WorkingDirectory)</workingDirectory>
<!--自动运行时间间隔-->
<triggers>
<cc:TriggerList/>
</triggers>
<!--对源码修改延迟处理时间间隔-->
<modificationDelaySeconds>$(ModificationDelaySeconds)</modificationDelaySeconds>
<maxSourceControlRetries>5</maxSourceControlRetries>
<!--源代码管理(SVN)-->
<cc:SourceControl/>
<state type="state" directory="$(CIDirectory)$(StateDirectory)"/>
<publishers>
<modificationHistory onlyLogWhenChangesFound="true"/>
<statistics/>
<xmllogger/>
<artifactcleanup cleanUpMethod="KeepLastXBuilds" cleanUpValue="$(KeepLastXBuilds)" />
<!--邮件通知-->
<cc:EmailPublisher/>
</publishers>
<tasks>
<cc:TaskList/>
</tasks>
</project>
</cc:define>

<!-- 默认配置 -->
<cc:define QueuePriority="1"/>
<cc:define KeepLastXBuilds="300"/>
<!-- Email 相关 -->
<cc:define EmailDomain="company.com"/>
<cc:define EmailSendHost="smtp.live.com"/>
<cc:define EmailSendPort="25"/>
<cc:define EmailUseSSL="TRUE"/>
<cc:define EmailSendUser="ci"/>
<cc:define EmailSendPassword="******"/>
<cc:define CIEmailUser="ci"/>
<cc:define PMEmailUser="pm_1"/>
<cc:define name="EmailTesterList">
<user group="tester" name="tester_1" address="tester_1@$(EmailDomain)"/>
<user group="tester" name="tester_2" address="tester_2@$(EmailDomain)"/>
</cc:define>
<!-- Trigger 相关 -->
<cc:define ModificationTriggerIntervalSeconds="300"/>
<cc:define ModificationDelaySeconds="60"/>
<cc:define ProjectTriggerIntervalSeconds="30"/>
<cc:define ProjectTriggerStatus="SUCCESS"/>
<cc:define DailyBuildTriggerTime="18:00"/>
<!-- SVN 相关 -->
<cc:define SVNUsername="ci"/>
<cc:define SVNPassword="******"/>
<cc:define SvnCleanCopy="FALSE"/>
<cc:define name="SourceControl">
</cc:define>
<!-- Task 相关 -->
<cc:define TestTimeout="1800"/>
<cc:define CopyTimeout="60"/>
<cc:define ReplaceTimeout="60"/>
<cc:define BuildConfiguration="DEGUB"/>
<cc:define PublishConfiguration="RELEASE"/>

<!-- TestProject: Service 项目 -->
<queue name="TestProject" duplicates="ApplyForceBuildsReAdd" />
<cc:Project ProjectName="TestProject-Servcies"
Queue="TesProjectt"
WorkingDirectory="TestProject\SourceCode\service_trunk\"
ArtifactDirectory="TestProject\Artifact\service\"
StateDirectory="TestProject\State\"
PublishDirectory="TestProject\Publish\"
EmailSubject="[CI-TestProjectService]"
ModificationDelaySeconds="30"
TeamLeader="caihaihua">
<cc:define name="SourceControl">
<cc:SVNSourceControl SVNTrunkURL="https://vm-caihaihua/svn/testproject/services/trunk/"
SvnCleanCopy="False"/>
</cc:define>
<cc:define name="TriggerList">
<cc:ModificationTrigger/>
<cc:DailyBuildTrigger/>
</cc:define>
<cc:define name="TaskList">
<!-- Config -->
<cc:Replace>
<cc:define name="Files">
/file=$(CIDirectory)$(WorkingDirectory)WcfService\Web.config
/file=$(CIDirectory)$(WorkingDirectory)ManagerTest\App.config
/file=$(CIDirectory)$(WorkingDirectory)WcfServiceTest\App.config
</cc:define>
<cc:define name="Rules">
/from=Catalog=(?![^;\s']*_log[;\s']+)(=?[^;\s']*)/to=Catalog=service_trunk_ci
/from=Source=(=?.*?)(=?[;\s']+)/to=Source=localhost$2
/from=http://(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$2.svc
/from=http://(=?.*?)/(?!SSO)(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$3.svc
/from=http://(=?.*?)/SSO/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/SSO/$2.svc
</cc:define>
</cc:Replace>
<!-- Build -->
<cc:Build SolutionPath="TestProjectService.sln"/>
<!-- Publish -->
<cc:Copy From="$(WorkingDirectory)WcfService"
To="$(PublishDirectory)WcfService"/>
</cc:define>
</cc:Project>
<cc:Project ProjectName="TestProjectServcies-Test"
Queue="TestProject"
QueuePriority="2"
WorkingDirectory="TestProject\SourceCode\service_trunk\"
ArtifactDirectory="TestProject\Artifact\test\"
StateDirectory="TestProject\State\"
EmailSubject="[CI-TestProjectServcie-Test]"
ModificationDelaySeconds="30"
TeamLeader="caihaihua">
<cc:define name="TriggerList">
<cc:ProjectTrigger ListenToProject="TestProject-Servcies"/>
</cc:define>
<cc:define name="TaskList">
<!--Run Test-->
<cc:RunTest TestContainerPath="ManagerTest\bin\Debug\ManagerTest.dll"/>
<cc:RunTest TestContainerPath="WcfServiceTest\bin\Debug\WcfServiceTest.dll"/>
</cc:define>
</cc:Project>

<!-- TestProject: AdminWeb 项目 -->
<cc:Project ProjectName="TestProject-AdminWeb"
Queue="TestProject"
WorkingDirectory="TestProject\SourceCode\admin_trunk\"
ArtifactDirectory="TestProject\Artifact\admin\"
StateDirectory="TestProject\State\"
PublishDirectory="TestProject\Publish\"
EmailSubject="[CI-TestProject-AdminWeb]"
TeamLeader="caihaihua">
<cc:define name="SourceControl">
<cc:SVNSourceControl SVNTrunkURL="https://vm-caihaihua/svn/testproject/adminweb/trunk/"/>
</cc:define>
<cc:define name="TriggerList">
<cc:ModificationTrigger/>
<cc:DailyBuildTrigger/>
</cc:define>
<cc:define name="TaskList">
<!-- Config -->
<cc:Replace>
<cc:define name="Files">
/file=$(CIDirectory)$(WorkingDirectory)AdminWeb\Web.config
</cc:define>
<cc:define name="Rules">
/from=http://(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$2.svc
/from=http://(=?.*?)/(?!SSO)(=?[^\/]+)/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/WcfService/$3.svc
/from=http://(=?.*?)/SSO/(=?[^\/]+).svc/to=http://vm-caihaihua/testproject_trunk_ci/SSO/$2.svc
</cc:define>
</cc:Replace>
<!-- Build -->
<cc:Build SolutionPath="AdminWeb.sln"/>
<!-- Publish -->
<cc:Publish SolutionPath="AdminWeb\AdminWeb.csproj"
To="$(PublishDirectory)AdminWeb" />
</cc:define>
</cc:Project>
</cruisecontrol>


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: