二维火掌柜Android持续化集成探索

CI持续集成

前言:

此文章前部分将以最理想的持续集成理念来阐述。实际具体项目使用,本就应该针对自身项目的情况“因材施教”,具体场景具体配置使用。文章后部分将结合我组Android项目具体情况进行实践。

1、什么是持续集成

1.1 起源

持续集成是敏捷开发流程背景下极限编程的方法论中的核心实践之一。

持续集成起源

1.2 定义

大师Martin Fowler对持续集成是这样定义的:

持续集成是一种软件开发实践。在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以多次。每次集成都通过自动化的构建(包括编译,自动化测试等)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成引起的问题,让团队能够更快的开发内聚的软件。

1.3 概述

简而言之,持续集成就是一种开发流程的具体实践,团队成员持续地收到持续集成系统的反馈并进行修改,不必等到开发周期后期才寻找和修复缺陷。

具体表现的话,可以举一个例子,开发人员的每一次代码提交都会触发一次持续过程(触发时机可以根据团队实际情况调整,并不一定是提交触发,也可以是周期触发等等),即从拉取源码到构建再到测试等等,最后反馈给开发人员,开发人员根据反馈修改程序后再次提交,如此,形成一个闭环。

2、为什么要做持续集成

持续集成收益与意义

2.1 开发团队收益

  1. 有效的控制或降低风险。

通过每天集成变化的代码并跑测试,能尽早做一些处理。

  • 尽早发现程序缺陷并修复。 通过持续集成,避免了等到交付给测试手里却发现程序根本跑步起来的尴尬。
  • 尽早排除假设。 程序出问题不必考虑程序环境因素,因为使用的是同一套脚本,同样的构建环境。
  • 尽早评估软件质量。 软件质量将被持续地全程跟踪。
  1. 减少重复性的活动,提高团队效率。

减少重复的过程可以节省团队的时间、费用和工作量。在软件开发过程中,浪费时间的重复劳动可能在我们的项目活动的任何一个环节发生,包括代码编译、测试、审查、发布等。通过持续集成可以将这些重复的动作都变成自动化的,无需太多人工干预,让团队成员将时间更多的投入到动脑筋的、更高价值的事情上。

  1. 提高软件交付速度。

持续集成可以让项目在任一点上及时交付可以安装的软件包。这是持续集成最可见的一个益处。我们可以无休止地讨论改善软件质量和减少风险,但是对用户或者客户来说,可以安装的软件包是最切实可行的。

2.2 其他意义

  • 增强对项目的把控力

项目负责人(QA负责人、开发leader等)需要一些量化的、宏观的指标帮助其进行一些决策或者判断。例如,这个项目的代码覆盖率如何?代码风格、编码质量如何?冒烟通过率如何?这些具有指导意义的指标可以很方便地从持续集成中产出。持续集成系统为项目构建状态和品质指标提供了及时的信息。

  • 增强团队成员对开发产品的信心

因为团队成员通过持续集成能清楚地知道每一次构建的结果,他们知道他们对软件的改动造成了哪些影响,结果怎么样。

3、如何来做持续集成

3.1 主要涉及工具

  • 版本控制/配置管理工具

版本控制与配置管理工具主要负责源代码,配置文件的管理。常见的工具如 git、svn 等, 其中 git 是当下最流行的版本控制工具。

  • 构建工具

实现主要负责自动化地编译、测试、部署等,这是持续集成的核心工具;构建工具是编程语言依赖型的,不同编程语言使用不同的构建工具。

  • CI 服务平台

CI 服务器主要负责将版本控制仓库和构建工具有机整合起来,并通过设置一种或多种构建触发条件来触发构建。

3.2 主流方案

  1. Gitlab-CI

  2. Jenkins(我组Android项目采用此种方案来实现持续集成)

  3. Travis CI

  4. Drone.io

  5. flow.ci

……

3.3 主要流程

  • 触发持续集成

  • 拉取源码仓库代码

  • 构建(这里的构建其实包含了持续集成的重要过程,如单元测试、集成测试、代码风格检查等等)

  • 进行一些构建后操作(例如发送邮件通知导致测试不通过的代码提交者,通过钉钉通知发送构建结果等)

持续集成流程

3.3 持续集成过程

3.3.1 总过程

持续集成过程

  • 由构建到归档是持续集成主线。

归档可以是给Git、Svn打Tag,也可以是把产出的Apk包、Jar包等,以一定的规则(例如:manage_2018-3-27_5.6.56_debug.apk )命名后存档。

  • 单元测试、静态代码扫描、代码风格检测的运行时间尽量控制在半小时内,避免反馈不及时。

  • 安全扫描、性能测试、UI测试可能比较耗时,需要根据项目实际情况调整。

  • 建议每天定时运行若干次(至少一次),产出一些经过全套测试的具有一定交付信心的构建物。

根据我组实际情况和当前收益期望,如图中所示,实线箭头是我组已经完成的集成任务,虚线箭头是尚未完成的集成任务;实线框是目前考虑集成到主线的任务,虚线框是目前不考虑集成到主线的任务。(相对来说,静态代码扫描和单元测试较为方便集成,收益也相对较大,集成的性价比高;而安全扫描、性能测试、UI测试相对来说集成难度较大。因此在持续集成初期,我组优先考虑前者。)

3.3.2 具体过程

针对我组情况,对lint静态代码扫描和单元测试的持续集成:

  1. 配置Jenkins平台。(配置源码管理和基础构建)

  2. 在Jenkins上配置部署lint静态代码扫描。

  3. 细化lint静态扫描规则,和团队成员讨论制定执行lint检查初期规则集合。

  4. 在Jenkins上配置部署lint静态代码扫描初期规则集合。

  5. 整理单元测试。

  6. 在Jenkins上配置部署单元测试。

  7. 根据lint报告反馈修改程序。

  8. 添加新的lint静态代码扫描规则到规则集合并更新配置部署在Jenkins。

  9. 补充单元测试并更新配置部署在Jenkins。

  • 在Jenkins上配置部署lint静态代码扫描和单元测试后概览:

在下图可以看到归档文件和lint扫描趋势图、单元测试趋势图,相应的趋势图点击进去还可以看具体的详细信息。

Jenkins持续集成概览

Lint原始报告

Lint分析报告

单元测试报告

  • 关于lint检查出的issue问题的解决落地

全面lint检查后,几乎必然出现海量的错误、警告。因此需要从海量的错误、警告中,抽取相对重要的,但也具备可执行性的规则集合(团队成员一起讨论,民主和谐)。

讨论制定具体执行lint规则(相对重要) -> 执行 -> 公示 -> 再讨论制定具体执行lint规则(相对重要) -> …

不断反馈,形成闭环,在执行过程中及时调整。

针对我组实际情况,落地方案:

  1. 分仓库解决。 (问题:业务issure分仓库 base以下issure如何落地)

  2. 专人负责专项issure。 (问题:有些issure比较多,有些issure比较少)

  3. 前两种方案结合,部分issure分仓库,部分issure专人。

考虑到模块化,模块仓库分到每个团队成员头上,采用分仓库落地方案,base层以下也由专人来负责。

持续集成初期收益较大的lint扫描规则集合:

  • warning UnusedResources: Unused resources 未使用的资源问题
  • error ResourceName: Resource with Wrong Prefix 资源前缀问题
  • warning Deprecated: Using deprecated resources 废弃文件、资源等问题