Building Android apps with Jenkins CI

在前东家,工程相关的都有专门的组来做,比如自动化的代码审查,编译,发布,测试,缺陷追踪等等系统。。。甚至当时就有人说就XXX的很多系统,即使司龄很大的员工都不一定都能使用的很熟练,因为实在是太多了。。。相反的是现在都没有,万事都需要自己动手,不过也还好,可以挑选些真的是非常有帮助的自动化系统来帮助我们提高工作效率(比如之前我一直都是不大记住写周报,其实我觉得那应该是小时报,不过还好,我当时的老大和部门经理对这个要求没有那么严格,我也不是偷懒的员工,所以基本是马马虎虎过了,但是我还是比较喜欢例如某些任务管理系统,用任务管理系统主要是防止自己忘记,一些大任务可以拆分成小任务,并且标记完成状况,或者是你在任务上撰写出你自己的意见/建议和老大进行沟通),今天就以自动化编译系统为起点来逐步搭建/定制出一个比较理想的持续集成系统。。。当然这是一个长期的任务,不是说它非常难,只是自己时间也不是特别多,会先挑些目前比较重要的东西来加入进来(building,lint,findbugs,monkey)。。。
今天先说编译系统,而且先是看基于Ant的,假设源码是放在GitHub上,比如https://github.com/guohai/and-expandable-listview/这个项目,我希望我的系统在每隔一定时间或者每次代码提交之后自己启动一次编译,第一这可以排错,防止开发人员不小心漏提交代码,或者merge代码的时候出错,尽早的发现这类比较低级的错误,编译系统编译失败会立刻邮件通知你,而不是你在本地编译测试了很多遍,信心满满的把代码提交(当然有人说会有人工代码审查,但是人工也不一定能发现所有错误,特别是编译错误),回家睡觉了,另外一个时区的同事刚开始新的一天,检出你的代码,发现根本编译不通过,那么他是该打你的电话叫醒你修改代码呢?还是等你第二天来修改呢?明显他两样都不想,所以最好是你保证自己提交的代码都是至少可以编译通过的(会有人说这么简单的事情会做不到吗?事实是当你很多人协同工作的时候,这个事情确实是有可能发生,很多次在XXX公司经历过一两天编译系统无法出一个可以通过的版本,当然这不是在黑前东家,只是事情确实有,而且公司也在逐步改用好一点的编译方式减少这种一个编译错误导致整个系统都无法编译出ROM的窘境);第二这个可以利用一些工具直接将编译的成果推送到自动化测试的服务里面完成基础的自动化测试,这样岂不是很好,减少些不必要的人工操作;第三有权限的人可以随时下载一个他需要的版本程序来安装运行,而不需要让你给他邮件发一个版本或者他自己安装编译环境,检出代码来完成编译。可能还有很多理由来需要这样一个系统,不过这里已经够了。。。
Jenkins的安装,基本使用就不说了,具体查看https://wiki.jenkins-ci.org/display/JENKINS/Use+Jenkins上面,我这里主要安装了一个GitHub插件,在Manage Jenkins->Manage Plugins当中可以很方便的完成,因为我本地都有Android SDK, Ant, Java等等一些基础环境,而且这些都已经在PATH当中,所以集成起来就很简单。然后就是创建任务, Jenkins当中称为job,然后就是配置该job,比如GitHub项目位置,仓库地址,keystore for release build,编译预处理,归档编译产物,以及触发编译条件,如下图:
Screen Shot 2014-01-27 at 12.00.47 AM
Screen Shot 2014-01-27 at 12.01.53 AM
Screen Shot 2014-01-27 at 12.14.36 AM
Screen Shot 2014-01-27 at 12.15.05 AM
Screen Shot 2014-01-27 at 12.34.11 AM
Screen Shot 2014-01-27 at 12.43.14 AM
这样就基本可以搭建出一个自动化的编译系统了,后面有机会来研究下基于Gradle的,毕竟这才是Google目前主导的方向。
当然你可以根据自己的需要调节更改配置来达到想要自己的目的,比如GitHub有提交就触发编译,只归档特定名字的文件等等,是否删除原有归档,如果新的版本有成功编译出来的话,等等可能还有更多的技巧。

洗完个澡,顺便试了下Gradle的,你可以在Jenkins当中下载Gradle插件,也可以不用专门下载,自己写个简单的脚本完成,比如我这里就是:
Screen Shot 2014-02-06 at 12.25.49 AM
而且也只有上述这一段不一样,其他都跟Ant的基本类似,不过生成需要归档的apk的路径可能需要改改,这里有个硬编码的ANDROID_HOME,目前没有发现比较好的解决方法,如果您知道如何解决,不吝赐教。在Ant版本中,我们sdk.dir是通过android update project生成的,但是在Gradle的项目当中似乎无法生成,没有SDK路径就会编译出错,比如:

* Where:
Build file '/Users/guohai/.jenkins/jobs/Gradle-Proj-Test/workspace/xxx/build.gradle' line: 9

* What went wrong:
A problem occurred evaluating project ':beckon'.
> SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable.
于是就先硬编码这个ANDROID_HOME变量先跳过这一问题,有空再来研究看看。
1
export ANDROID_HOME=/Users/guohai/Dev/android-sdk-macosx
chmod +x ./gradlew 
./gradlew clean assembleDefaultFlavorDebug

当然这gradlew后面跟的task可以自己调整,比如debug版本或者release版本,或者编译子项目(./gradlew :sub-project:clean,sub-project就是实际子项目的名字)。

P.S.
通知邮件发送使用Jenkins Email Extension Plugin
不过在配置的时候出现
501 mail from address must be same as authorization user
参考http://bbs.csdn.net/topics/390353671设置System Admin e-mail address就可以了。

Updated at 2015.12.25
升级到最新版本之后出现即使代码没有改变,也不停的出 Started by SCM
https://issues.jenkins-ci.org/browse/JENKINS-17614
这是一个 bug,我这里导致的原因,是有多个 branch 的名字包含 develop,然后进行 branch 指定的时候,指定 develop 就分不清了。
删掉或者改名 branch 就可以正常工作了。

另外在 headless 的服务器上下载 Android SDK ,如果只想下载/更新指定的包,那么请参照这里。
http://tools.android.com/recent/updatingsdkfromcommand-line
简单来说先通过

$ android list sdk

查看有哪些更新
然后指定需要安装的包

android update sdk --no-ui --filter tools,3,8

不清楚的可以

android update sdk --help

看一下

比如强制使用 http 协议列出所有更新(包括已废弃的)

android list sdk --no-https --all

注意,调用更新的时候也要带 –all 参数,否则编号会错乱

Leave a Reply

Your email address will not be published. Required fields are marked *