企业级DevOps实战案例--移动APP持续交付实践

发布于 2021-02-26 17:02

本文由团队内大瑶同学撰写。



引言


移动App具有更新频繁的特性,这一点,从各大App在应用市场的版本发布频率可见一斑。高频发布意味着迅速迭代和交付,这对需求、开发、测试、运维的效率提出了更高的要求。那么,在快速变化的互联网环境下,如何在保证质量的前提下,提高App的交付速度?这是业界共同面临的问题。DevOps提供了解决该问题的答案,它倡导尽可能多地对软件构建过程中的所有步骤进行自动化处理,也就是构建自动化流水线,以提高效率、缩短开发周期。在当今的IT领域,DevOps倡导的持续交付理念已经被普遍接受,实施DevOps实践已经成为软件组织管理的趋势。近几年,随着敏捷软件模式的深化,我们也一直在尝试敏捷、持续集成等实践,以积极的态度拥抱DevOps。

 

值得重视的是,DevOps并非一个固定的模式或标准,事实上,业界对DevOps没有统一的定义(而且DevOps的定义是随着时间不断演变的)。它是一种普适的软件工程文化和实践,但每个企业的组织文化有差异,DevOps基础也不尽相同,现有的一些成功方案往往并不完全适合团队的实际情况,业界也不存在一个万能的实例供我们复制。因此,应当基于自身实际情况,参考同类优秀案例和经验,摸索出最适合自己的模式。一方面,我们缺乏专门的工具部门或团队,短时间内无法建立起大型的一体化持续交付平台;另一方面,我们又急需建立起持续交付流水线,以改进敏捷产品的开发测试流程。因此,我们以开源持续集成工具为核心,再适当开发辅助工具,构建了一个较为实用的App产品持续交付流水线。

 

一、案例背景

 

随着App的功能日益复杂,与第三方合作的模块越来越多,开发、测试阶段联调的难度也随之增加。同时,为迅速响应市场需求变化,App的迭代越来越快,发布周期越来越短。工期紧、任务多,这给开发、测试人员带来了很大的压力,例如,开发为了按时完成代码,挤压了一些本来用于代码评审、单元测试的时间,导致项目代码的质量下降;随之而来的是生产风险的提高,产品质量难以保障;开发需要花费额外的精力偿还技术债(漏洞、不规范的代码等),这又给新一轮迭代带来风险——如此便陷入“疲于奔命”的恶性循环。

 

为解决上述问题,在参考DevOps等主流解决方案基础上,我们也吸收DevOps和敏捷理念,开展App产品持续交付流水线实践,从工艺改进、组织文化等方面,改进App产品的持续交付实施过程,最终构建起一条完备的流水线。

 

二、案例内容

 

(一)问题分析

 

与其他产品不同,App的交付比较特殊。例如,H5产品需要将部署包放置到服务器上,并进行相应的配置,用户就可以通过访问网址获取服务;而安卓和IOS并不是部署在企业自己的服务器上,而是需要在各自的应用市场“上架”,用户才能从市场上获取App,安装到自己的手机上,完成交付过程。

 

对症方能下药,我们首先必须明确,是什么影响了App的迭代效率?经过分析和总结,我们发现,App的实施过程存在以下痛点:

 

1、开发任务繁重,代码质量不高。

 

造成这一点的原因有很多,如需求规划不合理、环境问题导致联调失败、代码评审不到位、测试覆盖不全面等。

 

2、版本分发效率低。

 

由于App产品的特殊性,用户必须在手机上安装新版本才能获取其服务。在开发人员频繁打出新版本的场景下,测试者需要及时获得最新的App版本。然而现实情况通常是开发在自己的电脑上构建(俗称“打包”),再把构建出的App安装包发给测试人员——这样人工的构建分发效率低,也难以保证构建出的安装包是“合格”(即通过了单元测试、代码扫描等必要的检查环节)的。

 

3、容易出现不同环境下版本不一致问题。

 

