点击关注“有赞coder”
获取更多技术干货哦~
无需重新发版,实时高效修复bug;
用户无感知修复,无需下载新的版本,代价小;
修复成功率高,能把损失降到最低;
因此热修平台愈加重要,需要搭建一个高效,好用且安全的热修复平台。
每次版本打包发布,如何保存基准包及mapping等文件用于后续热修生成补丁?
热修代码的分支如何规范管理?
如何构建补丁包,构建了如何保存 ?
补丁包如何快速高效的本地验证 ?
补丁发布策略,发布审批等
补丁下发数据如何统计?
针对特定用户怎么查询热修状态?
热修出了问题怎么定责,怎么对热修代码追溯?
支持打包文件保存
定义标准的热修分支规范
支持补丁包的构建保存
支持方便的本地验证测试
支持权限审批
支持补丁全量,灰度及条件发布
支持热修状态查询,数据统计
支持历史热修代码查看
CI
系统的产物。下游则是 C 端用户,作为应用发布生命周期的最后一环,为所有应用补全了热修复 和 灰度分发相关的能力。Tinker
首先要考虑的是构建产物及 mapping
等文件的保存,用于后续打补丁包apk&mapping
文件。MBD 构建平台打包是在运行着 GitLabRunner
的黑苹果上进行的, GitLabRunner
是 GitLab
基于 Go
实现的脚本解释器,如果感兴趣可以自行了解下,这里不再展开。yaml
格式,其中 artifacts
指定哪些文件要上传到 CDN
, 配置中的 paths
中指定了 Tinker
构建产物目录 bakApk&mapping
,因此Tinker 产物会上传到 CDN
, 脚本如下:
build:Git API
artifacts:
untracked: false
name: "out"
preview_pattern: "app-full-release.apk"
cdn_path: "xxxxxxxx"
paths:
- app/build/bakApk
- app/build/outputs/apk/
- app/build/outputs/mapping/full/release/
script:
- env
- ./gradlew clean assembleFullRelease -PTINKER_ID=$CI_BUILD_ID -PBAK_PATH=$CI_PROJECT_DIR/app/build/bakApk -Paar=$JOB_COMPONENT_DEPENDENCIES -PMBD_RELEASE=$JOB_BUILD_RELEASE -PMBD_TEST_VERSION=$JOB_COMPONENT_VERSION -PMBD_BRANCH_NAME=$CI_COMMIT_REF_NAME --no-daemon
1. 应该从哪个分支拉取代码修改打补丁?
2. 修复问题后热修代码合并问题?
bus/${version}-${date}
的分支,在 bus/${version}-${date}
分支打出包后,开发同学自测然后交由项目的测试回归,没问题后,最后经App的测试同学回归,回归通过后开发同学会将 bus/${version}-${date}
分支合入master 构建 release
包。release
版本构建时的 commit hash
。release
版本都有一个固定的热修分支为 hotfix/${version}-mbd
,热修分支的管理也是直接由MBD构建平台统一规范处理的如图所示:App2.3.5
版本发现问题需要热修复:首先要在MBD 构建平台搜索 2.3.5
版本的 release
集成单, release
集成单中包含一个热修复按钮
点击热修复按钮判断 2.3.5
版本是否已经存在 hotfix/2.3.5-mbd
分支?
存在直接创建热修复集成单,不存在MBD平台调用 GitLabAPI
创建 hotfix/2.3.5-mbd
分支
开发者在 hotfix/2.3.5-mbd
拉取创建修改问题的分支,如 hotfix/xxx_bugfix
应该从哪个分支拉取代码修改打补丁?
的问题,合并到哪个分支的问题,暂且不表,下文会讲到。CDN
,再次构建时 MBD 平台只需把产物下载解压到 Tinker
基准包路径,
同App打包逻辑,热修构建也是通过 yaml
脚本配置,指定要上传补丁文件的相对路径,补丁构建命令执行结束后会上传补丁文件到 CDN
,用于后续补丁下发,简要过程如图:patch:
artifacts:
untracked: false
name: "patch"
preview_pattern: "patch_signed.apk"
paths:
- app/build/outputs/apk/full/tinkerPatch/full/release/patch_signed_7zip.apk
- app/build/outputs/apk/full/tinkerPatch/full/release/patch_signed.apk
script:
- env
- pwd
- mv app/build/bakApk base/
- ls base/
- ./gradlew clean tinkerPatchFullRelease -Paar=$JOB_COMPONENT_DEPENDENCIES --no-daemon -POLD_BUILD_FLAVOR=$CI_PROJECT_DIR/base
- rm -rf base
Tinker
也提供了加载本地补丁包的 API
:TinkerInstaller.onReceiveUpgradePatch(context, 补丁包的本地路径);
CDN
文件下载到特定路径,在App重启时检测补丁文件是否已下载,如果已下载直接加载补丁即可。补丁MD5 安全校验 、签名
补丁 CDN 地址
补丁对应App版本及基准包 CDN 地址
补丁对应App包名
Tinker
的机制补丁本地合成后,需要再次冷启动使补丁生效。userId == 10023451 && roleType == 1
若第一次下发补丁,包含了条件值,不符合条件的设备补丁不会生效。
若非第一次下发补丁,上一个补丁版本是全量下发,不符合条件的设备会请求上一个版本补丁。
若非第一次下发补丁,上一个补丁版本非全量下发(灰度/条件/开发),不符合条件的设备若之前请求过补丁,会保留执行之前的补丁,若没有请求过补丁(新用户),不会请求到补丁。
A
同学需要修改 App2.3.5
版本的问题,发布热修复。开发者需要从 hotfix/2.3.5-mbd
拉取 hotfix/xxx_bugfix
分支
在 hotfix/xxx_bugfix
分支修改问题并构建补丁
接着申请发布补丁,在审批通过之后,发布热修的同学在 Apub
平台上操作下发在 MBD平台构建并上传到 CDN
的补丁
Apub
发布平台在 A
发起审批时,自动创建了 hotfix/xxx_bugfix->hotfix/2.3.5-mbd
的 MR
并自动写入审批单申请理由中。
在 A
点击下发补丁时调用 GitLabAPI
获取 MR
状态,如果 MR
已合并则允许下发,否则提示 A
催促审批人合并代码才可下发补丁
最后下次发版时将 hotfix/2.3.5-mbd
分支添加到下一趟发版列表中,将 bug
修复代码带到下一趟车中,最终合入 master
GitLabMR
, 即可查看代码变更。开发者在 MBD平台搜索需要热修版本的集成单,点击热修复按钮,MBD会创建 hotfix/2.3.5-mbd
分支,同时创建一个热修集成单 (MBD 构建平台每个App构建,热修构建,SDK构建都是一个集成单)
开发者需要从 hotfix/2.3.5-mbd
拉取创建 hotfix/xxx_bugfix
分支
在 hotfix/xxx_bugfix
分支修改问题提交代码并在MBD平台创建的热修集成单上操作构建补丁
然后使用有赞移动助手App 扫码验证补丁
接着在Apub发布平台选择热修发布方式,填写申请发布理由申请发布补丁,Apub 平台会自动创建 hotfix/xxx_bugfix
-> hotfix/2.3.5-mbd
的 MR
,并把 MR
地址自动填充到申请理由中,开发者等待审批,审批通过之后,确认 MR
合并,即可发布操作下发补丁
MR
等逻辑