怎样让你更快的完成工作去“摸鱼”,我的 Android 美团求职之路
steps {
//
}
}
}
}
pipeline 和 agent 分别是声明式流水线的两种特定语法,后者为流水线指定了一个特定的工作区。stages 由多个不同的 stage 组成,stage 可以展示在 stage view 中,用来表示构建环节中的不同阶段。steps 我们可以理解成每个构建阶段中包含的不同步骤。通常我们的构建指令可以在这里编写。
接下来本文将介绍关于个推使用 Jenkins 持续集成方案的实践(本文基于 Jenkins 2.19,使用 Jenkins Pipeline 构建)。
需求分析
====
以个推的实践经验来分析,在打包过程中,我们最好能有一种控制代码风险的机制,这种机制能够自动化地控制有关风险代码进入打包环节,并中断打包流程,给出风险警示。另外,中大型项目的模块依赖往往比较复杂,我们应提供一种按需依赖组合的方式。研发人员还可以引入一些自动化测试,保证代码的质量。综上所述,一个打包方案的需求分析如下:
代码检测:在多人开发中,除了代码 review,我们还需要在构建阶段引入一定的代码检测机制,对一些风险代码进行扫描检测,比如内存泄漏、不可退出循环等等,以规避此类代码打包上线。
模块组合:个推 SDK 有许多不同的功能业务模块,但是一些模块并非打包所必须,所以在打包的过程中研发人员需要根据不同的需求将相应的模块组合打包,输出产物。
单元测试:为了在一定程度上规避问题代码的上线,在构建之前,我们需要先对代码进行单元测试。只有通过了单元测试才能继续进行 SDK 构建。
SDK 构建:个推 SDK 经常会有一些定制需求,而这些定制需求的功能类似,所以我们可以根据不同的定制需求,结合个推的预编译插件,选择编译不同的代码,以减少开发成本。
Jar/AAR 文件合规性检验:对 SDK 来说,构建输出的产物一般为 aar 或 jar 文件。为保证输出的文件合规性,我们需要对输出产物的格式(包括版本号、域名等信息)做最终的检测。
真机自动化测试(可选):如果我们希望生成的 SDK 可以在真机上模拟运行测试,则可以选择这个步骤。
资料包归档:由于我们最后输出的文件包含集成文档、demo 等等,所以构建的最后阶段,我们需要将这些资源文件进行归档并放到指定的目录下。
通知构建者:有些时候构建可能需要一定的时间,构建者会异步地去处理其他事情。当构建完成的时候,我们需要通知相关的构建人员。
根据上述需求的分析,一个完整的持续集成流程图如下所示:
首先,进入准备阶段(prepare), 在该阶段会进行打包前的准备工作,比如环境准备等。接着是解析编译打包相关参数(parse jenkinsConfig), 用于之后的打包构建,包括模块依赖组合的支持等。
然后是拉取相关打包代码(checkout code)阶段。随后进入代码检测(Android Lint)阶段和单元测试阶段(Unit Testing)。通过前面的单元测试以及代码检测之后就可以进入我们的编译 SDK 阶段(Build SDK)了, 在该阶段我们可以配合个推的预编译插件以及相关的打包环境变量参数,选择相对应的模块组合或者选择对应的功能代码进行按需编译。
编译完成后,我们需要对相关的输出产物(JAR/AAR)进行格式检测(CheckJar 阶段)。待检测通过就可以进行真机模拟测试了(Automated Testing 阶段,可选),随后就可以输出构建产物(PrintSDK 阶段)并发送邮件通知相关构建人员(Email Notification 阶段)。至此,一次完整的打包流程已经结束。
Android 构建环境管理
==================
上文介绍了打包构建方案的流程,但是在实践中,我们会发现随着构建的任务越来越多,构建的环境会变得越来越繁杂,难以管理。
痛点分析:当我们依赖于宿主机构建 Android 时,不同的项目有着不同的 gradle 环境。随着 gradle 的升级、项目的迭代,当不同的构建项目任务数量越来越庞大时,宿主机的 gradle 环境就越容易出现污染。另外,由于构建的环境依赖宿主机的编译环境,一旦宿主机的编译环境发生变化,就很容易对构建项目产生影响。
为解决这个问题,我们可以将不同的 Android gradle 构建环境放进一个 Docker 容器中。Docker 是一个开源的应用容器引擎,可以实现虚拟化,也可以由开发者打包应用或者依赖包到一个轻量级、可移植的容器,然后发布至不同的机器上。容器完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 App), 更重要的是容器性能开销极低。
在每次编译构建时我们都依赖于一个 Docker 容器的环境,通过这种方式将任务之间的编译环境以及与宿主机之间通过 Docker 容器隔离开来,这样可以保证宿主机的环境变化对编译任务不产生影响,保证构建环境的干净。再之后随着 gradle 版本升级,我们需要升级并发布对应的 Docker 镜像版本,以兼容高版本的编译环境、做相应的环境版本管理。
Jenkins Pipeline 提供了使用 Docker 镜像作为构建环境的功能,代码如下:
pipeline {
agent {
docker {
image 'allbears/jenkins-android:1.0.1'
}
}
}
维护和扩展
使用 Pipeline 构建时,开发者可以通过维护 Jenkinsfile 对打包功能进行版本管理。这种构建方式更方便,开发者可以自由地回归历史版本进行打包。Jenkinsfile 的大致结构模板如下。
pipeline{
agent {
docker {
image 'allbears/jenki
ns-android:1.0.1' //指定构建环境
}
}
stages {
stage('Prepare'){
steps {
echo "构建前准备"
}
}
stage('Parse Jenkins Config'){
steps {
echo "Jenkins 构建参数解析"
}
}
stage('Checkout Code'){
steps {
echo "构建代码检出"
}
}
stage('Android Lint'){
steps {
echo "代码静态检测"
}
}
stage('Unit Testing') {
steps {
echo "单元测试"
}
}
stage('Clean') {
steps {
echo "编译前环境初始化"
}
}
stage('Build SDK') {
steps {
echo "构建 SDK"
}
}
stage('Check JAR') {
steps {
echo "Jar 包合规性分析"
}
}
stage('Automated Testing') {
steps {
echo "自动化测试"
评论