ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Flutter库发布自动化:pub_release鸿蒙化适配全流程实践

Flutter库发布自动化:pub_release鸿蒙化适配全流程实践 1. 先搞清楚 pub_release 到底在解决什么问题1.1 没有自动化之前发布一个 Flutter 三方库有多痛苦做过 Flutter 三方库维护的应该都有同感真正磨人的不是写代码而是发布。我最早维护一个开源包的时候每次发版流程是这样的手动改pubspec.yaml里的版本号手动整理 CHANGELOG跑一遍flutter analyze和测试然后dart pub publish --dry-run检查有没有遗漏文件最后再执行真实发布等 pub.dev 那边构建通过还要打 git tag、推远端。这一套下来快的话二十分钟慢的话半小时以上而且每一步都靠人肉盯着稍不留神就出岔子。最常见的翻车现场有三个版本号改了但 CHANGELOG 忘更新仓库 tag 和 pub.dev 上的版本对不上以及发布包里的文件没过滤干净把密钥或者临时文件打进去了。这些都属于低水平但高频率的错误偏偏又特别消耗信任用户一发现你发布的包有问题下一次用之前就会犹豫。所以当我第一次看到pub_release这个工具的时候第一反应是终于有人把“发布”这件事当成正经工程来做了。1.2 pub_release 的核心能力拆解pub_release是一个专门面向 Dart/Flutter 包维护者的发布自动化工具它做的最核心的一件事情就是把“版本决策 发布动作 信息同步”整合成一条命令。你可以通过dart run pub_release publish来触发发布它内部会帮你完成语义化版本号的自动递增、CHANGELOG 的生成与更新、git tag 的创建与推送以及在真正pub publish之前自动跑一遍 dry-run 校验。这个工具最大的价值在于它把发布流程变成了一个可重复、可审计的过程。版本号怎么升升大版本还是小版本是 break change 还是 feature这些决策由你下但是执行过程由工具统一完成。团队协作时尤其好用不再依赖某个“记得住全部流程”的个人新人照着文档跑命令也能发布。这也是我后来下决心做鸿蒙化适配的原因——鸿蒙生态的开发链路已经逐渐成熟但发布工具链这块还存在不少断档值得花时间补上。1.3 鸿蒙化适配到底改什么不是代码移植是流程再造很多人一听“鸿蒙化适配”第一反应是代码怎么跨平台编译。但pub_release不一样它是纯 Dart 写的工具理论上跑在哪里都行。真正的适配难点在于它的发布目标原先只有 pub.dev而鸿蒙生态的三方库发布目标并不是 pub.dev而是 OpenHarmony 三方库中心仓用的是ohpm publish。这意味着我要保留pub_release的版本管理、CHANGELOG 生成、流程编排能力同时把发布动作换成鸿蒙生态的那套逻辑。所以“鸿蒙化适配”这个题目本质上是在做一次发布流程的再造。你需要同时考虑两个生态的双重发布需求pubspec.yaml和oh-package.json5双元信息同步pub.dev 与 ohpm 仓库的版本对应关系以及 Flutter 插件在鸿蒙侧的ohos目录能否被正确校验。这些都梳理清楚之后才算把“发布”这个事在鸿蒙环境下盘活了。2. 鸿蒙化适配的整体设计与工具链选型2.1 双元信息同步pubspec.yaml 与 oh-package.json5鸿蒙化适配过程中我踩到的第一个坑就是双元信息同步。Flutter 插件如果要跑到鸿蒙上光有标准的 Flutter 工程还不行OpenHarmony 侧一般会要求你维护一份oh-package.json5里面声明这个包的名称、版本、依赖和 RPC 标记等元数据。一开始我的处理方式很粗暴每次发布前手动同步两份文件的版本号。结果必然翻车某一版忘了同步Flutter 侧引用的是 1.2.0鸿蒙侧 ohpm 拉到的还是 1.1.2排查了大半天还以为是缓存问题。后来我把这个同步动作硬编码进了发布流水线用脚本读取pubspec.yaml里的version字段作为唯一真源再覆盖写入oh-package.json5的对应字段。核心思路就是永远不要让两份元数据各自独立演进必须定义一个唯一真源剩下的靠程序去对齐。# 伪代码示意同步版本号 PUBSPEC_VERSION$(grep ^version: pubspec.yaml | awk {print $2} | tr -d \) OH_PACKAGE_FILEoh-package.json5 sed -i s/\version\: \[^\]*\/\version\: \$PUBSPEC_VERSION\/ $OH_PACKAGE_FILE需要注意的是oh-package.json5是 JSON5 格式支持注释和单引号每个项目的写法多少有点差异所以 sed 的匹配规则要根据实际情况调整。我建议先在自己的工程里跑一次 dry-run确认版本号字段能正确替换之后再纳入 CI。2.2 流水线架构如何把 pub_release 嵌进鸿蒙生态聊到流水线架构核心问题就一个原有pub_release的发布动作还保留吗答案是分场景。鸿蒙化并不意味着放弃 pub.dev恰恰相反一个真正合格的 Flutter 三方库最好做到一套代码同时发布到两个仓库让 Android、iOS、鸿蒙的开发者都能很方便地用你的包。流水线分层上我是这样设计的第一层版本决策层。保留pub_release的语义化版本递增策略通过参数控制是发 major、minor 还是 patch 版本。第二层元数据同步层。版本号确定之后自动完成oh-package.json5版本同步以及 CHANGELOG 的追加。第三层构建验证层。跑 Flutter 侧的分析与测试同时检查鸿蒙侧的hvigor是否能正常装配依赖。第四层发布执行层。按需并行发布到 pub.dev 和 ohpm 中心仓。每一层之间用脚本解耦允许单独执行。这样本地开发和 CI 跑的是同一套逻辑不会出现“本地能发CI 挂了”的割裂情况。2.3 工具链选型ohpm、hvigor、DevEco Studio 的角色分配鸿蒙生态的工具链跟 Flutter 侧差别很大这里简单划线ohpm是鸿蒙生态的包管理器对标 pub.dev 的发布通道负责包的下载和发布命令格式类似ohpm publish。hvigor是鸿蒙侧的构建任务框架对标 Gradle负责处理 OpenHarmony 工程里的编译任务Flutter 插件的鸿蒙原生部分最终会通过它构建成 HAR 包或 HAP。DevEco Studio 是集成开发环境它内置了 SDK 管理、签名配置和调试工具。CI 环境里一般不需要它但本地联调排查签名问题时绕不开。我实际跑下来的经验是CI 环境最好预装并使用与本地一致的 ohpm SDK 和 hvigor 版本否则非常容易出现本地编译通过、CI 构建失败的情况。鸿蒙工具链的版本演进很快API 版本和构建工具版本一旦错位报错信息还很隐蔽后面我会专门列几个典型问题。3. 核心实操把发布流水线真正跑起来3.1 第一步建立可控的目录与版本基线动手之前先把工程的目录结构整理干净。因为pub_release发布时会自动收集目录下的文件如果一个工程里既有 Flutter 标准结构又有鸿蒙的ohos目录文件过滤规则一定要提前设计好否则发布出去的包里会出现大量无效文件。我建议的目录基线大致如下my_flutter_package/ ├── lib/ # Dart 实现 ├── ohos/ # OpenHarmony 平台实现 │ ├── entry/ │ └── build-profile.json5 ├── test/ # 测试用例 ├── tool/ # 发布脚本与工具类 │ ├── sync_version.sh │ └── publish_harmony.sh ├── pubspec.yaml ├── oh-package.json5 └── CHANGELOG.md版本基线方面我习惯把pubspec.yaml里的version作为唯一真源oh-package.json5和 CHANGELOG 都从这个源头派生。这样做的好处是减少人工操作点因为每一次人工介入都是一次出错的机会。你只需要在发布时告诉pub_release要大版本还是小版本剩下的全是机器在做。3.2 第二步写好自动化脚本核心脚本是整个鸿蒙化适配的心脏。我会把过程拆成两个脚本sync_version.sh负责元数据同步publish_harmony.sh负责鸿蒙侧的发布。前者逻辑刚才已经讲过后者要处理的事情更复杂一些。publish_harmony.sh的大体逻辑如下检查 ohpm 是否登录没有 token 就提前报错。校验oh-package.json5的版本号跟pubspec.yaml一致。执行ohpm build或者通过 hvigor 构建 HAR确保鸿蒙侧产物没问题。最后执行ohpm publish。# publish_harmony.sh 关键片段 set -e # 1. 登录态校验 ohpm whoami /dev/null 21 || { echo ohpm 未登录请先执行 ohpm login; exit 1; } # 2. 版本一致性校验 PUBSPEC_VERSION$(grep ^version: pubspec.yaml | awk {print $2}) OHPM_VERSION$(grep version oh-package.json5 | sed s/.*: \(.*\),*/\1/) if [ $PUBSPEC_VERSION ! $OHPM_VERSION ]; then echo 版本不一致: pubspec$PUBSPEC_VERSION ohpm$OHPM_VERSION exit 1 fi # 3. 鸿蒙侧构建 hvigorw --mode ohos -p productdefault assembleHar # 4. 发布 ohpm publish注意set -e一定要加上任何一个环节失败都要中断绝不能带着失败状态继续往下走。我见过不少 CI 配置忽略了这个细节表面看流水线是绿的实际上发布动作根本没执行成功。3.3 第三步接 CI 并加上发布验证本地脚本跑通之后就要把它接到 CI 上了。我的建议是发布动作不要由开发者本地触发而是通过 Git tag 触发 CI 任务。开发者推送一个v1.2.0的 tag 到远端CI 检测到之后自动执行全流程。这样发布记录和代码记录是对齐的审计的时候非常方便。CI 任务的阶段划分可以参考阶段一安装 Flutter SDK 和 OpenHarmony SDK 工具链。阶段二跑dart pub_release publish --dry-run注意这个 dry-run 不真正发布只做校验。阶段三执行版本同步脚本确认oh-package.json5被正确更新。阶段四运行 Flutter 单测和鸿蒙侧的编译验证。阶段五真正执行发布发布成功后自动打上发布完成标记。这里特别提一个细节CI 里的 OpenHarmony 环境变量要显式设置。尤其是DEVECO_SDK_HOME和OHPM_REGISTRY不同机器上 SDK 路径不一样如果在脚本里写死绝对路径换一台机器就废了。最好在 CI 配置里统一注入脚本只读取环境变量。# CI 环境变量示例 export DEVECO_SDK_HOME/opt/ohos-sdk export OHPM_REGISTRYhttps://ohpm.openharmony.cn/ohpm/3.4 第四步验证环节不能省的东西回到开头那个痛点自动化最怕的就是把错误也自动化了。因此验证环节是这条流水线的生命线必须包含以下几类校验Dart 侧静态分析flutter analyze必须零 errorwarning 视团队规范决定是否拦截。测试套件核心逻辑的单元测试必须通过没有测试的模块不允许发布。dry-run 发布校验dart pub publish --dry-run会列出即将打包的所有文件人工或脚本检查有没有多余文件混入。鸿蒙侧构建产物校验确认 HAR 包能正常产出且oh-package.json5里声明的依赖都能被解析。我团队里的规矩是以上四项任何一项失败流水线直接红发布者需要在 PR 描述里解释原因。这套机制跑起来之后发布出问题的概率明显下降。4. 实跑中的坑与排查实录4.1 鸿蒙化适配常见问题速查表这里把我实际跑溪中遇到的典型问题整理成了一张速查表按症状、原因、解法三列来写省得大家再踩一遍。症状根本原因解决办法ohpm 发布时提示版本已存在oh-package.json5版本号未递增重复发布同版本执行同步脚本后检查版本号确认pub_release已完成版本递增CI 里 hvigor 构建失败本地却能过本机与 CI 的 OpenHarmony SDK 版本不一致锁定 SDK 版本CI 与本地统一安装指定版本ohpm publish报 401 错误token 失效或未登录重新执行ohpm login获取 token并在 CI 密钥管理里更新发布后的 Flutter 包在鸿蒙侧 import 失败ohos目录下的原生实现未被正确打包检查插件工程结构确认oh-package.json5中的 main 入口有值CHANGELOG 里版本号和实际发布版本不一致手动改过 CHANGELOG绕过工具禁止手动维护 CHANGELOG统一交给脚本追加pub.dev 发布成功ohpm 发布失败双通道发布其中一个通道执行异常确保流水线里两步发布相互独立失败一方可单独重试4.2 我反复踩的三个典型坑第一个坑是oh-package.json5的注释兼容问题。这玩意儿虽然是 JSON5但有些工具链在解析时对注释的容忍度不一样。有一回我为了在配置文件里写一行说明文字加了一个//注释结果ohpm publish直接解析失败。后来我查了一下才知道版本较旧的 ohpm 对 JSON5 的注释支持不完整。解决方案很简单要么不用注释要么升级 ohpm 到新版本。第二个坑是版本号前缀不一致。Flutter 侧习惯用1.2.0这种三段式版本号但部分鸿蒙生态的包会在版本号前加或者带 build 号比如1.2.0-rc.1。如果你的oh-package.json5里版本号被手动加上了奇怪的后缀而pubspec.yaml里没有同步脚本就给出来的version:判断失败。踩过一次之后我在脚本里加了严格的版本号正则校验不合法直接拒绝发布。第三个坑是CI 里的 JAVA_HOME 影响 hvigor 构建。hvigor 构建底层依赖 Gradle而 Gradle 是需要 JDK 的。CI 机器上如果同时存在多个 JDK 版本而JAVA_HOME没有明确指向 JDK 17构建过程就会报一些莫名其妙的错误比如Unsupported class file major version。排查了半天才发现是基础镜像里默认 JDK 版本太老。这个问题后来通过在 CI 脚本里显式导出JAVA_HOME解决。5. 这套流水线还能怎么扩展5.1 从“发布工具”到“研发流程基础设施”适配完pub_release之后我最大的感受是这已经不是一个简单的发布工具适配了它实际上在帮你搭建研发生命线的“最后一段”。你可以继续往上扩展比如在版本同步阶段自动生成“发布说明卡片”把 CHANGELOG 里的重要变更转成团队群里的公告或者把每次发布的产物 metadata版本号、发布时间、提交哈希写进一个自动化报表页面再进一步还可以把发布流水线与 issue 自动关联当某个 PR 合入并触发发布时自动关闭对应的 issue。这些扩展都是在同一套版本决策机制之上做文章并不会增加太多额外成本。5.2 我在实际维护中形成的一个习惯最后分享一个我自己坚持了很久的习惯每次发布之后我会手动去看一眼两个仓库上拉取到的包内容确认无误之后才在群里发版本公告。自动化能保证流程稳定但不能百分之百保证结果符合预期保持一点人工复核的仪式感反而能让发布这件事在团队里传递出一种“可靠”的信号。尤其是鸿蒙侧的三方库生态还处在快速演进期多加一道检查省下来的可能是后面一连串的线上问题。这个适配方案的完整链路跑通之后我已经把 Flutter 三方库发布到鸿蒙生态的流程固化成了团队标准动作整个过程的耗时从过去的一小时压缩到五分钟以内而且出错率大幅下降。如果你也在维护跨端 Flutter 库并且打算支持鸿蒙希望这套从工具理解、流程设计到脚本落地的思路能对你有些启发。
返回列表