在测试阶段,测试人员通常对测试环境下的版本进行测试,而产品发布时,使用的是测试版本对应的生产版本,必须做到这个两个版本除了环境相关的参数配置不同外,其他代码完全一致。然而从测试通过到人工切换成生产环境参数并构建生产版本的这段时间,可能会存在开发人员改动代码的风险,导致一个未经测试的App版本被发布。因此,需要寻求同时构建多个不同环境参数的App的方案。

 

4、测试分析不到位,同类质量问题重复出现。

 

我们的目的不仅仅是修复问题,而且要保证日后不再发生同样的错误。事实上,一个产品的缺陷可以给其他产品带来启发,我们需要吸取他人的经验和教训,加强不同产品之间的交流。

 

以上几个问题,其实都是缺乏规范的流程、人工介入过多等原因造成的。当人工操作影响到工作效率时,应当考虑借助工具来节省人力,提高效率。

 

(二)方法体系

 

从工艺改进和组织文化两个方面入手,逐步构建起持续交付的实施流程和与之匹配的组织结构。

 

1、从工艺改进的角度,构建App持续交付流水线。

 

● 分别对DevOps的各个步骤进行优化和改进,并组合成一条基于Jenkins自动化持续交付流水线,覆盖从需求到交付的各个环节,从实施流程上规范App交付的各个环节,如优化需求拆分、强化代码评审等步骤,提高代码质量。

 

● 自主开发小型工具,如App持续交付工具、挡板系统等,完善上述流水线,以提高开发、测试效率。

 

2、进行组织结构调整,开展开发测试融合实践。

 

● 在开发测试融合思维的导向下,开发与测试团队被规划到同一部门,这消除了部门壁垒,使得敏捷迭代中开发、测试成为一个整体,强化了二者的沟通和联系。

 

● 强化质量监督环节,测试团队发挥QA作用。测试团队不再仅仅负责传统的测试工作,而是统筹测试实施、质量管理、工艺改进三大板块。在这种模式下,测试团队不仅仅负责传统的测试实施任务,还要深入敏捷团队,担任QA角色,监督自动化测试、持续集成等环节,从更高层次上把控产品质量。

 

● 开展DevOps相关的交流活动,如开放日、系列培训等,在部门内部、部门之间进行推广和交流,互相借鉴经验,培养员工的持续交付理念和能力。

 

(三)构建持续交付流水线

 

在各类资源有限的情况下,我们必然要借助现有工具来支持持续交付实施过程。作为最受欢迎的CI工具之一,Jenkins成为我们的首选平台。它以插件的形式支持各种功能(官方提供了丰富的插件库,开发者也可以根据官方API开发定制化插件)。此外,Jira、Sonarqube等受业界认可的工具成为流水线的组成部分。

 

1、App持续交付流水线

 

正所谓“工欲善其事,必先利其器”,自动化流水线的搭建必然需要借助工具。业界对于持续交付流水线工具的选择,可以大概分为两类:一是使用通用的CI、CD工具,二是使用一体化DevOps平台。前者灵活通用、不需要太多成本,但缺少业务元素;后者提供一站式解决方案,但通用性不强。

 

既然短时间内不具备采购或自主开发一体化DevOps平台的条件,我们选择前者来实现交付流水线。如图1所示,将各个环节如同串珠子一样串联起来,组合成完整的流水线。

 


图1 App交付流水线

 

1)需求/知识:需求决定了任务量,进而决定了开发、测试的工作量,也直接影响代码的质量。因此,要从流水线源头进行改进,避免因需求规划不合理影响开发效率。

 

 过去:存在需求堆积、粒度过粗、变化频繁,把开发“逼疯”的情况;过分依赖人工看板,不容易统计迭代燃尽图、故事活跃度等数据。 

 现在:合理规划需求、减少任务粒度,减轻迭代工作量,为实现小步交付做准备;使用Jira电子看板,方便存档用户故事、问题等,更好地把控敏捷健康状况。

 

