【Hello CC.NET】巧用模板简化配置
从 《【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>
变量名称 | 描述 | 值 |
CIWebSite | CC.NET配套网站的地址 | http://vm-caihaihua/CCNET/ |
CIDirectory | 工作目录 | C:\CI\ |
MsBuildPath | MsBuild 程序的地址 | C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe |
MsTestPath | MsTest 程序的地址 | C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe |
SVNPath | Svn 程序的地址 | C:\Program Files (x86)\VisualSVN Server\bin\svn.exe |
FCReplacerPath | FCReplacer 程序的地址 | C:\CI\Tools\FCReplacer.exe |
DFCopierPath | DFCopier 程序的地址 | 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 | 是否启用 SSL | TRUE |
EmailSendUser | 发送邮箱的帐号 | ci |
EmailSendPassword | 发送邮箱账户的密码 | ****** |
CIEmailUser | CI 维护人员的邮箱账户 | 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 |
SVNUsername | SVN 帐号 | ci |
SVNPassword | SVN 帐号的密码 | ****** |
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.com | N |
EmailSendHost | 邮件服务器的地址 | smtp.live.com | N |
EmailSendPort | 邮件服务器的端口 | 25 | N |
EmailUseSSL | 是否使用 SSL(取决于邮件服务器的配置) | TRUE | N |
EmailSendUser | 邮件通知的发送帐号 | CI | N |
EmailSendPassword | 邮件通知的发送帐号的密码 | ****** | N |
PMEmailUser | 部门经理的邮箱帐号 | pm_1 | N |
CIEmailUser | CI 环境维护人员的邮箱帐号 | ci | N |
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 | 源码监测频率(秒) | 600 | N |
例子:
- <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:00 | N |
例子:
- <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 | 监测依赖项目的频率(秒) | 30 | N |
ProjectTriggerStatus | 设定的构建结果 | SUCCESS | N |
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>
模板变量:
变量名称 | 描述 | 默认值 | 是否必填 |
SVNUsername | Svn 账户,需要项目的 checkout 权限 | ci | N |
SVNPassword | Svn 账户的密码 | ****** | N |
SvnCleanCopy | 下载源代码前是否先删除本地源代码 | FALSE | N |
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 | 替换的超时时间(秒) | 60 | N |
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 | 编译的配置 | DEBUG | N |
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 | 编译的配置 | RELACE | N |
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 | 拷贝的超时时间(秒) | 60 | N |
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 | 测试的超时时间(秒) | 1800 | N |
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 | 项目在队列里的优先级 | 1 | N |
KeepLastXBuilds | 保存最后的 X 个构建结果 | 300 | N |
ModificationDelaySeconds | 源代码变更触发构建任务的延迟时间 | 60 | N |
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>
【Hello CC.NET】巧用模板简化配置的更多相关文章
- CC.NET模板简化配置
[Hello CC.NET]巧用模板简化配置 从 <[Hello CC.NET]CC.NET 实现自动化集成> 到 <[Hello CC.NET]自动化发布时 Web.config ...
- Spring事务支持:利用继承简化配置
因为事务代理的实现类是 TransactionProxyFactoryBean . 事务代理Bean必须注入事务管理器. 大部分情况下,每个事务代理的事务属性大同小异,对于这种情况,Spring提供了 ...
- C#开发中使用配置文件对象简化配置的本地保存
C#开发中使用配置文件对象简化配置的本地保存 0x00 起因 程序的核心是数据和逻辑,开发过程中免不了要对操作的数据进行设置,而有些数据在程序执行过程中被用户或程序做出的修改是应该保存下来的,这样程序 ...
- WCF学习之旅—WCF4.0中的简化配置功能(十五)
六 WCF4.0中的简化配置功能 WCF4.0为了简化服务配置,提供了默认的终结点.绑定和服务行为.也就是说,在开发WCF服务程序的时候,即使我们不提供显示的 服务终结点,WCF框架也能为我们的服务提 ...
- Spring注释与简化配置
在Spring 2.5及以后的版本中,提供了注释和命名空间来简化Spring的配置.下面是一些常用配置分享. 1.@Autowired注释 以前给一个Bean配置属性时,Bean必须配置< ...
- ElasticSearch 模板文件配置
首先是推荐一下参考资料 中文资料:http://kibana.logstash.es/content/elasticsearch/index.html 官方文档:https://www.elastic ...
- maven pom文件简单模板和配置详解
https://blog.csdn.net/earbao/article/details/49924943 maven pom文件简单模板和配置详解
- 7 -- Spring的基本用法 -- 11... 基于XML Schema的简化配置方式
7.11 基于XML Schema的简化配置方式 Spring允许使用基于XML Schema的配置方式来简化Spring配置文件. 7.11.1 使用p:命名空间简化配置 p:命名空间不需要特定的S ...
- smarty模板的配置
smarty下载: http://www.smarty.net/download 建议使用一个兼容性好的smary版本. 太新的版本往往对php的版本支持不好. php推荐使用的模板是:sma ...
随机推荐
- PHP操作Mongodb之高级查询篇
本文主要讲解PHP中Mongodb的除了增删改查的一些其他操作. 在PHP操作Mongodb之增删改查篇中我们介绍了PHP中Mongodb的增加.删除.修改及查询数据的操作.本文主要是将查询时用到的高 ...
- 如何在Mac OS X中显示隐藏的文件
打开终端,输入: defaults write com.apple.finder AppleShowAllFiles -bool true 显示文件夹中的隐藏文件. defaults write co ...
- Java内存与垃圾收集知识总结
总结一下关于Java内存的知识,今天我不生产知识,我只是知识的搬运工. 1.运行时数据区域 java虚拟机在执行JAVA程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 由所有线程共享的数据 ...
- IntelliJ 支持web
- 如何在一个div标签里显示出另一个网页? <iframe src=" http://www.baidu.com " width="800px" height="200px" scrolling="no" frameborder="0"> </iframe>
如何在一个div标签里显示出另一个网页? 用在div里用iframe,就像下面的代码 <iframe src=" http://www.baidu.com " width=& ...
- oracle impdp 导入
用imp语法导入dmp文件: imp mdm/mdm@SYSWARE file= E:\Product\9y5s\5.MDM\20161024.DMP full=y 报错 IMP-00002:无 ...
- WinForm应用只运行一次
一.WinForm应用只能运行一次 static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [ST ...
- hdu 5795
A Simple Nim Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- session和cookie的简单理解
0. 引子,我们为什么要cookie和session 因为http请求是无状态的(不能记录用户的登录状态等),所以需要某种机制来保存用户的登录状态等信息,在下次访问web服务的时候,不用再 ...
- innodb的存储结构
如下所示,innodb的存储结构包含:表空间,段,区,页(块),行 innodb存储结构优化的标准是:一个页里面存放的行数越多,其性能越高 表空间:零散页+段 独立表空间存放的是:数据.索引.插入缓冲 ...