Cruise Control 持续集成 - 如何自动编译,打包,并自动发布至Tomcat

一, 前言

目标是,利用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="[email protected]">
            <failure address="[email protected]" 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" failonerror="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" failonerror="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" failonerror="false">
    <arg line="/C NET START tomcat"></arg>			
  </exec>  
</target>

 这样,CruiseControl 即不会被 Tomcat 启动窗口所阻塞,因为此时Tomcat已在后台运行,已无窗口!

相关推荐