2)源代码:使用SVN或Git托管代码。代码库也有鄙视链,在大多程序员看来,似乎Git才是更“高级”的工具。其实,无论是SVN还是Git,都具备相当完备的功能,选择哪一种工具并不重要,关键的是如何规范使用。

 

 过去:由于并行任务多,分支策略混乱,代码整合起来很复杂,耗费人力。 

 现在:逐步转换成串行任务,采取主干开发策略,减少产品并行开发的情况;强化代码提交纪律,如要求开发必须经过本地构建成功、单元测试通过、规范检查通过后方可提交,且注意及时拉取和提交代码。加强对关键逻辑代码的管控和审查,改进代码评审方式。

 

 过去:人工走查的方式,经常一拖再拖,积压了大量代码,导致走查时耗费大量时间,效果也难以保证。 

 现在:利用相关工具(如Gerrit)实施代码评审环节,取代原始的人工走查。这样既可以及时发现问题,又能减少开发人员的工作量。

 

 过去:CI纪律形同虚设,常有构建失败无人处理的情况。 

 现在:强化CI纪律,每个敏捷组配置红绿仪表盘,实时查看动向。若有构建失败,立即进行修复,修复不成功全组不下班。

 

3)代码拉取:Jenkins从代码库拉取代码、触发后续流水线/Job构建。这通常是Jenkins Job执行的第一步。

 

4)自动化测试:主要分为自动化单元测试、自动化接口测试、自动化UI测试三部分。其中自动化单元测试作为Job的一个环节,随着Job构建而执行;而其他两类自动化测试则借助专门的自动化工具(RobotFramework、Appium)实施,在Jenkins上进行相应配置,可定时触发和构建自动化测试Job。

 

5)静态代码扫描:对于代码的质量,不能仅仅局限于那些“可视的”bug。代码中往往存在大量潜在的问题,如健壮性问题、浮点数比较大小等,不容易被发现,但就像定时炸弹一样,是产品质量的隐患。因此,我们借助静态代码扫描工具进行代码扫描。例如,Sonarqube工具为各开发语言提供了静态代码扫描支持,用户也可以自定义自己的规则。对于扫描出的各类问题,要求开发尽快解决。此外,Sonarqube还可以读取自动化单元测试报告,并将单元测试结果展示在其仪表盘上,方便相关人员随时了解代码质量。

 

6)安全扫描:增加安全扫描环节,提高代码安全性。以Checkmarx安全扫描工具为例,在流水线中引入Checkmarx插件,触发安全扫描环节。同时,对于扫描报告中出现的问题,要求开发予以解决,将问题及时归零。

 

7)App加固:App进行加固处理,防止被反编译。

 

 过去:使用客户端进行加固。 

 现在:为了将加固环节自动化、纳入持续交付过程,使用shell脚本调用加固命令,取代手动加固。

 

8)构建:前面的环节都是为了这一步做准备。对App产品而言,最终构建的结构是生成安装包(ipa或apk)。App开发涉及开发、测试、灰度、生产环境,如何保证其处理环境参数外,其他代码完全一致,是值得我们关注的问题。对此,我们借助Jenkins的Pipeline流水线,提出并行构建机制。

 

 过去:开发一般在开发、测试环境下编写代码,通过测试后,手动修改代码里的环境配置,然后构建出对应的生产版本,用于后续投产。若这个过程中有人修改了功能性代码,则构建出的生产包包含未经过测试的代码,直接投产的风险可想而知。 

 现在:项目代码设置多环境(开发、生产、测试等环境)配置,执行构建命令时可指定环境,从而构建出对应环境的App版本;使用Pipeline并行脚本,同时构建出多个环境参数的版本,这几个版本除了环境配置不同,其他完全一致。在选取生产版本时,强制选择其中的生产版本,该生产版本和测试版本同时被构建出,不存在被修改代码的可能,可以保证App功能测试版本和生产版本一致性。

 

9)制品:制品即安装包,也就是构建出的版本,将被推送至App持续交付工具进行统一管理。

 

2、流水线中的工具建设

Jenkins不是万能的,它只提供了一个纯粹的流水线引擎,不包含业务属性。也就是说,Jenkins上的流水线无法关联软件管理周期中的需求、项目、任务、产品等元素,它们只能是一个无层次的平行Job的集合。因此,上述环节并不能满足App建设的实际需要。为此我们自主研发了几个工具:App持续交付工具、QA仪表盘、多协议挡板系统、错题本,以进一步提高交付效率。

 

 App持续交付工具:App产品版本管理的平台,提供开发、测试、交付功能。

 

