ARTICLE DETAIL

资讯详情

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

Flutter 三方库鸿蒙适配:pub_release 自动发布实践

Flutter 三方库鸿蒙适配:pub_release 自动发布实践 做 Flutter 三方库维护这几年发布这件事一直是我最不愿意手工碰的一环。版本号漏改、CHANGELOG 忘写、tag 打偏随便一个失误都能让下游团队排查半天。而在 Flutter 包要支持鸿蒙之后这个问题被放得更大了——因为你不再只需要校验安卓和 iOS还要多一个鸿蒙平台的构建与依赖声明。这篇文章我就拿 pub_release 这套发布流程来说说如何把 Flutter 三方库的包发布在鸿蒙生态下做成自动化、标准化并把我在实际适配中踩过的坑一并梳理出来。1. 先搞清楚 pub_release 解决了什么问题1.1 包发布这件事为什么值得做标准化如果你维护一个 Flutter 三方库最原始的发布流程大概是这样的手动改pubspec.yaml里的版本号手写一段 CHANGELOG本地跑一遍flutter analyze和flutter test然后执行dart pub publish。听起来步骤不多但人一旦开始做重复的事情就会开始犯错。我见过最经典的事故是版本号从2.5.1升到2.6.0CHANGELOG 却还停在2.5.1或者代码已经合并到主干tag 却停留在两周前的提交上。下游用户升级后发现变更内容和实际代码对不上这种不信任感对开源库是致命的。所以包发布的核心痛点不是“发布命令怎么敲”而是“整个流程如何让机器去执行、让每次发布都具有一致性和可追溯性”。这也是我后来围绕 pub_release 搭建发布流程的原因。它的本质是把版本决策、变更记录、构建校验、发布动作、标签管理串成一条流水线每个人执行的都是同一个标准流程而不是靠记忆力。尤其当你在团队里协作今天你发、明天他发如果没有统一规范版本秩序很快就会失控。1.2 pub_release 的功能拆分与配置形态按照我的使用体会pub_release 要干的事情可以拆成这几个环节版本决策基于语义化版本自动计算下一个版本号patch、minor、major可以通过参数或 commit 类型来触发。变更记录更新读取最近的 commit 信息辅助生成或校验CHANGELOG.md。质量门禁自动执行flutter analyze和flutter test确保代码通过基础检查才放行。发布预检执行dart pub publish --dry-run检查包内容、许可证、平台声明。正式发布调用dart pub publish把包推到仓库。版本标记发布成功后自动打 git tag 并推送。这六个环节看起来各自独立串联起来价值就出来了。你可以把这种思路理解成 Node 社区的semantic-release或者 Rust 社区的cargo releasepub_release 在 Dart/Flutter 生态里承担的也是类似职责。发布不再是一个“记得就做”的操作而是仓库里一套可以被重复执行的配置。我使用的 pub_release 版本把配置放在.pub_release.yaml里方便在不同仓库间统一行为。一份基础配置长这样release: branch: main versioning: conventional plugins: - name: analyze command: flutter analyze - name: test command: flutter test - name: dry_run command: dart pub publish --dry-run publish: registry: https://pub.dev args: [-f] git: tagPrefix: v pushTags: true这套配置的核心思路是“把要执行的命令变成数据”。以后无论谁发版只需要运行一个发布命令剩下的事情交给 pub_release 按配置逐项完成。这种数据驱动的方式也为后面的鸿蒙适配打下了很好的基础——因为鸿蒙的构建校验本质上也不过是往这个流程里再插入一个插件步骤而已。2. 鸿蒙化适配的核心思路2.1 鸿蒙化让三方库发布流程多了什么现在不少 Flutter 三方库要支持鸿蒙。所谓适配不只是把 Dart 代码静态检查过一遍还需要处理鸿蒙平台的原生工程配置。落到包发布环节主要有三处变化。第一包内平台目录要包含ohos/。Flutter 插件识别平台依赖的方式是看包根目录下有没有对应的平台目录以及pubspec.yaml里有没有显式声明ohos平台。如果你只改了代码、忘了声明平台那么鸿蒙项目通过 pub 依赖你的包时Flutter 工具链会认为这个包不支持鸿蒙根本不会把源码拉下去。第二发布前的构建校验必须覆盖鸿蒙。以前发布一个插件本地验证只需要跑 Android 构建和 iOS 构建。现在支持鸿蒙之后至少要跑一遍鸿蒙目标的 release 构建确认原生部分的 ArkTS/C 代码能通过 hvigor 编译。这一步如果漏掉很容易出现“包发布成功、鸿蒙工程一接入就编译失败”的局面这种事故比发版失败更尴尬。第三CI 环境里要准备鸿蒙 SDK。GitHub Actions 或内部 CI 上不能只装 Flutter 和 Java还要把 OpenHarmony 的 SDK、命令行工具装好并配置OHOS_SDK_HOME环境变量让 Flutter 工具链能定位到鸿蒙构建产物。很多适配项目恰恰是写代码很快最后卡在 CI 环境搭建上。2.2 适配方案选型硬编码与 hook 的取舍在考虑 pub_release 鸿蒙化适配时通常会面临两条路直接改 pub_release 的源码把 ohos 平台硬编码进去或者保留工具核心能力通过外层脚本和配置来注入鸿蒙相关动作。我更推荐后者。原因很简单。pub_release 的本质是流程编排器它不关心你最终构建出什么产物只关心“发布之前这些步骤是否全部成功执行”。所以鸿蒙适配的正确姿势应该是把鸿蒙构建作为一个 preflight 插件注入比如配置成flutter build ohos --release而不是把平台细节写死在工具内部。另一个原因是鸿蒙的构建工具链更新很频繁。今天用 hvigor 2.x明年可能升到 3.x。如果工具把平台逻辑写死每次 SDK 变化都要跟着升级 puh_release而外层脚本可以根据 CI 环境灵活调整维护成本低得多。换句话说我们要把“适配”当成仓库配置层面的事情而不是动工具的源码。我最终采用的方案是pub_release 继续负责版本、changelog、发布和 tag 主流程在 CI 工作流里增加独立的鸿蒙构建步骤同时在 pub_release 的 preflight 阶段把鸿蒙构建作为门禁之一。这样既保留了工具的通用性又把鸿蒙的差异化逻辑收敛在一个地方。3. 从零落地pub_release 鸿蒙化适配实操3.1 环境准备让 Flutter 工具链认识鸿蒙鸿蒙化适配的第一步是搭建正确的开发环境。目前要在 OpenHarmony 工程里跑 Flutter最常用的是社区维护的 flutter_flutter fork 版本对应 OpenHarmony 分支。除了 Flutter SDK 本身你还需要完整安装 OpenHarmony SDK 和 DevEco Studio 的命令行工具。这里我强烈建议先在本机 IDE 里手动跑通一个 HarmonyOS demo 工程确认能构建、能安装、能启动再进入包发布流程。不要在没有验证环境的情况下直接上 CI那样问题会变成一团浆糊分不清是代码问题还是环境问题。环境配置的几个关键点设置OHOS_SDK_HOME指向 OpenHarmony SDK 目录。不同版本对应目录名不同务必让 Flutter fork 工具链能找到。配置 DevEco Studio 的 command-line-tools 路径hvigor 构建依赖它。注意 JDK 版本。DevEco 和 hvigor 对 JDK 版本有要求一般用 JDK 11 或 17具体以 SDK 文档为准。环境变量建议固化到 shell profile 或 CI secrets 里不要每次手工 export。发布流程一旦自动化环境配置就必须可重复。我自己的经验是把所有版本号和路径都写进 README防止换电脑或者换 CI 环境时抓瞎。3.2 三方库的 ohos 平台声明与目录结构让 Flutter 工具链识别鸿蒙支持第一步就是改pubspec.yaml。典型写法是这样name: my_flutter_package version: 1.2.0 description: A sample Flutter package with ohos support. flutter: plugin: platforms: android: package: com.example.my_package pluginClass: MyPackagePlugin ios: pluginClass: MyPackagePlugin ohos: package: com.example.my_package pluginClass: MyPackagePlugin注意ohos平台标识和目录名必须保持一致。插件源码放在ohos/目录下里面是标准 OpenHarmony 工程结构包括oh-package.json5、entry/src/main/ets/等。Dart 侧的平台判断逻辑也需要更新。Flutter 鸿蒙适配分支里鸿蒙通常被映射为TargetPlatform.android处理你需要结合自己的插件场景去判断。如果插件内部依赖了安卓的系统接口那么在鸿蒙上执行时需要走ohos/目录下的原生实现Dart 侧尽量只做通用逻辑。我之前写过一段代码就是因为没有区分安卓与鸿蒙直接调用了安卓原生路径导致鸿蒙设备上静默失败。3.3 自动化发布脚本核心实现接下来是重头戏。我把当前使用的 pub_release 执行脚本简化后贴出来。支持鸿蒙之后的核心调整就是 preflight 阶段多了 ohos 构建步骤。#!/bin/bash set -euo pipefail # 手动指定版本类型 patch / minor / major RELEASE_TYPE${1:-patch} CURRENT_VERSION$(grep -E ^version: pubspec.yaml | awk {print $2}) NEW_VERSION case $RELEASE_TYPE in patch) NEW_VERSION$(echo $CURRENT_VERSION | awk -F. {print $1.$2.($31)}) ;; minor) NEW_VERSION$(echo $CURRENT_VERSION | awk -F. {print $1.($21).0}) ;; major) NEW_VERSION$(echo $CURRENT_VERSION | awk -F. {print ($11).0.0}) ;; esac echo Current version: $CURRENT_VERSION echo New version: $NEW_VERSION版本号自动计算这里我吃过亏后面踩坑部分会细说。这里先给个结论如果版本号格式不规整比如存在2.10.0和2.9.5这种多位数字一定要保证 awk 处理的是十进制数值而不是字符串拼接否则很容易出现版本倒退。继续看构建和发布部分# 1. 更新 pubspec.yaml 版本号 sed -i s/^version:.*/version: $NEW_VERSION/ pubspec.yaml # 2. 质量门禁 flutter analyze flutter test # 3. 鸿蒙构建验证 preflight flutter build ohos --release # 4. 发布预检 dart pub publish --dry-run # 5. 正式发布 dart pub publish -f # 6. 打版本标签 git add pubspec.yaml CHANGELOG.md git commit -m chore(release): v${NEW_VERSION} git tag v${NEW_VERSION} git push --tags注意flutter build ohos --release这个命令只在鸿蒙分支的 Flutter 工具链里存在。官方 upstream Flutter SDK 不认识 ohos target所以 CI 里必须使用 OpenHarmony 对应的 Flutter SDK。如果你在本地用的是社区 fork 版在 CI 里却用了官方版那么这一行会直接报错。对应的 GitHub Actions 工作流大致是这样name: publish on: workflow_dispatch: inputs: release_type: description: patch / minor / major required: true default: patch jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-javav4 with: distribution: temurin java-version: 17 - uses: subosito/flutter-actionv2 with: flutter-version: 3.24.5-ohos - name: Setup OHOS SDK run: | curl -L -o ohos_sdk.zip ${{ secrets.OHOS_SDK_URL }} unzip ohos_sdk.zip -d $HOME/ohos-sdk echo OHOS_SDK_HOME$HOME/ohos-sdk $GITHUB_ENV - run: ./scripts/pub_release.sh ${{ github.event.inputs.release_type }}这里最关键的是把OHOS_SDK_URL放到 secrets 里维护。不同鸿蒙 SDK 的下载地址和时间都会有差异建议在 CI 环境搭建初期先用固定版本稳定后再考虑动态拉取。不要照抄任何人的下载链接版本变了链接大概率失效。3.4 适配后的发布验证与 dry-run 检查脚本和 CI 都跑起来之后不要急着发正式包。我的习惯是先在 CI 里执行一遍 dry-run 模式重点检查三样东西包内容列表里是否包含ohos/目录以及oh-package.json5是否完整。flutter build ohos --release是否真实执行而不是被跳过。pubspec.yaml里的平台声明和实际目录结构是否一致。如果dart pub publish --dry-run输出的文件列表里ohos/目录没有出现基本可以判定平台声明写错了回去检查pubspec.yaml的flutter.plugin.platforms段落。还有一个容易踩的细节ohos/目录如果被.gitignore忽略了也会导致发布时文件缺失。我在一个仓库里遇到过原因就是.gitignore里写了ohos/结果包始终没有鸿蒙支持排查了很久才发现问题不在平台声明。提示dart pub publish会把除了.gitignore忽略之外的几乎所有文件都打包。所以在ohos/目录下如果有本地调试用的临时文件一定要在.gitignore里加上否则发布出去的包里会带着垃圾文件。4. 踩坑实录与排查技巧4.1 我在鸿蒙化适配中的真实踩坑经历先说版本号自动升级的坑。之前我用 sed 做字符串替换直接把2.5.10处理成了2.5.1发布出去是错误版本整条流水线白跑。后来我统一把版本计算改成 awk 的数值运算并且补了单元测试。自动化工具犯的错最容易迷惑人因为你会盲目相信它。所以凡是涉及版本数字计算强烈建议用脚本测试覆盖。第二个坑是 CI 里flutter命令能找到但执行flutter build ohos时报Unable to locate ohos sdk。原因很直接OHOS_SDK_HOME环境变量没传递到构建子进程。我把变量写在了 setup 步骤里但后续步骤用的是另一个 shell环境变量没有 export。排查方法也简单在构建前加一行echo $OHOS_SDK_HOME打印出来一看就知道问题在哪。第三个坑是版本号发布到 pub.dev 后新建项目里dart pub get永远拉不到最新版本。这个其实和发布工具无关是 pub 仓库的缓存机制。不同镜像源滞后情况不一样做发布流程设计时最好在文档里明确告诉用户“如果发布后暂时拉不到新版本先等缓存刷新”。不然用户很容易误以为你的包有问题对你的开源信誉产生怀疑。4.2 常见问题速查表问题现象可能原因解决办法flutter build ohos报未知 target使用的不是鸿蒙分支 Flutter SDK切换 flutter_flutter OpenHarmony 分支发布的包在鸿蒙工程拉不到缺少 ohos 平台声明或 ohos 目录检查pubspec.yaml的 platforms补上 ohosCI 和本地版本号不一致CI 里 pubspec.yaml 被改动或缓存工作流开始强制 checkout不缓存 pubspec发布成功但 tag 丢失脚本中git push --tags被跳过检查 CI 权限改用git push --follow-tagsdry-run 里看不到 ohos 目录目录被 .gitignore 忽略确认 ohos 目录没有被忽略鸿蒙构建成功但运行崩溃原生权限或 ability 未配置检查module.json5权限声明4.3 容易被忽略的三个细节再说三个细节这三个问题不会直接让发布失败但一定会影响下游使用体验。第一ohos/目录下的原生代码要统一版本号。很多 Flutter 插件会在oh-package.json5里写自己模块的版本这个版本和pubspec.yaml的版本号经常是分开维护的。如果只改了 pubspec鸿蒙模块内部还是旧版本号用户做鸿蒙应用依赖解析时会出现奇怪的冲突。第二CHANGELOG 不要只写“适配鸿蒙”四个字要把具体改了什么原生行为、Dart 侧 API 有没有破坏性变更写清楚。鸿蒙用户和安卓/iOS 用户看的是同一份 CHANGELOG不写清楚很容易让移动端用户误升级。我习惯在一条变更里同时标注影响平台比如“修复初始化时序问题ohos/android”这样下游维护者扫一眼就明白。第三如果插件在鸿蒙上需要申请权限或注册 ability一定要在ohos/entry/src/main/module.json5里配置好。我见过不止一个包Dart 代码看起来支持鸿蒙但原生权限没配用户接入后一调用就闪退。这种问题在发布者的自测场景里很难覆盖因为大家手头不一定有鸿蒙真机。没有真机的话至少要在文档里明确列出所需权限让用户在接入前有预期。5. 几点个人经验写给同样在做鸿蒙适配的人流程和工具的部分讲完最后分享几点我个人体会比较深的东西。pub_release 这类自动化工具体现的价值不是某个脚本写法多巧妙而是它强制养成了一个习惯每次发布都走同样的路径。你在哪个平台、用什么 SDK、怎么验证、怎么打 tag都会有迹可循。鸿蒙生态目前还在快速变化SDK 更新频率很高如果发布流程靠“这次记得手动做一下”很快就会被拖垮。把鸿蒙构建作为发布门禁之一不是给自己添麻烦而是给后续版本迭代兜底。如果你手头的三方库还不支持鸿蒙建议先不要急着上全套自动化。先把ohos/目录和平台声明搞定本地能跑通一次手动发布再考虑接入 CI。自动化是“对成熟流程的固化”不是“对混乱流程的补救”。流程还没稳定就上自动化只会放大错误。最后分享一个小技巧在pubspec.yaml里给ohos平台声明加上注释标注适配的鸿蒙工具链版本和支持的最低 API 级别。这些信息现在看起来多余但半年后鸿蒙 SDK 大版本一更新你翻回来看会很感激当时记录下来的上下文。这个方法也顺手写进 CHANGELOGRelease notes 对下游开发者的实际帮助会大得多。鸿蒙适配这条路代码量往往不大真正考验人的是流程收敛和环境一致性把这些基础工作做扎实后续的迭代才会越走越顺。
返回列表