您的位置:首页 > 理论基础 > 计算机网络

Hudson:持续集成服务器的介绍http://blog.csdn.net/heihuifeng/article/details/7258467

2013-09-13 09:47 477 查看


资料参考

hudson官网
hudson wiki网站
插件介绍


转自:/article/11444234.html


介绍


什么是持续集成(Continuous Integration)

持续集成(CI)是一种实践,旨在缓和和稳固软件的构建过程。在整个软件开发生命周期内,它主要用于保证代码质量,确保尽早遇到问题(如代码缺陷),避免问题在软件开发周期晚期变复杂时才被发现。CI的作用主要有如下几个方面:

软件构建自动化。
构建可持续的自动化检查。
构建可持续的自动化测试。
生成后后续过程的自动化。


组件

实现CI的上述功能,需要三个组件:

用 Ant 或 Maven 等工具建立的自动构建过程。
一个代码存储库,比如 CVS 或 Subversion。
一个 CI 服务器,比如 Hudson。


hudson介绍

Hudson 是一种革命性的开放源码 CI 服务器,它从以前的 CI服务器吸取了许多经验教训。Hudson最吸引人的特性之一是它很容易配置:很难找到更容易设置的 CI 服务器,也很难找到开箱即用特性如此丰富的CI 服务器。Hudson 容易使用的第二个原因是它具有强大的插件框架 ,所以很容易添加特性。例如,一个 Hudson 插件可以随时间的推移跟踪FindBugs
和代码覆盖。它还可以报告测试结果的趋势(来自 JUnit 或TestNG? )以及构建结果和对应的执行时间。有人调查过,Hudson是目前使用最多的CI服务器。


工作原理

CI系统的基本结构图




构建过程

触发构建--手动、代码更新、定制时间。
更新代码--Svn、Git、CVS。
构建--执行 Shell、执行 Windows 批处理、使用Ant、使用Maven。


安装

安装sun-java6-jdk,设置环境变量JAVA_HOME
安装tomcat6
安装 ant (optional)
hudson官网下载hudson.war,放到tomcat/webapps下。访问http://localhost:8080/hudson,进入hudson的启动页面。注:使用sudo apt-get install tomcat6时,将hudson.war放在/var/lib/tomcat6/webapps目录下。
默认在/usr/share/tomcat6/.hudson下建立hudson的主目录。注意权限问题。


通用配置


系统管理

打开系统管理-系统设置,进行配置。

主目录:这个目录用来保存所有的配置信息和数据。默认是当前用户目录下的.hudson。也可创建一个空目录,并将这个目录路径赋给环境变量 hudson/WEB-INF/web.xml中的HUDSON_HOME,重启hudson。
JDK:设置JDK的路径,默认是自动安装的,如果你的电脑安装过JDK那就将自动安装复选框勾掉,填写JAVA_HOME的路径即可。
Ant:设置Ant的路径ANT_HOME。
Android Emulator:针对Android项目,设置 SDK安装路径。
Xvnc-Command line:设置vncserver启动路径及参数。如:/usr/bin/vncserver :99 -geometry 800x600。
Xvnc-Base display number:设置桌面显示号的基数。如:99.

