为了方便开放人员进行项目发布和测试,老大要我部署一个自动化的平台。在研究了一阵子之后,总算是有了一些成果。特此分享
基本思路如下:在局域网中有一台svn服务器用来存放程序员的代码。公司租了一个阿里云的服务器,用作测试环境。云服务器上也装有svn,对不同的项目有不同的版本库,方便测试人员随时进行项目回滚。我要做的工作就是:
1.将源码从局域网的svn服务器上导出到我的电脑上(系统为ubuntu14.10)
2.利用ant对源码进行编译。
3.执行脚本将编译好的源文件通过svn传到云服务器上。
当然第3部也能够通过build.xml实现,只是系统上的ant是通过apt-get安装,版本太高。下不到相应的antsvn插件,所以用脚本代替。
hudson的安装就不细说了,具体可参照
http://developer.51cto.com/art/201111/304118.htm
虽然版本和我的不一样,但配置起来是一样一样的,晒一下我的配置
如果是通过yum 或者 apt-get 安装的ant 可以使用rmp -qf ant 或者 dpkg -L ant 查看ant的安装路径,我这是/usr/share/ant
我在shell部分指定了一个脚本,用来将编译好的文件传到云服务器上。内容如下:
#!/bin/bash
LOG=/tmp/svn.log
svn update /home/join/svn/$JOB_NAME >> $LOG 2>&1
脚本很简单,不过其中出现了一个 JOB_HOME 的变量。而且在脚本中也没有定义,其实JOB_HOME 变量是hudson中自带的,它表示当前编译的项目名。关于更多的环境变量可以从
http://localhost:8080/hudson/env-vars.html
http://localhost:8080/hudson 替换为你hudson的访问url
下面是我项目的配置
首先是源码库的位置。 图上的 "." 所表示的路径为 ~/.hudson/jobs/$JOB_NAME/workspace
关于svn中文路径的问题,上篇博客也有提到过,这里不再赘述
在Build 中必须要添加Invoke Ant 和 Execute shell ,其中的顺序也是有讲究的,它会按照定义的先后顺序分别执行。即先执行ant进行编译,然后在执行先前在系统配置中指定的shell脚本。
build.xml的内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<project name ="test" default ="copy" basedir =".">
<property name="jre" value="/usr/local/jdk1.7.0_71/jre/lib"/>
<property name="javahome" value="/usr/local/jdk1.7.0_71/lib"/>
<property name="tomcatdir" value="/usr/local/tomcat"/>
<property name="build" value="{basedir}/build"/>
<property name="build.classes" value ="${build}/classes"/>
<property name="src" value ="${basedir}/src"/>
<property name="dest" value ="/home/join/svn/ZXClient"/>
<property name="dest.classes" value="${dest}/WEB-INF/classes"/>
<property name="lib" value ="${basedir}/WebRoot/WEB-INF/lib"/>
<!-- 定义jar包路径 -->
<path id="classpath">
<fileset dir="${lib}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${tomcatdir}/lib">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${jre}">
<include name="**/rt.jar"/>
</fileset>
<fileset dir="${javahome}">
<include name="**/*.jar"/>
</fileset>
</path>
<!-- 删除build 路径-->
<target name ="clean">
<delete dir ="${build}" includeEmptyDirs="true" deleteonexit="true" verbose="true" failοnerrοr="false"/>
<echo message ="Java Version: ${ant.java.version}"/>
</target>
<!-- 建立build/classes 路径,并编译class 文件到build/classes 路径下-->
<target name ="compile" depends ="clean">
<mkdir dir="${build}"/>
<mkdir dir ="${build.classes}"/>
<javac srcdir ="${src}" destdir ="${build.classes}" nowarn="true" encoding="UTF-8" compiler="org.eclipse.jdt.core.JDTCompilerAdapter" source="1.7" target="1.7">
<classpath refid="classpath"/>
</javac>
</target>
<!-- 将文件拷贝到相应目录夹 -->
<target name="copy" depends="compile">
<copy todir="${dest}">
<fileset dir="${basedir}/WebRoot">
<!-- <exclude name="**/*.jar"/> -->
</fileset>
</copy>
<copy todir="${dest.classes}">
<fileset dir="${build.classes}"/>
</copy>
<copy todir="${dest.classes}">
<fileset dir="${src}">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
</project>
关于build.xml文件的编写网上也有很多资料,值得一提的是javac指定编译器这个细节。
程序员们开发所使用的IDE是Eclipse,而Eclipse的默认编译器是JDT,和ant所默认的javac还是有区别的。如果使用javac可能会出现很多让人找不着头脑的错误,而程序员们则会说,代码没问题,我这儿编译就能通过。今天就碰到了字符编码的问题,程序注释中有部分中文是乱码,使用javac编译会报错。将乱码替换之后,再度编译又出现utf-8(BOM)编码问题,同样不通过。换成ADT就没那么麻烦了。具体做法也很eazy , 让程序员将他们Eclipse中的ecj.jar包拷贝到ant的lib目录下即可。我这里是/usr/share/ant/lib。下面是编译成功的截图:
可以看到,在编译完程序之后,调用了之前指定的脚本。
本身在云服务器的svn中版本库中我定义了post-commit钩子函数,当有新的提交时,会自动update下来。这样就使得整个部署过程很方便了。如果再为项目添加一个定时任务,就能做到持续化集成了。至于钩子函数,之前博客中也有介绍。
最后要交代的是关于build.xml中copy标签的测试,如果两个文件相同,copy操作不会覆盖。要强制覆盖的话,有相应的参数。