ABS工具是如何实现?

2

原理介绍

先说一个普通的ant文件结构,包括project/property/target/task等元素,下面是一个样例:

<?xml version="1.0" encoding="UTF-8"?>
<project name="test" all="all" basedir=".">
   <property name="source.dir" location="source" />
   <target name="all" depends="clean,compile,package,deploy" />
   <target name="clean">
     <delete file="${tmp.dir}" />
   </target>
   
   <target name="compile">
   </target>
   
   <target name="package">
   </target>
   
   ...
</project>

其中delete元素就是一个task,在ant内置的task中有一个可以执行外部构建文件的task叫ant(参考地址:http://ant.apache.org/manual/Tasks/ant.html)我们可以这样去包装构建文件:
file: test_project/build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="test" all="all" basedir=".">
    <property environment="env" />
    <!-- properties configuration -->
    <property name="ci.root" location="${env.JENKINS_CI}" />
    <property name="jenkins.tools.root" location="${env.JENKINS_TOOLS}"
    <property name="jdk.root" location="${env.JAVA_HOME}" />
    <property name="ant.root" location="${env.ANT_HOME}" />

    <property name="abs-tasks.root" location="${jenkins.tools.root}/abs-tasks" />
    <property name="abs-libs.root" location="${jenkins.tools.root}/abs-libs" />
    <property name="ant-contrib.entry.jar" location="${abs-libs.root}/ant-contrib.jar" />

    <!-- taskdef define section -->
    <!--ant-contrib taskdefs.-->
    <taskdef resource="net/sf/antcontrib/antlib.xml">
        <classpath>
            <pathelement location="${ant-contrib.entry.jar}" />
        </classpath>
    </taskdef>

    <!-- abs-task-framework macro -->
    <macrodef name="abs-task">
        <attribute name="task" />
        <element name="properties" optional="true" />
        <sequential>
            <ant antfile="${abs.tasks.root}/@{task}/run.xml" inheritRefs="true">
                <properties />
            </ant>
        </sequential>
    </macrodef>
    <!-- more taskdef ... -->

    <target name="clean">
        <!-- clean tasks... -->
    </target>

    <target name="compile">
        <abs-task name="customtask">
            <properties>
                <property name="executable.file" value="scripts/demo_vs.bat" />
            </properties>
        </abs-task>
    </target>

    <target name="package">

        <path id="artifact.files">
            <fileset dir="${artifact.dir}">
                <include name="**/*.exe" />
                <include name="**/etc/*.ini" />
            </fileset>
        </path>

        <abs-task name="package">
            <properties>
                <propety name="artifact.pathrefid" value="artifact.files" />
            </properties>
        </abs-task>
    </target>

</project>

file: abs-tasks/customtask/run.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="customtask" default="customtask">
    <dirname property="task.basedir" file="${ant.file.customtask}" />
    <import file="${task.basedir}/macro/customtask_macro.xml" optional="true" />
    <target name="customtask">
        <customtask-macro executableFile="${executable.file}" />
    </target>
</project>

file: abs-tasks/package/run.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="package" default="package">
    <dirname property="task.basedir" file="${ant.file.package}" />
    <import file="${task.basedir}/macro/package_macro.xml" optional="true" />
    <target name="package">
        <package-macro artifactPathRefId="${artifact.pathrefid}" />
    </target>
</project>

将最开始的代码进行拆分然后包装成abs-tasks扩展task,这样就可以实现构建task的重用。

<ant antfile="${abs.tasks.root}/@{task}/run.xml" inheritRefs="true">
    <properties />
</ant>

这个原理其实就是ant -f run.xml -Dk1=v1 -Dk2=v2

重构包装

将build.xml文件中的proerties/taskdef define抽取出来单独存放,目录结构可以这个

- jenkins-tools
    - abs-config
        ci-common-properties.xml
        ci-common-taskdefs.xml
        ci-common-config.xml
        standerdData.xml #用于描述项目目录结构规范,可以自定义一些属性方便构建使用
    - abs-tasks
        - sourcemonitor # 这个有构建和报告展示功能
            - run.xml
            - macro
                - customtask-macro.xml
            - convertor # 后面会讲
                - report.xsl
                - ci-summary.xsl
                - ci-module.xsl
        - customtask #这个只有构建功能
            - run.xml
            - macro
                - package-macro.xml
                - package.xml

file: xxx_project/build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="xxx_project" default="build" basedir=".">
    <property environment="env" />
    <property name="abs-config.dir" location="${env.JENKINS_TOOLS}/abs-config" />
    <import file="${abs-config.dir}/ci-common-config.xml" />
    <import file="${abs-config.dir}/standardData.xml" />

    <target name="build" depends="build.steps,build.after-steps" />
    <target name="build.steps" depends="compile" />
    <target name="build.after-steps" depends="artifact" />

    <target name="compile" depends="setup.normal">
        <abs-task name="customtask">
            <properties>
                <property name="executable.file" value="xxx" />
            </properties>
        </abs-task>
        <abs-task name="sourcemonitor">
            <properties>
                <property name="xxx" value="xxx" />
            </properties>
        </abs-task>
    </target>

    <target name="package">
        ...
    </target>

</project>

好了就到这里吧,ant脚本只是一个构建载体,你可以将借用exec 扩展很多命令,也可以使用groovy脚本开发扩展任务或者字符串解析等等。

下期预告:如何实现构建任务的数据展示?



你可能感兴趣的

载入中...