← 返回主页
Jenkins CI/CD HarmonyOS Playwright 双端发布

一条流水线,两个系统:股宇宙双端自动化打包实录(Android + HarmonyOS)

2026.09 · by Easin

股宇宙 APP 有了鸿蒙版之后,打包从"一条命令"变成了"两套流程"——Android 签名、蒲公英上传、鸿蒙签名、AGC 发布、下载页更新,每一步都机械但都不能错。这篇记录我怎么把五个手工步骤压进一条 Jenkins 流水线:Playwright 无头浏览器过蒲公英的验证码,tkinter 弹窗让签名密码不进脚本、不进日志,一次提交双端齐发。

一、为什么要做双端流水线

股宇宙现在有两个端:Android(Kotlin + Compose)和鸿蒙 HarmonyOS(ArkTS + ArkUI,DevEco Studio 构建)。在此之前,每次发版是这样的:

步骤多、依赖人、容易漏:忘改下载页版本号、传错通道、密码贴在聊天记录里……这些事故每一件都真实发生过。所以在打通了 GitLab → Jenkins → 企业微信通知之后,下一步自然是把打包发布本身也自动化——而且要一次覆盖两个系统。

二、流水线总览

现在的一条流水线长这样,全程无人值守:

开发者 push(双端任一仓库)
   │
   ▼
GitLab Webhook → Jenkins(Windows 打包机,有桌面环境)
   │
   ├─ ① Android 签名打包(Gradle assembleRelease)
   │      └─ 签名密码:tkinter 弹窗人工输入(不落盘)
   ├─ ② 上传蒲公英(pgyer API)
   │      └─ 登录凭证:Playwright 无头浏览器预先换取
   ├─ ③ 鸿蒙签名打包(hvigor → hap → 签名)
   │      └─ .p12 / .p7b 签名材料同样弹窗解锁
   ├─ ④ 上传 AppGallery Connect(AGC API)
   └─ ⑤ 发布 GitHub Pages(更新扫码下载页版本)
   │
   ▼
企业微信通知(成功/失败 + 二维码 + 双端下载地址)

一次提交,两个系统的包同时就绪,下载页自动更新。下面按环节展开。

三、Android 签名:密码不进脚本,也不进日志

签名是打包里最敏感的一环。密码写 Jenkins 凭据库当然可以,但我们的打包机有桌面环境,于是选了个更"物理隔离"的方案——tkinter 弹窗:

这个设计换来两个好处:密码轮换零成本(改密码不用改任何配置),泄漏面趋近于零(日志里翻不到、进程列表里看不到明文)。代价是每次构建要人守一下——对发版频率不高的我们来说,完全可接受。

细节:弹窗脚本要处理无显示器会话下 tkinter 起不来的情况(Jenkins 服务方式启动时可能没有交互桌面),我们的打包机以"允许服务与桌面交互"方式运行 Jenkins agent,弹窗才能正常弹出。

四、上传蒲公英:Playwright 过验证码

蒲公英的 API 上传需要用户凭证,而我们的账号启用了登录验证——直接拿 token 会遇到验证码拦截,curl/HTTP 客户端在这里全部失效。

解法是用 Playwright 无头浏览器模拟真实登录:

  1. 流水线触发时,Playwright 启动无头 Chromium,打开蒲公英登录页;
  2. 遇到验证码环节,把验证码图片实时推送到企业微信,打包人直接在群里回复验证码;
  3. 登录成功后提取会话凭证交给上传环节使用,浏览器关闭。

这个"验证码进群"的设计有点歪打正着:它把本来要打断开发者的安全验证,变成了一条群消息——验证码出现在你要收打包通知的同一个地方,心智负担反而更低。

五、鸿蒙端:把 HarmonyOS 签名也压进流水线

鸿蒙的构建比 Android 多一层:DevEco Studio 里点一下就能完成的签名,在命令行下是三份材料的组合——.p12 证书、.cer 公钥证书、.p7b Profile 文件,用签名工具对 hap 包签名。流水线化的关键动作:

做完之后回头看,鸿蒙端流水线化最大的收获不是省时间,而是签名一致性:本地手动签名容易出现"用了错的 Profile"这种事故,流水线只认固定路径的签名材料,从机制上杜绝了拿错证书的可能。

六、发布到 GitHub Pages:下载页自动更新

最后一环是扫码下载页(就是用户扫码进的那个页面)。流水线在上传成功后自动:

  1. 写入本次双端的版本号、构建时间、蒲公英/AGC 链接;
  2. 推送更新到 GitHub Pages 仓库;
  3. 下载页二维码指向的地址永远是最新的包。

"忘改下载页"这类事故从此从可能项里消失了——因为没有任何人工环节可以忘。

七、踩坑清单

坑现象解法
Jenkins agent 无交互桌面tkinter 报错 / 弹窗不出现agent 以"允许服务与桌面交互"方式运行
蒲公英验证码API 直传被拦截Playwright 无头登录 + 验证码推企业微信
密码进日志环境变量方式被打进构建日志改为 tkinter 弹窗内存输入,日志脱敏兜底
鸿蒙签名材料混乱调试/发布 Profile 用错固定目录存放 + 流水线只读引用
AGC 上传 API 鉴权token 有效期与构建时长冲突上传前实时获取 token,不做长缓存
下载页缓存更新后手机仍显示旧版本页面资源带版本参数,强刷 CDN 缓存

八、下一步展望

九、小结

这条流水线做完,最大的体会是:自动化的价值不在"快",而在"确定性"。手工五步,每步都简单,但串起来每次都有出错概率;流水线把它们变成同一次执行、同一套材料、同一个来源——发版从"凭仔细"变成了"凭机制"。双端齐发这件事,也从奢侈变成了日常。

Easin's Code Lab · 作者:Easin ← 返回主页 · 相关:Jenkins 打包通知体系 · GitHub ↗