乐趣区

关于jenkins:让你工作效率提升975倍的秘籍竟然是

作者 | 个推高级安卓研发工程师 萨其拉

引言

在个推 SDK 开发过程中,通常而言一个残缺的开发上线流程是这样的:提出需要 -> 需要开发 -> 打包测试 -> 问题修复 -> 打包交付测试验证 -> 测试通过 -> 产品上线。

在这个流程中,不难发现打包是一项重复性劳动,而且咱们经常会反复经验问题修复阶段,也就意味着咱们在一个开发上线周期内须要进行多个重复性的打包过程。如果能优化这个环节,那么开发效率就能失去显著晋升。

除此之外,手动打包往往还容易引入一些危险,比如说打包环境不统一、签名文件透露、效率低、包的溯源治理艰难等等,所以咱们须要一套继续集成的计划来缩小这种重复性劳动以及标准打包流程。Jenkins 作为继续集成的计划,领有丰盛的插件反对,以下咱们将为大家介绍个推基于 Jenkins 的构建实践经验。

Jenkins 简介

Jenkins 是一款开源的 CI&CD 软件,用于自动化各种开发工作,包含构建、测试和部署软件等。Jenkins 反对多种运行形式,比方通过零碎包、Docker 或者独立的 Java 程序的运行。对于 Jenkins 构建 Android 实际,能够参考小编写的这篇教程《应用 Jenkins 构建 Android 利用》:

https://jenkins-zh.cn/tutoria…

开发者能够通过抉择流水线的形式来创立一个 PipeLine 构建工作,如下:

通过创立 Jenkinsfile 进行版本控制,如下:

Jenkins Pipeline 容许你像写代码一样治理你的构建脚本。咱们通常能够通过创立 Jenkinsfile 管制版本从而更好地进行性能的更新迭代。一个申明式流水线语法的根本构造如下:

pipeline {
    agent any 
    stages {stage('Build') { 
            steps {//}
        }
        stage('Test') { 
            steps {//}
        }
        stage('Deploy') { 
            steps {//}
        }
    }
}

pipeline 和 agent 别离是申明式流水线的两种特定语法,后者为流水线指定了一个特定的工作区。stages 由多个不同的 stage 组成,stage 能够展现在 stage view 中,用来示意构建环节中的不同阶段。steps 咱们能够了解成每个构建阶段中蕴含的不同步骤。通常咱们的构建指令能够在这里编写。

接下来本文将介绍对于个推应用 Jenkins 继续集成计划的实际(本文基于 Jenkins 2.19,应用 Jenkins Pipeline 构建)。

需要剖析

以个推的实践经验来剖析,在打包过程中,咱们最好能有一种控制代码危险的机制,这种机制可能自动化地管制无关危险代码进入打包环节,并中断打包流程,给出危险警示。另外,中大型项目的模块依赖往往比较复杂,咱们应提供一种按需依赖组合的形式。研发人员还能够引入一些自动化测试,保障代码的品质。综上所述,一个打包计划的需要剖析如下:

  1. 代码检测:在多人开发中,除了代码 review,咱们还须要在构建阶段引入肯定的代码检测机制,对一些危险代码进行扫描检测,比方内存透露、不可退出循环等等,以躲避此类代码打包上线。
  2. 模块组合:个推 SDK 有许多不同的性能业务模块,然而一些模块并非打包所必须,所以在打包的过程中研发人员须要依据不同的需要将相应的模块组合打包,输入产物。
  3. 单元测试:为了在肯定水平上躲避问题代码的上线,在构建之前,咱们须要先对代码进行单元测试。只有通过了单元测试能力持续进行 SDK 构建。
  4. SDK 构建:个推 SDK 常常会有一些定制需要,而这些定制需要的性能相似,所以咱们能够依据不同的定制需要,联合个推的预编译插件,抉择编译不同的代码,以缩小开发成本。
  5. Jar/AAR 文件合规性测验:对 SDK 来说,构建输入的产物个别为 aar 或 jar 文件。为保障输入的文件合规性,咱们须要对输入产物的格局(包含版本号、域名等信息)做最终的检测。
  6. 真机自动化测试(可选):如果咱们心愿生成的 SDK 能够在真机上模仿运行测试,则能够抉择这个步骤。
  7. 材料包归档:因为咱们最初输入的文件蕴含集成文档、demo 等等,所以构建的最初阶段,咱们须要将这些资源文件进行归档并放到指定的目录下。
  8. 告诉构建者:有些时候构建可能须要肯定的工夫,构建者会异步地去解决其余事件。当构建实现的时候,咱们须要告诉相干的构建人员。

根据上述需要的剖析,一个残缺的继续集成流程图如下所示:

首先,进入筹备阶段(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/jenkins-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 "自动化测试"}
        }
        stage('Print SDK') {
            steps {echo "构建产物归档"}
        }
        stage('Email Notification') {
            steps {echo "邮件告诉"}
        }

    }

}

从上述的 Jenkinsfile 中咱们不难得悉,每个流水线会由不同的 stage 组成,而每一个 Stage 则能够作为一个独立的小功能模块。开发者能够通过将不同的 stage 进行排列组合来进行相应的扩大。

总结

人工构建过程繁琐、操作耗时,还容易在手动打包过程中引入一些危险。个推应用 Jenkins 自动化构建免去了繁琐的人工操作过程,充沛解放了研发人员的生产力。此外,个推应用 Pipeline 形式“继续集成”构建,让研发人员治理、迭代构建工程更加不便。接下来,个推还会在“继续集成”这个畛域深刻拓展,向开发者们分享最新的实际计划。

退出移动版