相信大家看完了上篇文章(http://gull.iteye.com/blog/1137200),会对自动化编译,部署和测试的过程与实现细节有所了解。那么我们稍微总结下就会发现其实现的实质就是一系列linux shell命令组成,且都是很常见的,如maven, ssh, scp, unzip, cp, mv, delete, kill, sed, awk等.
我们回想下——项目是采用maven2构建的,而我们CI自动化job的阶段也是借鉴maven2中默认的phases,因此我们做了下映射, 如下图:
此时你会有什么样的想法? —— 我们能否扩展maven2的生命周期,将我们不同流程的脚本嵌入到maven2的各个生命周期中,这样就可以直接使用原生的maven2命令来完成CI自动化流程了。
所幸的是maven2已经提供了这样的机制和插件,在实践中我们主要用到了下面这2个插件:
这2个插件如何操作可以查看相关手册:
http://maven.apache.org/plugins/maven-antrun-plugin/
http://evgeny-goldin.com/wiki/Maven-sshexec-plugin
maven-antrun-plugin这个插件官方介绍得比较简单,远不能达到我们的需要,因此我们需要扩展ant task来完成CI流程的定制化。
public class CodeSync extends Task { //todo public void execute() throws BuildException { //todo prepare some parameters try { //sync the application code sync(depot, p4ClientRoot, p4ClientFolder); } catch (Exception e) { e.printStackTrace(); throw new BuildException(e); } } private void sync(String depotRoot, String clientRoot, String folderPath) throws Exception { String depotPath = depotRoot + "/" + folderPath + "/..."; IServer server = ServerFactory.getServer("p4java://p4host:p4port", null); server.connect(); server.setCharsetName(p4Charset); server.setUserName(p4User); //login the p4 server server.login(p4Passwd); IClient client = server.getClient(p4Client); server.setCurrentClient(client); List<IFileSpec> fileSpecs = server.getDepotFiles(FileSpecBuilder.makeFileSpecList(new String[] { depotPath }), false); log("sync "+fileSpecs.size()+" flies"); client.sync(fileSpecs, true, false, false, false); server.logout(); } }
codesync=com.xxx.ant.tasks.CodeSync
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.6</version> <executions> <execution> <id>initialize</id> <phase>initialize</phase> <configuration> <target> <echo message="**************************"/> <echo message="** A P P S CODE SYNC "/> <echo message="**************************"/> <typedef file="$typedef.properties" /> <codesync> <parameter name="maven">xxx.xxx.xxx</parameter> <parameter name="xxxx">yyyy</parameter> </codesync> <echo message="**************************"/> <echo message="** END CODE SYNC *********"/> <echo message="**************************"/> <echo message=""/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> <execution> <id>compile-skip-unittest</id> <phase>test</phase> <configuration> <target if="maven.test.skip"> <echo message="*****************************************"/> <echo message="===== BEGIN COMPILE(TEST) ===="/> <echo message="*****************************************"/> <exec dir="/xxx/yyy/sourceFolder" executable="mvn"> <arg line="clean compile -Dmaven.test.skip=true -Ddependency.locations.enabled=false"/> </exec> <echo message= "***************************************"/> <echo message= "===== END COMPILE(TEST) ===="/> <echo message= "***************************************"/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> <execution> <id>compile-unit-test</id> <phase>test</phase> <configuration> <target unless="maven.test.skip"> <echo message="***********************************"/> <echo message="===== BEGIN COMPILE ===="/> <echo message="***********************************"/> <echo message="//TODO: prepare unittest environment "/> <exec dir="/xxx/yyy/sourceFolder" executable="mvn"> <arg line="clean compile -Ddependency.locations.enabled=false"/> </exec> <echo message="***********************************"/> <echo message="===== BEGIN COMPILE ===="/> <echo message="***********************************"/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>com.xxxx</groupId> <artifactId>ci-anttasks</artifactId> <version>1.0.0</version> </dependency> </dependencies> </plugin> </plugins> </build>
在这个配置文件中,我们扩展了maven2的initialize和test周期,并通过ant来执行我们想要的操作。
对于deploy过程也是比较杂的,也需要按照相同的方式来扩展,并且还要配合maven-sshexec-plugin插件来完成部署操作。
pom.xml配置片段
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.6</version> <executions> <execution> <id>upload package</id> <phase>pre-integration-test</phase> <configuration> <target> <mkdir dir="..."/> <!-- upload package to the remote server--> <scp todir="deployserver:path" keyfile="$keyfile" trust="true" failonerror="false"> <fileset dir="$buildFolder/"> <include name="*.zip"/> </fileset> </scp> ... </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>com.xxxx</groupId> <artifactId>ci-anttasks</artifactId> <version>1.0.0</version> </dependency> </dependencies> </plugin> <plugin> <groupId>com.goldin.plugins</groupId> <artifactId>maven-sshexec-plugin</artifactId> <executions> <!-- Run commands on each remote server --> <execution> <id>do deploy</id> <phase>pre-integration-test</phase> <goals> <goal>sshexec</goal> </goals> <configuration> <location>scp://$deployserver/uploadFolder</location> <keyfile>$keyFile</keyfile> <commands> <command>echo '********************************'</command> <command>echo '==== { Run Remote Commands} ===='</command> <command>echo '********************************'</command> <command> unzip xx.zip </command> <command>echo ''</command> <command>echo '==== END Run Remote Commands ===='</command> <command>echo '*********************************'</command> <command>echo ''</command> </commands> </configuration> </execution> </executions> </plugin>
目前integration test我们主要是采用jmeter来进行完成API测试的,因此我们需要配置ant jmeter task.
<execution> <phase>integration-test</phase> <configuration> <target> <echo message="******************************************"/> <echo message="==== { Run Integration test Scripts } ===="/> <echo message="******************************************"/> <path id="jmeter.classpath"> <fileset dir="$jarFolder"> <include name="ant-jmeter*.jar"/> </fileset> </path> <taskdef name="jmeter" classpathref="jmeter.classpath" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/> <property name="transformation.xsl" value="$resourcesFolder/jmeter-results-detail-report.xsl" /> <property name="resourcesFolder" value="$resourcesFolder" /> <ant antfile="$jmeter.integration.testscript" /> <echo message=""/> <echo message="=====END Integration Test====="/> <echo message="******************************"/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution>
到此maven2生命周期的扩展算是结束了,但如果子项目比较多的话,每一个这样配置很是麻烦,可以通过下面2种手段解决:
——全文完