本文内容为极客时间《持续交付 36 讲》学习笔记

极客时间《持续交付 36 讲》课程作者王潇俊(携程系统研发部总监)

一、交付流水线

后端持续交付流水线包括了:代码管理、环境管理、集成和编译管理、测试管理,以及发布管理这五个核心过程。而与之相比,移动 App 的运行形势决定了其在环境管理方面没有特别多的要求。

二、APP 交付特点

移动端的 APP 交付特点包括:iOS/Android 两套环境、分支管理复杂、编译速度慢、应用市场审核速度慢、热修复技术限制、组件化的依赖管理问题等。

三、依赖管理

Android - Gradle

iOS - CocoaPods

H5、Hybrid - NPM

四、项目信息管理

版本信息管理

功能信息管理

五、构建管理

通过代码变更,触发自动的持续集成。集成过程基本遵循:拉取代码、静态检查、编译构建、自动化测试,以及打包分发的标准过程。

移动 App 和后端服务的持续交付体系,在构建管理上的不同点,主要体现在以下三个方面:

  • 你需要准备 Android 和 iOS 两套构建环境,而且 iOS 的构建环境还需要一套独立的管理方案。因为,iOS 的构建环境,你不能直接使用 Linux 虚拟机处理,而是要采用 Apple 公司的专用设备。
  • 在整个构建过程中,你还要考虑证书的管理,不同的版本或使用场景需要使用不同的证书。如果证书比较多的话,还会涉及到管理的逻辑问题,很多组织都会选择自行开发证书管理服务。
  • 为了解决组件依赖的问题,你需要特别准备独立的中央组件仓库,并用缓存等机制加快依赖组件下载的速度。其实,这一点会和后端服务比较相像。

六、运营管理

指追踪、分析和调优这个版本发布的表现和反馈。主要关注的内容包括:奔溃报告、区域分析、用户分析、系统资源消耗、流量消耗、响应时长、包体大小、系统监控,以及预警等。

七、热修复

目前原生开发模式热修复方案均受到较大限制,可通过 H5 等方案支持需要热修复的业务场景开发。

八、代码管理

8.1 静态代码检查

Clang Static Analyzer,被 Xcode 集成,但其缺乏代码风格的检查,可配置性也比较差;

OCLint,其检查规则更多,也更易于被定制;

Infer,是 Facebook 提供的一款静态检查工具,具有大规模代码扫描效率高、支持增量检查等特点。

8.2 发布快车

发布快车,就像一列由多节车厢组成的火车,每一节车厢代表一个发布版本,整个火车以一节节车厢或者说一个个版本的节奏,定期向前发车。而工程师们,则会把自己开发完成的功能集成到一节节的车厢上,这样集成在一节车厢的功能代码,就形成了一个新的版本。

第一个关键点是,并不是说所有开发的功能,都一定要集成到最近的那节车厢、最近的那个版本中。任何功能都应该按照既定计划,规划纳入到适合的那节车厢、那个版本中。这也是为什么移动端 App 的持续交付需要良好的信息管理的原因。

第二个关键点是,我们必须要保证固定间隔的发车时间,每周、每两周都可以,但必须保证每个车厢到点即发。只有这样,我们才能保证持续交付流水线的持续运行,以及不间断地产出。这里需要注意的是,对于一些特殊的、不规则的发布,我们要把它们归类到热修复的流程,而不是在发布快车中处理。

第三个关键点是,这个过程的最终产物是可以发布到市场的版本,而不是发布到用户侧的版本。虽然我们把这个发布模式叫作发布快车,但其实它的最终产物是可以发布的待发布版本。所以这个流程完成后的版本没有被正式发布,或出现了部分缺陷无法发布的情况是很正常的,可以被接受。我们并不需要保证每个版本都一定能发布到用户手上。

8.3 分支管理

发布快车模式适合使用 Gitlab Flow 代码分支策略来进行。

为了高效的持续交付,我们就必须对构建通道进行一定的改造。

我们会在功能分支合并入 Master 分支前,增加一次构建(Merge CI Service),这次构建的作用是保证功能分支的集成是成功的,否则不允许合并;同时,对于一个代码仓库来说,增加的这次构建过程要保证是串行的,即如果这个仓库正有一个合并构建在进行,则后续的合并构建需要等待。

