HarmonyOS 7.0 / API 26 DevEco SDK 基线检查:团队协作为什么要先锁版本再写代码

团队里做 HarmonyOS 7.0 / API 26 适配时,最容易被忽略的不是某一个 API 写错,而是每个人本地 DevEco Studio、SDK、Hvigor、ArkTS 编译链版本不一致。一个人能编译,另一个人打开就报错;本地能跑,CI 上又失败。这个问题如果不提前拦住,后面排查会非常耗时间,因为错误表面看起来像代码问题,实际根因是环境基线飘了。

DevEco SDK 基线检查示意

先看问题怎么发生

我把这个问题拆成三个层次:IDE 版本、HarmonyOS SDK/API 版本、工程构建插件版本。只锁其中一个不够。比如工程声明 API 26,但有人本地只装了旧 SDK;或者 SDK 对了,但 Hvigor 插件版本和仓库不一致;再或者本地缓存里残留了旧编译产物,导致同一份代码在不同机器上表现不一样。

这种问题的麻烦点在于,它不会总是在第一行报“版本不一致”。有时会表现成 ArkTS 类型推断失败,有时是资源编译失败,有时是预览器能打开但真机构建失败。所以我的做法不是等报错以后再猜,而是在项目启动阶段就把基线写成可执行检查。

场景一:API 版本不一致导致构建结果不同

假设项目准备按 HarmonyOS 7.0 / API 26 做适配,团队里有人还停留在旧 SDK。代码里使用了新版本组件或配置项,本地 A 能通过,B 那边却构建失败。这个时候不要直接让 B 改代码,先确认 SDK 基线是否一致。

export interface SdkBaseline {
  harmonyApi: number
  minApi: number
  targetApi: number
  hvigor: string
  nodeMajor: number
}

export const requiredBaseline: SdkBaseline = {
  harmonyApi: 26,
  minApi: 18,
  targetApi: 26,
  hvigor: '7.x',
  nodeMajor: 18
}

export function checkSdkBaseline(current: SdkBaseline): string[] {
  const errors: string[] = []
  if (current.harmonyApi < requiredBaseline.harmonyApi) {
    errors.push('HarmonyOS SDK 版本过低,需要 API 26 或以上')
  }
  if (current.targetApi !== requiredBaseline.targetApi) {
    errors.push('targetApi 不一致,团队构建结果可能不同')
  }
  if (current.nodeMajor !== requiredBaseline.nodeMajor) {
    errors.push('Node 大版本不一致,Hvigor 依赖解析可能漂移')
  }
  if (!current.hvigor.startsWith('7.')) {
    errors.push('Hvigor 插件版本不在约定范围内')
  }
  return errors
}

这段代码不替代 DevEco Studio 的完整检查,它只做一件事:把最容易造成分歧的版本项提前暴露出来。团队成员拉代码以后先跑检查,错误信息指向环境,而不是让大家在业务代码里来回试。

场景二:CI 和本地版本不一致,导致线上构建失败

第二类问题更隐蔽:开发机可以跑,CI 不行。原因通常是 CI 镜像、Node、Hvigor、SDK 包没有跟着项目一起升级。解决方式是把基线结果写进构建前置步骤,不满足就直接失败,不要等编译跑到一半。

import { checkSdkBaseline, SdkBaseline } from './build-profile-check'

function readCiBaseline(): SdkBaseline {
  return {
    harmonyApi: Number(process.env.HARMONY_API || 0),
    minApi: Number(process.env.HARMONY_MIN_API || 0),
    targetApi: Number(process.env.HARMONY_TARGET_API || 0),
    hvigor: process.env.HVIGOR_VERSION || '',
    nodeMajor: Number((process.version.match(/^v(\d+)/) || [])[1] || 0)
  }
}

const errors = checkSdkBaseline(readCiBaseline())
if (errors.length > 0) {
  console.error('[baseline failed]')
  for (const error of errors) console.error("- " + error)
  process.exit(1)
}
console.log('[baseline ok] HarmonyOS 7.0 / API 26 build environment is ready')

这一步放在真正构建之前,价值很直接:CI 失败时第一眼就知道是不是环境问题。如果这里通过了,后面的编译错误才更有资格怀疑代码本身。

为什么不只写在 README 里

README 当然要写,但只写文档不够。因为文档不会阻止旧环境继续构建,也不会在 CI 上自动失败。版本基线最好同时落在三个地方:文档给人看,脚本给机器跑,CI 给结果兜底。

做法 优点 风险 适合场景
只写 README 成本最低 容易没人看,环境继续漂移 小实验、个人项目
DevEco 手动检查 能看到完整工具链信息 依赖人工记忆,难沉淀 临时排查
构建前脚本检查 可复用、可进入 CI 需要维护基线字段 团队协作、长期项目
CI 强制失败 最可靠 首次接入要整理环境变量 发布前质量门禁

我的选择是 README + 脚本 + CI 三层都保留。README 说明为什么这么定,脚本负责本地快速失败,CI 负责防止漏网。