1)可对接Jenkins平台,获取Jenkins制品,并按照其对应的环境参数,分阶段统一管理,解决Jenkins Job无序、缺乏制品管理的问题;

 

2)App可通过扫描二维码进行下载安装,取代原有的手工分发模式,极大地提高测试效率。

 

3)提供灰度发布功能,用于App的灰度测试。

 

 多协议挡板系统:提供模拟接口,用于环境不联通导致真实接口无法调用的场景。开发人员不再手动编写假数据,而是像调用真实接口一样调用挡板模拟出的接口,解决环境不通引发的进度阻塞问题。

 

1)实际开发阶段、测试前期中,往往会遇到接口不通的问题,影响开发进度,使用该挡板可以Mock接口。

 

2)现有接口不具备复杂数据、特殊场景等,对测试异常情况造成困难,此时可以使用挡板模拟特殊数据,进行相应测试。

 

 QA仪表盘:必要的质量监督环节可以提高开发、测试的QA意识,QA仪表盘是对流水线质量数据进行收集和统一展示的平台。尽管我们可以从SVN、Jenkins、Sonar上看到相应的数据,但它们基于分散的Job,无产品关联信息,且缺少统计类数据。为了更好地发挥质量监督作用,我们开发了QA仪表盘,将各个环节质量数据进行收集、加工、展示。

 

1)以产品为基本维度组织数据,并进行团队、部门等不同层级的统计和展示。

 

2)提供邮件订阅等个性化功能,方便用户定期监督产品质量数据。

 

 错题本:顾名思义,这是一个记录质量问题的平台。各个阶段注入的问题(需求、开发、测试分析、测试实施、运营等)都可以纳入这个平台,并进行详细跟踪记录。测试经理也会定期从错题本导出问题,组织质量问题分析会。通过及时记录问题、分析问题,可以为以后的测试分析积累经验,避免同类质量问题重复出现,减少日后“踩坑”的几率。

 

(四)开发测试融合组织形式 

 

开发测试融合与敏捷实施是相辅相成的。从组织结构上看,将开发、测试团队融于同一部门,其中测试团队承担部门的测试实施、质量管控、工艺改进(工具建设)工作;产品以敏捷组为单元开展任务实施,敏捷组里包含PO、开发、测试,逐步建立起一个全功能敏捷虚拟团队。通过这样的组织调整,加强测试与开发的联系,也增强敏捷团队的集体意识,有利于培养DevOps文化氛围。

 

伴随着上述组织调整,测试团队的职能也发生了改变。过去,测试团队的主要任务是实施测试任务,测试经理们重点关注的是案例执行情况、测试流程等;而随着开发测试融合的推进,我们赋予了测试经理更多的话语权:测试经理承担产品QA角色,从产品需求到投产阶段结束,关注整个工程活动周期的质量问题,如用户故事质量、单元测试情况、缺陷分析等,建立QA全流程质量控制机制。从这个角度讲,测试经理要不断提高自身能力,培养更全面的质量意识。

 

三、案例效果

 

经过上述一系列提升和改进工作,App产品的交付效率有了明显改善,各敏捷小组的质量意识和CI意识也得到了显著提升,DevOps的氛围已经形成。

 

1、App产品的迭代速率明显提高。得益于App持续交付流水线的有效实施,任务下达至完成时间明显缩短。App持续交付工具、挡板等工具得到了有效推广,工具赋能对于开发、测试效率提升发挥了巨大作用。

 

2、迭代质量显著提升。2018年以前,部门迭代成功率仅为70%,2019年已提升至93%。迭代过程中,持续交付流水线的构建成功率也保持在80%以上。

 

3、产品质量明显提升。开发更加注重自己的代码质量,并在QA的监督下关注自动化测试数据,从而使开发团队的Bug数量明显减少。自动化接口测试积累了大量案例,自动化单元测试覆盖率从无到有,从有到高,目前部分产品覆盖率已达90%以上。



本文介绍的实践案例仍处于初级阶段,App持续交付流水线还存在很大的提升空间。未来,计划进一步优化持续交付流水线,扩展工具功能,深化DevOps实践。