这个合并构建过程,保证了 Master 分支上的任何 commit 随时都可以成功构建。之后再根据发布快车的要求定期启动版本构建(Auto CI Service),就能顺利地得到可测试版本了。

构建测试版本之后,流水线还可以继续处理,在 production 分支上打上对应的 tag。

九、发布管理

自动化的发布

iOS 系统的发布步骤为:构建,导出 ipa 包,记录符号表,备份,上传至 iTC;

Android 系统的发布步骤为:构建打包,更新渠道标识,签名,保存 mapping 文件,备份,上传至发布点。

利用 fastlane 工具可以实现高效快速的自动化发布:

fastlane/fastlane
fastlane/examples

十、效率提升

10.1 如何提升开发效率?

解耦,通过组件化形成合理的开发框架。

组件化是指,解耦复杂系统时将多个功能模块拆分、重组的过程。对于移动 App 来说可以横向地按功能模块进行组件化;也可以纵向地按照架构层次进行组件化。当然目前移动 App 的架构往往都已经比较复杂了,所以通常都是两者混合的模式。

10.2 如何提升构建效率?

扁平化依赖管理

通常情况下,一个移动 App 可以拆分出十几到几十个组件。大型的移动 App,如淘宝、美团,甚至可以拆分出几百个组件。要保证这么多组件间依赖传递的准确性,其难度非常大。所以,为了解决这个问题,业界现在普遍直接采用扁平化的依赖管理方式,减少甚至去除传递依赖,以此避免组件、版本冲突的问题。

扁平化管理方式,对于一个 App 版本来说,更清晰、直观。那么,实现这种扁平化的管理方式,需要具备什么前提吗。

答案,当然是需要。这个前提就是:不同组件之间,以及不同版本之间要保证可兼容。但是,你我都清楚,要想保证全部版本的完全可兼容性,其成本是巨大的。所以,在实践中,我们不会去保证所有版本的绝对兼容,而是去实现所有版本、组件间的相对兼容性。

相对兼容性是指,每个组件在发布新版本时,对于其所依赖的其他组件,都选择组件仓库中的最新版本。这样就保证了这个组件在发布之后的兼容性。如果所有组件都可以这么做,就能保证其各自都兼容。但是这个方法不是绝对的,比如我们会遇到并发发布,或者多个组件间引起的功能逻辑的冲突等问题,所以还是需要对移动 App 进行集成测试。

二进制交付

二进制交付,会优先把组件编译成二进制包,再形成版本,并通过组件仓库进行版本管理。在真正编译时,我们只要直接链接二进制包就可以了,无需再进行一次编译。

10.3 如何提升测试效率?

代码静态扫描工具。

移动 App 的测试,同样可以使用与后端服务一样的代码静态扫描工具。但相比之下,后端服务通常使用的那些工具虽然普适性强,但太重且定制的门槛也很高;所以针对移动 App 的代码静态扫描,目前多数大厂都采用自研的方式,定制静态代码扫描工具。另外,针对移动 App 开源的静态代码扫描工具,如 Lint 等,已经可以满足小团队的使用了。

UI 自动化测试。

这部分的关注点是成本和收益比,你我都清楚,UI 自动化测试的脚本维护成本高,导致其难以被大规模使用。所以,针对重要的模块和组件,有计划地使用 UI 自动化测试是重中之重。

自动 Monkey 测试。

Monkey 是一款非常好用的探索性测试工具,可以大幅提升测试效率,有效解决手工测试的盲点。iOS 系统的测试,由于系统限制比较多,所以可以在模拟器上执行 Monkey 的方式。

10.4 如何提升发布效率?

要注意分发的精准性。

精准性指的是,分发的目标、数量、时长,以及渠道一定要合理、有效,否则就会消耗无谓的分发成本。

使用动态灰度名单方式避免影响用户体验和测试结果。

要注意分发的稳定性。

稳定性指的是,在分发的过程中,一定要做好监控数据的收集和分析,并且要考虑好风险的处理以及必要的回滚和热修复手段。