一, 前言
目标是,利用CruiseControl 自动抓取SVN下的源代码,并且将项目源码自动编译,打包成war,并自动部署到 Tomcat 中。
二, CruiseControl 如何自动获取SVN源码
1. 首先, 将 SVN 工程 checkout 到 CruiseControl Project 目录下。
cd ${CC_PROJECT_PATH}/yourproject/resources (${CC_PROJECT_PATH} CruiseControl 安装路径 )
svn co svn://127.0.0.1/trunk/yourproject/ (需要安装 SVN Server 端,命令可以执行)
2. 其次,CuriseControl 可以自动感知代码库中的源码是否有变更
CruiseControl 通过自身的 plugin <svnbootstrapper> 即可以通过checkout 的工程目录种的.svn,自动感知有没有新的变更,如若有新的变更,首先更新工程源码,然后触发项目中的ant脚本进行自动编译,打包。
<plugin name="svnbootstrapper" classname="net.sourceforge.cruisecontrol.bootstrappers.SVNBootstrapper"/> <plugin name="svn" classname="net.sourceforge.cruisecontrol.sourcecontrols.SVN"/> <bootstrappers> <svnbootstrapper localWorkingCopy="projects/${project.name}/resource"/> </bootstrappers> <!-- quietperiod: The number of seconds required to have passed since the last modification before a build can commence. This attribute is used to avoid starting a build while someone is in mid-checkin. --> <modificationset quietperiod="30"> <svn localWorkingCopy="projects/${project.name}/resource"/> </modificationset> <!-- 3 min --> <schedule interval="180"> <ant anthome="apache-ant-1.7.0" buildfile="projects/${project.name}/resource/build.xml" /> </schedule>
上面的配置既是告诉 CruiseControl 每隔 3分钟去 check 一下 yourproject 项目源码是否有变更,如果有,先更新,然后调用yourporject项目中的build.xml脚本自动进行build!
(CruiseControl默认情况下是必须要有变更才进行build,如果需要强制build,可以再 <project> 上加属性 requiremodification="N")
三, 一个完整的自动build的配置
<project name="yourproject" requiremodification="N"> <plugin name="svnbootstrapper" classname="net.sourceforge.cruisecontrol.bootstrappers.SVNBootstrapper"/> <plugin name="svn" classname="net.sourceforge.cruisecontrol.sourcecontrols.SVN"/> <listeners> <currentbuildstatuslistener file="logs/${project.name}/status.txt"/> </listeners> <bootstrappers> <svnbootstrapper localWorkingCopy="projects/${project.name}/resource"/> </bootstrappers> <!-- quietperiod: The number of seconds required to have passed since the last modification before a build can commence. This attribute is used to avoid starting a build while someone is in mid-checkin. --> <modificationset quietperiod="30"> <svn localWorkingCopy="projects/${project.name}/resource"/> </modificationset> <!-- 3 min --> <schedule interval="180"> <ant anthome="apache-ant-1.7.0" buildfile="projects/${project.name}/resource/build.xml" /> </schedule> <log dir="logs/${project.name}"> <merge dir="projects/${project.name}/build/logs/"/> </log> <publishers> <email mailhost="SMTP_HOST" buildresultsurl="http://localhost:8080/cruisecontrol/buildresults/${project.name}" skipusers="true" spamwhilebroken="true" returnaddress="project@example.com"> <failure address="comedshang@gmail.com" reportWhenFixed="true"/> </email> </publishers> </project>
将上面这段配置内容更新到 ${CC_PROJECT_PATH}/config.xml 中,这样,CruiseControl就会定期的(3分钟一次)感知代码库的变化,如果有变化,则更新,然后执行 scheduler 中的 ant 脚本。
这样,自动 build 的功能就实现了。
四,自动部署到 Tomcat
通常情况下,我们有两种方案。
1. 利用Tomcat自动部署功能,在 server.xml 中,将<Host>的属性autoDeploy设置为true。
这样,一旦有新的war部署到Tomcat 的工程目录webapps下,则Tomcat 可以自动部署!
这样做的好处是,我们只需要新建另外一个Ant脚本,把新打包的war部署到Tomcat中,既可。
但是这样做的问题是,自动部署后,由于JVM清理不干净,日而久之,则容易导致 java.lang.OutOfMemoryError: Java heap space.
2. 先自动关闭Tomcat,删除Tomcat中的工程文件,然后将打包的war部署,然后启动Tomcat
<project name="yourproject" default="startuptomcat" basedir="."> <property name="tomcat.dir" value="D:\Program Files\apache-tomcat-5.5.36"/> <property name="war.dir" value="../yourproject/" /> <property name="war.dist.dir" value="${war.dir}/build/dist"/> <property name="war.name" value="yourproject.war"/> <!-- 自动关闭 Tomcat --> <target name="shutdowntomcat"> <exec executable="${tomcat.dir}/bin/shutdown.bat" failοnerrοr="false"> <env key="CATALINA_HOME" value="${tomcat.dir}" /> </exec> <!-- sleep 30 seconds until it's completed. --> <sleep seconds="30"/> </target> <target name="clean" depends="shutdowntomcat"> <delete dir="${tomcat.dir}/work/Catalina/localhost/${ant.project.name}"/> <delete dir="${tomcat.dir}/webapps/${ant.project.name}"/> <delete file="${tomcat.dir}/webapps/${ant.project.name}.war"/> </target> <target name="copyWar" depends="clean"> <copy file="${war.dist.dir}/${war.name}" todir="${tomcat.dir}/webapps"></copy> </target> <target name="startuptomcat" depends="copyWar"> <exec executable="${tomcat.dir}/bin/startup.bat" spawn="true" vmlauncher="false"> <env key="CATALINA_HOME" value="${tomcat.dir}" /> </exec> </target> </project>
上述Ant 脚本,调用批处理文件,自动关闭Tomcat,部署后,自动启动Tomcat,
( 将上面这个Ant Script 加入CruiseControl的config.xml的<scheduler>中,既可实现自动部署!
但是看似一切很完美,但是,CruiseControl却只能自动部署一次,再也不会定期进行build部署了。也就是说,当Tomcat启动过后,CruiseControl被卡住了,它在等待新建的Tomcat窗口执行完毕,但新启动的Tomcat永远不会自动关闭,除非人为,所以 CruiseControl会被永远的卡住。
那么该如何解决?
经过测试,需要将 Tomcat 设置为服务模式既可!
cd %TOMCAT_HOME%\bin
service install tomcat
运行上面两行 command line 即可以将 Tomcat 设置为后台服务! 这样我们可以使用 net start tomcat 启动,同样可以使用 next stop tomcat 来停止,故,更新 deploy ANT 脚本
<target name="shutdowntomcat"> <exec executable="c:\Windows\System32\cmd.exe" failοnerrοr="false"> <arg line="/C NET STOP tomcat"></arg> </exec> <sleep seconds="30"/> </target> <target name="startuptomcat" depends="copyWar"> <exec executable="c:\Windows\System32\cmd.exe" failοnerrοr="false"> <arg line="/C NET START tomcat"></arg> </exec> </target>
这样,CruiseControl 即不会被 Tomcat 启动窗口所阻塞,因为此时Tomcat已在后台运行,已无窗口!