打开系统管理-管理插件,可安装插件。hudson默认的插件保存目录为:HUDSON_HOME/plugins,所以也可以直接将插件拷贝到该目录下,重启hudson即可。
HUDSON_HOME目录结构
[python] view plaincopyHUDSON_HOME
|-------config.xml (hudson基础配置)
|-------*.xml (其他站点范围内的配置文件)
|-------userContent (此目录中的文件将被送达您的http://server/hudson/userContent/。)
|-------fingerprints (存储指纹记录,关于fingerprints请查阅文件指纹识别)
|-------plugins (存储插件集)
|-------jobs(构建任务总目录)
|-------[JOBNAME] (为每个作业定义一个子目录)
|-------config.xml (作业配置文件)
|-------workspace (为版本控制系统而工作的目录)
|-------lastSuccessful (这个符号关联到最近的成功构建。)
|-------builds



用户配置

选中系统设置-启用安全 ,进行用户配置

JNLP节点代理的TCP端口选项中选择“Disable”。
访问控制-安全域

选择“Hudson专有用户数据库”:使用Hudson自己的用户列表验证, 而不是外部系统代理. 这适用于没有用户数据库小范围的设定. 建立的用户配置信息保存在HUDSON_HOUME/users下。
允许用户注册:如果勾选上,则表示允许用户自己注册一个新账号,通过点击页面右上角的注册链接进行操作。取消这个选框表示禁止任意注册新账号。 当这个选框被取消,就必须使用系统管理员来创建账号。

授权策略-安全矩阵

需要先注册一个admin用户(与角色名称相同),赋予全部的权限以便检验,否则我们将无法管理hudson。
默认会有一个匿名用户角色,表示未登录用户的访问权限,你可以不授权或只授予read权限。
添加用户/组:输入一个名称,然后点击添加,这里实际上是先建立一个角色,因为这时用户并不存在。然后注册一个相同名字的用户。

授权策略-项目矩阵授权策略

这个授权模型扩展自"安全矩阵",允许把下面的ACL(访问控制列表)矩阵附加到每个项目定义中(在Job配置页面). 就是说,除了可以在这里进行全局授权外,还可以在JOB中进行配置。
任务设置-启用项目安全:这里只能对当前的JOb进行授权配置,同样的,这里也是创建角色,用户需要自己注册或管理员进行创建。如果“系统设置”与“JOB设置”中存在相同的角色,则权限取并集。

反设置

有时候会出现这样的情况,就是虽然创建了角色,但是没有勾选上“允许用户注册”,这时就无法控制hudson了,这时可以通过如下修改,开启“允许用户注册”。
在$HUDSON_HOME环境变量对应的文件夹下config.xml,修改true 元素为false。重启hudson,这时候的Hudson又回归到无认证模式,任何人都能拥有该系统的全部权限。


创建构建任务


配置JOB_WORKSPACE

构建时使用的目录,也就是从代码仓库中取得的代码所要保存的路径,默认路径为:HUDSON_HOME/jobs/$jobname/workspace
job的配置中,所有涉及到路径的配置,都是基于JOB_WORKSPACE基础上的,配置时都是使用相对路径,也就是从这个路径开始计算。
可以在job设置中修改这个路径,找到Advanced Project Options,点击“Advanced”,勾选Use custom workspace,并设置一个绝对路径,比如/usr/local/hudson/jobname/workspace,保存。


ngux构建:svn+cppcheck+gtest

注:需要安装hudson的svn插件、cppcheck插件。

新建任务
Source Code Management:设置项目的源码获取方式Subversion地址

[python] view plaincopysvn+ssh://hjhei@192.168.1.4/home/projects/svn/ngux/trunk@HEAD


Build Triggers:设置构建的触发器

Poll SCM:指定一个定时作业表达式来定义Hudson每隔多久检查一下您源代码仓库的变化。如果发现变化,就执行一次构建。
Build periodically:选项支持类似crontab格式的任务周期定制。* * * * *对应分钟,小时,月份相应的日期,月份,星期

Build:添加指令以执行构建脚本,这里添加的是shell脚本

执行cppcheck的脚本,并在ngux的目录下生成cppcheck-result.xml测试报告。

[python] view plaincopycd ./ngux
cppcheck --enable=all -q --xml . 2>cppcheck-result.xml


编译执行gtest测试用例的脚本,在ngux/unittest/reports目录下生成每个类对应的xml测试报告。

[python] view plaincopycd ./ngux
make clean
make -j3
cd .unittest/
./run_gtest.sh


run_gtest.sh文件内容

[python] view plaincopy#!/bin/bash
TEST_ITEMS=(textviewtest imageviewtest gridviewtest pageviewtest pagenavigateviewtest panelviewtest boxlayoutviewtest pairlayoutviewtest buttonviewtest linelayoutviewtest scrollviewtest menuviewtest itemviewtest listviewtest listviewlooptest trackbarviewtest)

[ -e reports/ ] || mkdir reports

for item in ${TEST_ITEMS[*]}
do
./$item --gtest_output=xml:$item.xml
if [ -f $item.xml ]; then
mv $item.xml reports/
else
echo "====================build $item failed===================="
continue
fi
done


Post-build Actions:构建完成后需要进行的处理

Publish JUnit test result report:如果构建脚本执行了JUnit测试,此选项将指示Hudson处理XML测试文档并为每次连续构建产生一份可持续的报告,依据正在进行的测试汇总处理结果。其结果是当前工作主页的一份报告,作业中的单元测试会随着时间的推移按由老至新进行陈列。

[python] view plaincopyngux/unittest/reports/*.xml


Publish Cppcheck results:发布cppcheck测试报告,同JUnit。

[python] view plaincopy**/cppcheck-result.xml


E-mail Notification:当选择此选项,可以输入一个或多个电子邮件地址[多个可用空格分隔],当Hudson完成了执行作业后,将会给它们发送通知。事件触发时将产生一份 Email,包括构建失败、构建不稳定等。这儿有一个额外的选项,当由于用户的错误提交造成Hudson决定废弃此次构建,将会发送一份专门的邮件给这位 SCM提交者,以便让他检查源代码。注:如果集成了gtest,测试用例不通过,会构建失败。


Espier构建:svn+Ant+Findbugs

注:需要安装ant、Findbugs插件、Static Analysis Collector结果分析插件、Android Emulator模拟器插件、Xvnc插件。

新建任务
Source Code Management:设置项目的源码获取方式Subversion地址

[python] view plaincopysvn+ssh://hjhei@192.168.1.4/home/projects/svn/espier/branches/nowebcore/Espier@HEAD


Build Triggers:设置构建的触发器
Build Environment:

勾选Run Xvnc during build。
勾选Run an Android emulator during build,并设置模拟器的属性。
Common emulator options:勾选显示模拟器窗口。

Build:添加指令以执行构建脚本,这里使用的是Ant-build.xml。

Invoke Ant-Targets

[python] view plaincopyclean
all
findbugs


build.xml内容

[python] view plaincopy<?xml version="1.0" encoding="UTF-8"?>
<project name="Espier" default="all" basedir=".">

<property environment="env"></property>
<property name="android_sdk_path" value="/opt/android-sdk-linux_x86"/>
<property name="android_api_level" value="10"/>
<property name="android_platform" value="${android_sdk_path}/platforms/android-${android_api_level}"/>
<property name="android_jar" value="${android_platform}/android.jar"/>
<property name="refjars" value="jars/common.jar:jars/framework.jar:jars/core.jar:jars/layout.jar:jars/fmsoft_guava.jar"/>
<property name="classpath" value="${refjars}:${android_jar}"/>
<property name="debug_keystore" value="/home/heihuijing/.android/debug.keystore"/>
<property name="espier_package" value="com.fmsoft.espier"/>

<target name="all" depends="Step7_jarsign"/>

<target name="Step0_updateVersion">
<echo message="Update Version in AndroidManifest.xml ..."/>
<exec executable="bash">
<arg line="build_version.sh"/>
</exec>
</target>

<target name="Step1_genR" depends="Step0_updateVersion">
<echo message="Generate R.java ..."/>
<mkdir dir="gen"/>
<exec executable="${android_sdk_path}/platform-tools/aapt">
<arg line="package -f --auto-add-overlay -m -J gen -S res -A assets -M AndroidManifest.xml -I ${android_jar}"/>
</exec>
</target>

<target name="Step2_aidl" depends="Step1_genR">
<echo message="Preprocess aidl ..."/>
</target>

<target name="Step3_compile_java" depends="Step2_aidl">
<echo message="Compile all java files ..."/>
<mkdir dir="bin"/>
<javac srcdir="gen:application:quicksearchbox" destdir="bin" classpath="${classpath}" debug="true" debuglevel="lines,vars,source"/>
</target>

<target name="Step4_dx" depends="Step3_compile_java">
<echo message="Package all classes to classes.dex ..."/>
<java jar="${android_sdk_path}/platform-tools/lib/dx.jar" args="--dex --output=bin/classes.dex bin" fork="true"/>
</target>

<target name="Step5_compile_res" depends="Step4_dx">
<echo message="Compile all resource files ..."/>
<exec executable="${android_sdk_path}/platform-tools/aapt">
<arg line="package -f -M AndroidManifest.xml -S res -A assets -F bin/ResClass -I ${android_jar}"/>
</exec>
</target>

<target name="Step6_apkbuild" depends="Step5_compile_res">
<echo message="Build apk ..."/>
<exec executable="${android_sdk_path}/tools/apkbuilder">
<arg line="bin/${ant.project.name}.apk -u -z bin/ResClass -f bin/classes.dex"/>
</exec>
</target>

<target name="Step7_jarsign" depends="Step6_apkbuild">
<echo message="Sign the apk ..."/>
<exec executable="jarsigner">
<arg line="-keystore ${debug_keystore}"/>
<arg line="-keypass android -storepass android"/>
<arg line="bin/${ant.project.name}.apk androiddebugkey"/>
</exec>
</target>

<!--clean target-->
<target name="clean">
<delete dir="bin"/>
<delete dir="gen"/>
</target>

<!--findbugs target-->
<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask"/>
<property name="findbugs.home" value="/home/heihuijing/tool/findbugs-1.3.9" />

<path id="findbugs.path">
<fileset dir="/home/heihuijing/findbugs-1.3.9">
<include name="**/*.jar" />
</fileset>
</path>

<target name="findbugs">
<findbugs home="${findbugs.home}"
output="xml"
outputfile="findbugs.xml">
<!--auxClasspath path="${findbugs.home}/lib/Regex.jar" /-->
<sourcePath path="gen:application:quicksearchbox" />
<class location="${basedir}/bin" />
</findbugs>
</target>
</project>


Post-build Actions:构建完成后需要进行的处理

Publish FindBugs? analysis
results :发布FindBugs测试报告,同Junit。
Build other projects:任务完成后,可触发其他任务构建。如:espiertest。espier任务完成后,触发espiertest构建。


EspierTest? 构建:svn+Ant+JUnit

新建任务
Source Code Management:设置项目的源码获取方式Subversion地址

[python] view plaincopysvn+ssh://hjhei@192.168.1.4/home/projects/svn/espier/branches/nowebcore/EspierTest@HEAD


Build Triggers:设置构建的触发器。如设置Build after other projects are built为espier,在espier构建完成后开始该任务的构建。
Build Environment:

勾选Run Xvnc during build。
勾选Run an Android emulator during build,并设置模拟器的属性。
Common emulator options:勾选显示模拟器窗口。

Build:添加指令以执行构建脚本,这里使用的是Ant-build.xml。

Invoke Ant-Targets

[python] view plaincopyuninstall
reinstall
run-test


build.xml内容

[python] view plaincopy<?xml version="1.0" encoding="UTF-8"?>
<project name="EspierTest" default="Step7_jarsign" basedir=".">

<property environment="env"></property>
<property name="android_sdk_path" value="/opt/android-sdk-linux_x86"/>
<property name="android_api_level" value="10"/>
<property name="android_platform" value="${android_sdk_path}/platforms/android-${android_api_level}"/>
<property name="android_jar" value="${android_platform}/android.jar"/>
<property name="tested_project" value="/home/heihuijing/fm/android-espier/Espier"/>
<property name="targetPackage" value="mobi.espier.browser"/>
<!-- <property name="refjars" value="jars/common.jar:jars/framework.jar:jars/core.jar:jars/layout.jar:jars/fmsoft_guava.jar"/> -->
<!-- <property name="classpath" value="${refjars}:${android_jar}"/> -->
<property name="adb" value="${android_sdk_path}/platform-tools/adb"/>
<property name="classpath" value="${tested_project}/bin:${android_jar}"/>
<property name="debug_keystore" value="/home/heihuijing/.android/debug.keystore"/>
<property name="espiertest_package" value="mobi.espier.browser.test"/>

<target name="Step1_genR" >
<echo message="Generate R.java ..."/>
<exec executable="${android_sdk_path}/platform-tools/aapt">
<arg line="package -f --auto-add-overlay -m -J gen -S res -A assets -M AndroidManifest.xml -I ${android_jar}"/>
</exec>
</target>

<target name="Step2_aidl" depends="Step1_genR">
<echo message="Preprocess aidl ..."/>
</target>

<target name="Step3_compile_java" depends="Step2_aidl">
<echo message="Compile all java files ..."/>
<javac srcdir="gen:src" destdir="bin" classpath="${classpath}" debug="true" debuglevel="lines,vars,source" encoding="UTF-8" includeantruntime="false">
<classpath>
<fileset dir="${tested_project}/jars" includes="*.jar" />
<!-- <fileset dir="libs" includes="*.jar" /> -->
</classpath>

</javac>
</target>

<target name="Step4_dx" depends="Step3_compile_java">
<echo message="Package all classes to classes.dex ..."/>
<java jar="${android_sdk_path}/platform-tools/lib/dx.jar" fork="true">
<arg line="--dex --output=bin/classes.dex bin"/>
</java>
</target>

<target name="Step5_compile_res" depends="Step4_dx">
<echo message="Compile all resource files ..."/>
<exec executable="${android_sdk_path}/platform-tools/aapt">
<arg line="package -f -M AndroidManifest.xml -S res -A assets -F bin/ResClass -I ${android_jar}"/>
</exec>
</target>

<target name="Step6_apkbuild" depends="Step5_compile_res">
<echo message="Build apk ..."/>
<exec executable="${android_sdk_path}/tools/apkbuilder">
<arg line="bin/${ant.project.name}.apk -u -z bin/ResClass -f bin/classes.dex"/>
</exec>
</target>

<target name="Step7_jarsign" depends="Step6_apkbuild">
<echo message="Sign the apk ..."/>
<exec executable="jarsigner">
<arg line="-keystore ${debug_keystore}"/>
<arg line="-keypass android -storepass android"/>
<arg line="bin/${ant.project.name}.apk androiddebugkey"/>
</exec>
</target>

<!--clean testproject target-->
<target name="clean">
<delete includeEmptyDirs="true">
<fileset dir="bin"/>
<fileset dir="gen"/>
</delete>
</target>

<!--install-test-apk to emulator-->
<target name="install" depends="Step7_jarsign" description="Install android-test project.">
<exec executable="${adb}">
<arg line="install bin/${ant.project.name}.apk"/>
</exec>
</target>

<!--reinstall-test-apk to emulator-->
<target name="reinstall" depends="clean, Step7_jarsign" description="ReInstall android-test project.">
<exec executable="${adb}">
<arg line="install -r bin/${ant.project.name}.apk"/>
</exec>
</target>

<!--uninstall-test-apk from emulator-->
<target name="uninstall" description="Uninstall android-test project">
<exec executable="${adb}">
<arg line="uninstall ${espiertest_package}"/>
</exec>
</target>

<!--run-test-->
<target name="run-test" description="run test project">
<property name="reports.dir" value="reports"/>
<property name="files.dir" value="/data/data/${targetPackage}/files"/>
<!-- <property name="test.runner" value="com.zutubi.android.junitreport.JUnitReportTestRunner"/> -->
<property name="test.runner" value="mobi.espier.browser.test.XMLInstrumentationTestRunner"/>

<echo>Cleaning up previous test reports...</echo>
<exec executable="${adb}" failonerror="true">
<!-- <arg line="${adb.device.arg}" /> -->
<arg value="shell" />
<arg value="rm" />
<arg value="${files.dir}/*" />
</exec>

<echo>Running tests...</echo>
<exec executable="${adb}" failonerror="true">
<!-- <arg line="${adb.device.arg}"/> -->
<arg value="shell" />
<arg value="am" />
<arg value="instrument" />
<arg value="-w" />
<arg value="-e" />
<arg value="outfile" />
<arg value="test-results.xml" />
<!-- <arg value="-e" /> -->
<!-- <arg value="multiFile" /> -->
<!-- <arg value="true" /> -->
<arg value="${espiertest_package}/${test.runner}" />
</exec>

<echo>Downloading XML test reports...</echo>
<exec executable="${adb}" failonerror="true">
<!-- <arg line="${adb.device.arg}"/> -->
<arg value="pull" />
<arg value="${files.dir}" />
<arg value="${reports.dir}" />
</exec>

</target>

</project>


Post-build Actions:构建完成后需要进行的处理

Publish JUnit test result report:发布JUnit测试报告。

[python] view plaincopyespiertest/reports/*.xml
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: