论坛首页 Java企业应用论坛

重构CruiseControl配置和Ant脚本

浏览 2826 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-07-29   最后修改:2010-09-29
代码的重复是件麻烦事,配置文件的重复也让人不爽。当配置文件出现bad smell时,也要着手进行重构了。

当在CruiseControl(以下简称cc)监控多个项目时,config.xml很容易出现大堆的重复配置。比如我的:
<cruisecontrol>
	<property file="common.properties" />
	<property name="anthome" value="apache-ant-1.7.0" />

	<project name="cc">
		<listeners>
            <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
        </listeners>
        <modificationset quietperiod="30">
			<svn RepositoryLocation="${svnloc}/${project.name}" username="${user}" password="${password}"/>
        </modificationset>
        <schedule interval="20">
            <ant anthome="${anthome}" buildfile="buildfiles/${project.name}.xml" target="update"/>
        </schedule>
        <publishers>
            <onsuccess>
                <antpublisher anthome="${anthome}" buildfile="buildfiles/${project.name}.xml" target="deploy"/>
            </onsuccess>
        </publishers>
	</project>

	<project name="dd">
		<listeners>
            <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
        </listeners>
        <modificationset quietperiod="30">
			<svn RepositoryLocation="${svnloc}/${project.name}" username="${user}" password="${password}"/>
        </modificationset>
        <schedule interval="20">
            <ant anthome="${anthome}" buildfile="buildfiles/${project.name}.xml" target="update"/>
        </schedule>
        <publishers>
            <onsuccess>
                <antpublisher anthome="${anthome}" buildfile="buildfiles/${project.name}.xml" target="deploy"/>
            </onsuccess>
        </publishers>
	</project>
</cruisecontrol>

当存在多个project时,由于每个project的处理过程是一模一样的,因此配置写了重复的n次。使用plugin定义模板来改变:
<cruisecontrol>
	<property file="common.properties" />
	<property name="anthome" value="apache-ant-1.7.0" />

	<!-- template --> 
	<plugin name="project">
        <listeners>
            <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
        </listeners>

		<!-- monitoring the svn change -->
        <modificationset quietperiod="30">
			<svn RepositoryLocation="${svnloc}/${project.name}" username="${user}" password="${password}"/>
        </modificationset>
		
		<!-- task --> 
        <schedule interval="20">
            <ant anthome="${anthome}" buildfile="buildfiles/${project.name}.xml" target="update"/>
        </schedule>
		
		<!-- publish -->
        <publishers>
            <onsuccess>
                <antpublisher anthome="${anthome}" buildfile="buildfiles/${project.name}.xml" target="deploy"/>
            </onsuccess>
        </publishers>
	</plugin>
	<!-- 1..n project -->
	<project name="cc"/>
	<project name="dd"/>
</cruisecontrol>

有更多的project都只需添加一句话而已。plugin的使用可参考官方http://cruisecontrol.sourceforge.net/main/plugins.html。其中name属性如果是cc默认定义的,可以不加classname属性,比如这里的name="project"。

由于cc经常和ant配合使用,ant也容易出现大堆的重复配置。比如我的:
cc.xml
<project name="cc" basedir=".">
	<property file="../common.properties" />
	<property name="project" value="../projects/${ant.project.name}" />
	<property name="tomcat" value="../apache-tomcat-5.5.26/webapps" />

	<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" />

	<target name="checkout">
		<svn username="${user}" password="${password}">
			<checkout url="${svnloc}/${ant.project.name}" 
				destPath="${project}"/>
		</svn>
	</target>

	<target name="update">
		<svn username="${user}" password="${password}">
			<update dir="${project}"/>
		</svn>
		<!-- war -->
		<ant dir="${project}"/> 
	</target>

	<target name="deploy">
		<copy todir="${tomcat}">
			<fileset dir="${project}/war"/>
		</copy>
	</target>
</project>

dd.xml
<project name="dd" basedir=".">
	<property file="../common.properties" />
	<property name="project" value="../projects/${ant.project.name}" />
	<property name="tomcat" value="../apache-tomcat-5.5.26/webapps" />

	<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" />

	<target name="checkout">
		<svn username="${user}" password="${password}">
			<checkout url="${svnloc}/${ant.project.name}" 
				destPath="${project}"/>
		</svn>
	</target>

	<target name="update">
		<svn username="${user}" password="${password}">
			<update dir="${project}"/>
		</svn>
		<!-- war -->
		<ant dir="${project}"/> 
	</target>

	<target name="deploy">
		<copy todir="${tomcat}">
			<fileset dir="${project}/war"/>
		</copy>
	</target>
</project>

cc.xml和dd.xml几乎一模一样,只是project name不同而已。使用import task来改变:
先定义公共的xml,这里为import.xml:
<!-- this project name is unuseful -->
<project name="import">
	<property file="../common.properties" />
	<property name="project" value="../projects/${ant.project.name}" />
	<property name="tomcat" value="../apache-tomcat-5.5.26/webapps" />

	<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" />

	<target name="checkout">
		<svn username="${user}" password="${password}">
			<checkout url="${svnloc}/${ant.project.name}" 
				destPath="${project}"/>
		</svn>
	</target>

	<target name="update">
		<svn username="${user}" password="${password}">
			<update dir="${project}"/>
		</svn>
		<!-- war -->
		<ant dir="${project}"/> 
	</target>

	<target name="deploy">
		<copy todir="${tomcat}">
			<fileset dir="${project}/war"/>
		</copy>
	</target>
</project>

在cc.xml和dd.xml中import进来即可:
cc.xml
<project name="cc" basedir=".">
	<import file="import.xml" />
</project>

dd.xml
<project name="dd" basedir=".">
	<import file="import.xml" />
</project>

需要注意的是,import.xml中的project name是没用的,${ant.project.name}不是指该值,而是指最上层引用的xml的project name。比如cc.xml引用了import.xml,那么${ant.project.name}是指cc.xml的project name。import task有点复制代码的味道。

参考:
http://www.blogjava.net/chelsea/archive/2008/03/06/184374.html
http://cruisecontrol.sourceforge.net/main/plugins.html
http://ant.apache.org/manual/index.html
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics