CI/CD 与发布体系
“从代码提交到用户手里的安装包,中间的自动化流水线不仅是效率工程,更是质量把控的最后防线。”
面试策略: 讲清楚持续集成(CI)的核心质量卡点,以及持续交付/部署(CD)中的版本、签名和多渠道策略,这能展现你对工程闭环的把控力。
一、CI/CD 核心概念与工具
- CI (Continuous Integration, 持续集成): 开发者频繁提交代码,流水线自动触发编译、静态代码检查(Lint/SonarQube)和自动化测试。目标是尽早发现缺陷。
- CD (Continuous Delivery/Deployment, 持续交付/部署): 自动将打好的包发布到测试环境,或者打包带有生产环境签名的正式包上传到应用商店/分发平台。
- 常用工具:
- Jenkins:老牌开源,可高度定制,适合企业内网部署。
- GitLab CI / GitHub Actions:基于 YAML 配置文件直接存在代码库里(Pipeline as Code),开箱即用,越来越流行。
二、APK 与 AAB 构建体系
| 产物格式 | 核心原理 | 特点与应用场景 |
|---|---|---|
| APK (Android Package) | 包含所有的资源、ABI、DEX 文件。设备安装时全盘拷贝。 | 适合国内通过 CDN 下载直装、企业内部测试使用。容易出现包体积臃肿。 |
| AAB (Android App Bundle) | 一种发布格式(不能直接安装),Google Play 会根据下载设备(屏幕密度、ABI、语言)按需生成动态 APK。 | 大幅降低用户下载体积。Google Play 强制要求,适合海外出海应用。 |
三、渠道包与版本策略
- 多渠道打包 (Flavors):
- 国内通常需要向不同的应用商店(华为、小米、应用宝等)发布,使用 Flavor 或第三方工具(如 Walle/VasDolly)写入渠道标识,以便服务端统计各个渠道的激活率和转化率。
- 版本治理 (Version Code / Version Name):
versionCode必须递增,用于系统判断是否允许覆盖安装。versionName只是展示给用户的字符串。在 CI 中,通常将versionCode与 Git commit count 或者 CI 系统的 Build Number 绑定,保证其唯一和自增。
四、安全签名与构建产物管理
- 签名安全:
- 绝对不能把 Release Keystore 和密码放在代码库里。
- CI 中通常使用系统注入环境变量(Secrets),构建时通过临时解密或安全文件服务来签名。
- 产物归档 (Artifacts):
- 构建成功后,不仅要保留 APK/AAB,还要归档 Mapping 文件(混淆后的符号表)和 Native 符号表 (.so 的 debug symbol)。如果没有它们,线上的崩溃堆栈将是一本无字天书,无法定位问题。
五、灰度发布、降级与质量门禁
发布绝不是一键上线那么简单,需要配合严密的策略控制风险。
- 自动化质量门禁 (Quality Gates):
- PR (Pull Request) 阶段强制触发 CI。如果不满足:单元测试通过率 > 80%、静态扫描无 Critical 级警告,禁止合并代码。
- 灰度发布 (Gray Release):
- 先放量 1% 的用户,配合 APM 监控崩溃率、ANR 和核心业务指标。观察平稳后再放量 10%、50% 到全量。
- 兜底与回滚:
- 客户端发布覆水难收(旧版本无法撤回),必须要有热修复补丁(Hotfix)机制,或者通过配置中心下发开关进行功能降级,关闭引起崩溃的新功能。
高频面试题
Q1: AAB 相比 APK 有什么优势?如果国内应用商店不支持 AAB 怎么优化体积? 优势:AAB 将打包和分发的职责分离,Google Play 会根据用户设备具体情况(如只需要 hdpi 图片、arm64-v8a 库、中文语言包)裁切出特定的 APK,大幅减少体积。 国内不支持 AAB 时:可以利用 Gradle 构建配置分别打包特定 ABI 的分包(APK Splits),或者使用资源混淆(AndResGuard)、动态下发非核心动态库和大型资源等方式优化。
Q2: 如何保证 CI 环境打包和本地开发打包的结果一致性? 使用固定的基础镜像环境(Docker);强制使用统一版本的 JDK 和 Gradle Wrapper;禁止在脚本中读取个人计算机的环境变量;版本号和依赖全部锁定版本。
Q3: 线上出现严重的崩溃,无法发新版(审核慢),有哪些应急预案? 首先利用功能开关(Feature Toggle)从配置中心下发指令,关闭引发崩溃的入口(降级);如果无法关闭,利用热修复(Tinker、Robust)下发补丁修复逻辑;同时对未升级用户的应用商店渠道包进行下架或暂停灰度放量。
易错点 / 追问
- Mapping 文件丢失: 打完包丢弃了本次构建的 mapping 文件,导致崩溃上报后无法解混淆,这是灾难性的工程事故。
- 混淆配置未同步: CI 开启了 R8 混淆但没有在测试环境验证,直接上生产,由于反射或 JNI 类被裁减导致秒退。
- 密钥泄露: 将签名文件或 API Key 随代码 Push 到了公网 Github,安全风险极高。