还要检查哪些项

  • DevEco Studio 大版本是否一致;
  • HarmonyOS SDK 是否包含目标 API,例如 API 26;
  • module 的 targetApi、compatibleSdkVersion 是否符合约定;
  • Hvigor 插件和 hvigor-wrapper 是否跟仓库一致;
  • Node 大版本是否统一;
  • 本地缓存是否需要清理;
  • CI 镜像是否已经更新到同一套工具链。

如果项目里有 ArkWeb、3D 图形、跨设备、多窗口、穿戴端这些能力,还要把对应能力依赖的 SDK 包单独列出来。因为这类能力经常不是一个普通 ArkTS 页面就能完全覆盖的,环境差一点,构建和运行结果都会变。

一套更稳的落地方式

我会在仓库里放一个 baseline.json,再让脚本读取它。这样后续升级 HarmonyOS 7.0 / API 26 小版本时,不用到处改代码,只改一份配置。

{
  "harmonyApi": 26,
  "targetApi": 26,
  "minApi": 18,
  "nodeMajor": 18,
  "hvigorPrefix": "7.",
  "reason": "HarmonyOS 7.0/API 26 capability adaptation"
}
export interface BaselineResult {
  ok: boolean
  errors: string[]
  warnings: string[]
}

export function buildResult(errors: string[], warnings: string[]): BaselineResult {
  return { ok: errors.length === 0, errors, warnings }
}

这样封装以后,IDE 前置检查、CI 检查、发布前自检都能复用同一套结果对象。后面如果要做图形能力、ArkWeb 内核、跨设备能力的分项检查,也可以往 baseline.json 里加字段,不用把逻辑散落在每个脚本里。

验证方式

我一般会做两组验证:正常环境下 API 26、targetApi 26、Node 18、Hvigor 7.x,脚本返回 baseline ok;异常环境下把 targetApi 改成旧值,或者把 HARMONY_API 模拟成 25,脚本必须直接失败,并给出明确原因。

[baseline failed]
- HarmonyOS SDK 版本过低,需要 API 26 或以上
- targetApi 不一致,团队构建结果可能不同

如果错误信息能让新人直接知道该升级 SDK 还是改配置,这个检查就有价值。反过来,如果只打印一个 build failed,那还是会把人带回猜错方向的老路。

本文验证环境

下面的示例不是泛泛地说“升级 SDK”。我按一个可复现的团队基线来写,读者可以直接把字段换成自己项目里的值。

项目 本文示例值 为什么要锁
DevEco Studio 6.0.0 Release 或同一主版本维护版 IDE 和预览器行为要一致
HarmonyOS SDK HarmonyOS 7.0.0 / API 26 新能力和类型声明依赖 SDK
ArkTS 编译链 随 DevEco 6.0.0 配套安装 避免类型检查结果漂移
Hvigor 7.x 同一小版本段 构建插件不同会影响任务解析
Node.js 18.20.x 避免依赖安装和脚本执行结果不同
CI 镜像 与本地同一套 SDK 和 Node 防止本地通过、流水线失败

我在项目里会把这几项写成 baseline.json,并把检查脚本放到真正构建之前。这样做的目标很简单:如果环境不对,直接在第一分钟失败,不要等页面、资源、签名、预览全跑一遍以后才发现方向错了。

{
  "devecoStudio": "6.0.0",
  "harmonyOs": "7.0.0",
  "api": 26,
  "arktsCompiler": "with-deveco-6.0.0",
  "hvigor": "7.x",
  "node": "18.20.x",
  "ciImage": "harmonyos-api26-node18"
}

验证日志怎么写才有排查价值

基线检查不要只返回 true 或 false。真正排查时,我希望日志里能看到当前值、期望值和修复建议。比如下面这段输出,看到第一行就知道不是页面代码错了,而是本地 SDK 还没升到 API 26。

[baseline failed]
current DevEco Studio: 5.1.x, expected: 6.0.0
current HarmonyOS SDK API: 25, expected: 26
current Hvigor: 6.x, expected: 7.x
action: update DevEco Studio and install HarmonyOS 7.0/API 26 SDK before build

正常环境下输出也要保留,因为它能作为 CI 记录,后面谁问“这个包到底用什么环境构建的”,可以直接回到日志里查。

[baseline ok]
DevEco Studio: 6.0.0
HarmonyOS SDK: 7.0.0 / API 26
Hvigor: 7.x
Node.js: 18.20.x
CI image: harmonyos-api26-node18

失败后怎么处理

如果检查失败,我不会让脚本继续跑构建。继续跑只会制造更多无关错误。更稳的处理是:本地直接提示升级项,CI 直接失败,PR 评论里贴出当前环境和期望环境。团队里多人协作时,这比口头提醒可靠得多。

结论

HarmonyOS 7.0 / API 26 适配不要等到页面写完才发现环境不一致。先锁 DevEco、SDK、Hvigor、Node 和 CI 基线,再写业务代码,排查成本会低很多。这个检查不复杂,但能把“我这里可以,你那里不行”的问题提前拦住。后续项目里只要涉及多设备、ArkWeb、新能力或上架前构建,都建议把基线检查放到真正构建之前。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