打包、签名与发布
客户端做得再好,签名错了发不出、证书泄露被吊销、发版靠手工人肉,都会把交付变成事故现场。本页把签名原理、渠道分发、CI/CD 与热更合规一次讲清。桌面侧(macOS 公证、Windows 签名、自动更新)在桌面应用有对照,本页以移动为主。
签名:一句人话理解
签名 = 用你的私钥给包盖章,系统用公钥/证书链验证「这包确实来自声明的主体、且没被篡改」。所以两件事要命的:私钥一旦泄露,别人能用你的身份发包;证书过期/吊销,已装用户的更新链路会断。
| 平台 | 私钥/证书 | 描述文件/授权 | 关键点 |
|---|---|---|---|
| iOS | Apple Developer 证书(开发/分发) | Provisioning Profile + Team | 设备信任链:包签名 + 描述文件决定能装在哪 |
| Android | keystore(jks) | 系统校验签名算法 | v1(JAR)/ v2 / v3(可轮换)/ v4;Google Play 用 App Signing |
| macOS | Developer ID 证书 | 公证(notarization) | 不公证 → Gatekeeper 拦下载 |
| Windows | 代码签名证书 | — | 没签名 → SmartScreen 红色警告 |
iOS 签名要点
- Xcode 自动管理签名(Automatically manage signing)开发期够用:Xcode 用你的 Team 自动生成证书与描述文件;
- 上架/对外分发的证书与描述文件要在 CI 里稳定复现:推荐 Fastlane match(把证书放进加密 git 仓库,按类型区分 development / appstore,一条命令同步);
- 描述文件过期要提前续:设日历提醒,别在发版日才发现;
- 设备限制:开发描述文件有设备数上限,新人入职要更新注册。
Android 签名要点
- keystore 是单点资产:生成即备份、设置强口令、绝不能进 git;
- 上架 Google Play 推荐 Play App Signing:上传包用「上传密钥」签,最终用户包由 Google 用「应用签名密钥」签——好处是丢了上传密钥可找回,坏处是应用签名密钥不可导出;
- 国内各市场收 APK/AAB 用同一 keystore 签名即可,别每渠道单独生成密钥(无法统一升级);
- 新版支持密钥轮换(v3),轮换需旧密钥在场一次完成。
版本号规范(统一全局)
- 语义版本:
版本名给人看(1.4.2),构建号/版本号给机器(数字单调递增); - iOS:
CFBundleShortVersionString(1.4.2)+CFBundleVersion(构建号);TestFlight/App Store 都要求递增; - Android:
versionName(1.4.2)+versionCode(整数递增);国内渠道有时要求同步改名/号; - CI 里一处定义、处处引用:从 git tag 或单文件读版本,生成原生配置,避免 iOS/Android/桌面三处手改不一致。
多环境构建:别让测试包进生产
| 维度 | 做法 |
|---|---|
| 环境地址 | 构建变体注入:iOS Scheme 环境、Android BuildConfig/变体、Flutter --dart-define、RN bundle 环境 |
| 产物区分 | 包名/bundle id 按环境隔离(如 com.example.app.dev),同一台机可并存调试 |
| 开关与日志 | 环境相关功能(mock、日志级别)随变体收敛,release 自动关闭 |
| 校验 | 发版前用「包内环境指纹」(版本+环境+commit)冒烟确认,杜绝手滑上错环境 |
iOS 分发流程
- Archive(归档)→ 自动签名;
- TestFlight 内测(内部成员,无需审核)与外部测试(需 Beta App Review,审核松于上架);
- 上架提交 App Store Connect → App Review(关注:隐私问卷、权限用途、截图与实际一致、不可用占位内容);
- 审核通过后可设置「分阶段发布」(1%/10%/50%/100%)观察崩溃与评分再放量。
要点:StoreKit 与支付规则、IDFA/隐私清单、第三方登录规则是常见被拒雷区,上架前对照 App Review 指南自查。
Android 分发流程
- 打 AAB(
bundleRelease)上传 Google Play;国内渠道出各渠道 APK 或接入厂商 SDK; - Google Play 发布走轨道:内部测试 → 封闭测试 → 开放测试 → 生产,可设分阶段发布与自动回滚(按崩溃率);
- 国内渠道差异提醒(视当前政策与目标市场核对):
- 应用需完成备案/资质(软件著作权视渠道而定)才可上架;
- 隐私政策、权限弹窗、未成年人保护等合规材料各市场模板不同;
- 部分渠道有自己的加固要求(混淆/加固后需保留原始 mapping 便于解栈)。
桌面分发与自动更新
macOS 公证、Windows 代码签名、Linux 打包格式 + 自动更新签名绑定——见桌面应用。
CI/CD 发版流水线
一个可复用的移动发版流水线(GitHub Actions + Fastlane 示意):
yaml
# .github/workflows/release.yml(结构示意)
name: Release
on:
push:
tags: ["v*"]
jobs:
ios:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- run: bundle install
- run: bundle exec fastlane beta # match 同步签名 + gym 构建 + pilot 上传
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APP_STORE_CONNECT_KEY: ${{ secrets.ASC_KEY }}
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "${{ secrets.KEYSTORE }}" | base64 -d > keystore.jks
- run: ./gradlew bundleRelease流水线纪律:
- 签名材料只进 secrets,CI 运行时解密,构建机不留明文;
- 产物生成后上传并校验指纹(sha256),避免「构建成功但包不对」;
- 触发即版本:tag 打上 → 自动出包 → 上传 → 测试邀请,全程无人工登录开发者后台;
- Fastlane match 仓库密码与开发者 API key 分开保管、定期轮换,离职即轮换。
灰度与回滚
- 灰度看什么:崩溃率(按版本对比)、启动失败率、关键转化;设自动暂停阈值;
- 回滚不是重发:服务端开关先行(feature flag 能关的功能别只靠发版关)、旧包保留随时可回滚、数据兼容双向(旧包能读新数据);
- 发布窗口错峰:避开大促与节假日,留观察窗口再全量。
热更新与合规红线
- iOS 明确不允许下载代码改变应用行为(App Review Guideline 对「下载可执行代码/改变功能」的约束历史严格,曾有 JSPatch 类方案被下架先例);可接受的更新是「不改变行为的内容/资源」(文案、图片、配置),且争议线常在灰色——含代码热更的产品要自行评估风险;
- Android 政策对代码热更相对宽松,但同样不得绕过商店审核做违规更新(合规以目标市场当时政策为准);
- RN/Flutter 的 OTA JS bundle 更新(如 CodePush 思路)本质是下载脚本执行,跨端框架也受同样规则约束,别以为跨端就豁免;
- 合规底线三条:a) 不做绕过审核的「马甲更新」;b) 热更失败要有版本兼容与回退;c) 每次「静默更新功能逻辑」都记录审计。
常见坑速查
| 坑 | 现象 | 对策 |
|---|---|---|
| keystore 进 git | 泄露=任人签名 | 只进 secrets,加 .gitignore |
| 描述文件过期 | 新装/更新全失败 | match 集中管理 + 过期日历提醒 |
| 版本号没递增 | 上架被拒/更新不提示 | 版本号一处定义,CI 校验递增 |
| 测试包上生产 | 用户用测试地址 | 变体隔离 + 包内环境指纹校验 |
| 签名/公证只在本地 | 换人换机发不了 | 全流程 CI 化 |
| 密钥一人保管 | 离职即瘫痪/泄露风险 | secrets 保管 + 轮换 + 双人复核 |
| 不发灰度 | 全量后崩溃率爆炸 | 分阶段发布 + 自动暂停阈值 |
| 只留最新包 | 回滚无旧包 | 产物归档保留 N 个版本 |
| 热更覆盖逻辑 | 被下架风险 | 先读合规红线,代码变更走正规发版 |
| 国内资质不全 | 审核被退回 | 上架材料清单前置核对 |
检查清单
- [ ] 签名资产安全:私钥/证书只在 secrets,轮换与备份有制度;
- [ ] 版本号一处定义、构建自动递增校验;
- [ ] 多环境包名/地址隔离,release 产物环境指纹校验通过;
- [ ] iOS 走 TestFlight + 分阶段上架,审核红线提前自查;
- [ ] Android 渠道资质/隐私材料齐全,Play 分轨道发布;
- [ ] CI 全流程出包上传,指纹留档,灰度指标与自动回滚阈值已配;
- [ ] 热更方案完成合规评估,失败有回退。