HarmonyOS开发:持续集成CI流水线搭建
HarmonyOS开发:持续集成CI流水线搭建
📌 核心要点:CI流水线是鸿蒙项目工程化的第一道关——代码提交即触发自动构建和测试,把集成问题消灭在萌芽阶段,而不是等到发布前才发现一堆冲突。
背景与动机
你有没有经历过这种场景?
周五下午5点,大家兴冲冲准备下班,突然测试同学跑过来说"打包失败了"。你一看日志,A同学改了公共模块的接口,B同学还在用老接口,编译直接炸了。然后就是一通互相确认、改代码、重新打包,搞到晚上9点才回家。
这种事在小项目里可能一周碰一次,在多人协作的大项目里?一天能碰好几次。
问题的根源在哪?集成太晚了。大家都各自开发,攒了一周才合并一次代码,能不出问题吗?
持续集成(Continuous Integration,CI)就是来解决这个问题的。核心思路很简单:频繁集成,尽早发现问题。每提交一次代码,自动触发构建和测试,有问题立刻暴露,绝不攒着。
对鸿蒙项目来说,CI还有一层特殊意义——ArkTS编译链和传统前端完全不同,DevEco Studio的构建系统是定制的hvigorw,签名流程也和Android不一样。如果这些都靠手动操作,出错概率极高,CI自动化就是刚需。
核心原理
CI流水线的本质是什么?一句话:把"代码变成可验证产物"这个过程自动化。
flowchart LR
A[代码提交] --> B[触发CI]
B --> C[拉取代码]
C --> D[依赖安装]
D --> E[编译构建]
E --> F[单元测试]
F --> G{测试通过?}
G -->|是| H[产物归档]
G -->|否| I[通知开发者]
classDef trigger fill:#FF6B6B,stroke:#C0392B,color:#fff
classDef process fill:#4ECDC4,stroke:#16A085,color:#fff
classDef decision fill:#FFE66D,stroke:#F39C12,color:#333
classDef success fill:#95E1D3,stroke:#27AE60,color:#333
classDef fail fill:#F38181,stroke:#E74C3C,color:#fff
class A,B trigger
class C,D,E,F process
class G decision
class H success
class I fail
鸿蒙项目CI流水线的几个关键阶段:
| 阶段 | 做什么 | 鸿蒙特有挑战 |
|---|---|---|
| 代码拉取 | 从Git仓库拉取最新代码 | 多仓库依赖管理 |
| 依赖安装 | ohpm install安装三方库 | ohpm registry配置 |
| 编译构建 | hvigorw assembleHap | SDK版本、签名配置 |
| 单元测试 | 执行ArkTS单元测试 | Hypium测试框架 |
| 产物归档 | 保存HAP/APP产物 | 签名文件管理 |
一条完整的鸿蒙CI流水线,和普通前端项目最大的区别在构建和签名环节。DevEco Studio底层用的是hvigorw构建工具(基于Node.js的构建框架),不是webpack也不是gradle。这意味着你没法直接套用前端的CI配置,得专门适配。
代码实战
基础用法:DevEco Studio命令行构建
CI的第一步,是让构建能在命令行跑起来。DevEco Studio提供了命令行构建工具,脱离IDE也能完成编译。
# 进入项目根目录
cd /path/to/your/project
# 安装依赖(鸿蒙的包管理器是ohpm)
ohpm install
# 执行构建(hvigorw是鸿蒙的构建命令)
# Windows环境用 hvigorw.bat
hvigorw.bat assembleHap
# macOS/Linux环境用 hvigorw
chmod +x hvigorw
./hvigorw assembleHap
# 指定模块和产品构建
hvigorw.bat assembleHap --mode module -p module=entry@default -p product=default
看起来简单对吧?但这里有个坑——环境变量。CI服务器上没有DevEco Studio,你得手动配置好Node.js、ohpm、HarmonyOS SDK的路径。
# CI服务器环境变量配置示例(Linux)
export NODE_HOME=/usr/local/node
export OHPM_HOME=/opt/ohpm
export HARMONYOS_SDK_HOME=/opt/HarmonyOS/sdk
export PATH=$NODE_HOME/bin:$OHPM_HOME/bin:$PATH
# 验证环境
node --version # 需要 Node.js 14+
ohpm --version # 验证ohpm可用
hvigorw --version # 验证hvigorw可用
进阶用法:GitLab CI集成
环境搞定后,接下来写CI配置。以GitLab CI为例(Jenkins后面单独说),这是目前中小团队最常用的方案。
# .gitlab-ci.yml - 鸿蒙项目CI配置
stages:
- install
- build
- test
- archive
variables:
# 项目路径和SDK路径
PROJECT_DIR: "/builds/your-group/your-project"
SDK_HOME: "/opt/HarmonyOS/sdk"
# 缓存ohpm依赖,加速后续构建
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .ohpm-cache/
- entry/node_modules/
- node_modules/
# 阶段1:安装依赖
install_deps:
stage: install
image: node:18
before_script:
- export OHPM_HOME=/opt/ohpm
- export PATH=$OHPM_HOME/bin:$PATH
script:
- echo "安装项目依赖..."
- ohpm install --all
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
# 阶段2:编译构建
build_hap:
stage: build
image: node:18
needs: [install_deps]
before_script:
- export OHPM_HOME=/opt/ohpm
- export HARMONYOS_SDK_HOME=$SDK_HOME
- export PATH=$OHPM_HOME/bin:$PATH
script:
- echo "开始构建HAP..."
- chmod +x hvigorw
- ./hvigorw assembleHap --mode module -p module=entry@default -p product=default --no-daemon
artifacts:
paths:
- entry/build/default/outputs/default/entry-default-signed.hap
expire_in: 7 days
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_MERGE_REQUEST_IID'
# 阶段3:单元测试
unit_test:
stage: test
image: node:18
needs: [install_deps]
script:
- echo "执行单元测试..."
- ./hvigorw --mode module -p module=entry@default -p product=default test@ut --no-daemon
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
# 阶段4:产物归档
archive:
stage: archive
image: node:18
needs: [build_hap, unit_test]
script:
- echo "归档构建产物..."
- mkdir -p archive
- cp entry/build/default/outputs/default/entry-default-signed.hap archive/
- echo "构建时间: $(date)" > archive/build-info.txt
- echo "提交哈希: ${CI_COMMIT_SHA}" >> archive/build-info.txt
artifacts:
paths:
- archive/
expire_in: 30 days
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
这里有几个关键设计点:
--no-daemon参数:CI环境里一定要加这个,否则hvigorw会启动守护进程,CI任务结束后进程不退出,导致构建卡住- 缓存配置:ohpm依赖下载很慢,缓存能节省大量时间
needs关键字:GitLab CI的DAG模式,test和build可以并行(如果测试不依赖构建产物)rules而非only/except:新语法,更灵活
完整示例:Jenkins Pipeline
大公司用Jenkins的更多,因为插件生态丰富、权限管理细。下面是一个完整的Jenkinsfile:
// Jenkinsfile - 鸿蒙项目Jenkins流水线
pipeline {
agent {
label 'harmonyos' // 指定已配置鸿蒙环境的构建节点
}
environment {
// 签名相关配置(从Jenkins凭据管理中读取)
SIGN_CERT = credentials('harmonyos-sign-cert')
SIGN_PROFILE = credentials('harmonyos-sign-profile')
BUILD_NUMBER_FORMATTED = "${env.BUILD_NUMBER}".padLeft(4, '0')
}
options {
// 构建超时30分钟
timeout(time: 30, unit: 'MINUTES')
// 不并发构建同一分支
disableConcurrentBuilds()
// 保留最近20次构建
buildDiscarder(logRotator(numToKeepStr: '20'))
}
triggers {
// 每天凌晨2点检查SCM变更
pollSCM('H 2 * * *')
}
stages {
stage('环境检查') {
steps {
sh '''
echo "========== 环境信息 =========="
node --version
ohpm --version || echo "ohpm未安装"
echo "SDK路径: ${HARMONYOS_SDK_HOME}"
echo "当前分支: ${BRANCH_NAME}"
echo "构建编号: #${BUILD_NUMBER}"
'''
}
}
stage('依赖安装') {
steps {
sh 'ohpm install --all'
}
}
stage('代码检查') {
steps {
// ArkTS代码风格检查(如果有配置的话)
sh '''
if [ -f ".eslintrc.js" ]; then
echo "执行代码风格检查..."
ohpm run lint || true
fi
'''
}
}
stage('编译构建') {
steps {
sh '''
echo "开始构建HAP..."
chmod +x hvigorw
./hvigorw assembleHap \
--mode module \
-p module=entry@default \
-p product=default \
--no-daemon
'''
}
post {
failure {
archiveArtifacts artifacts: 'entry/build/**/*.log', allowEmptyArchive: true
}
}
}
stage('单元测试') {
steps {
sh '''
./hvigorw --mode module \
-p module=entry@default \
-p product=default \
test@ut --no-daemon || true
'''
}
post {
always {
// 收集测试报告
junit '**/test-results/**/*.xml'
}
}
}
stage('产物归档') {
when {
branch 'main'
}
steps {
sh '''
mkdir -p archive
cp entry/build/default/outputs/default/entry-default-signed.hap archive/
echo "构建时间: $(date)" > archive/info.txt
echo "Git提交: $(git rev-parse HEAD)" >> archive/info.txt
echo "构建编号: #${BUILD_NUMBER}" >> archive/info.txt
'''
archiveArtifacts artifacts: 'archive/**', fingerprint: true
}
}
}
post {
success {
echo '✅ CI流水线执行成功'
}
failure {
echo '❌ CI流水线执行失败,请检查日志'
// 发送钉钉/飞书通知
dingtalk(
robot: 'harmonyos-ci',
type: 'MARKDOWN',
title: '构建失败',
text: ["鸿蒙项目构建失败\n分支: ${BRANCH_NAME}\n构建号: #${BUILD_NUMBER}"]
)
}
always {
cleanWs() // 清理工作空间
}
}
}
Jenkins相比GitLab CI,优势在于:
- 凭据管理:签名证书、Profile文件不用硬编码在配置里
- 节点标签:可以指定专门配置了鸿蒙环境的构建机器
- 插件生态:钉钉通知、JUnit报告、SonarQube集成都有现成插件
- 权限控制:谁触构建、谁看日志,粒度更细
踩坑与注意事项
坑1:CI环境缺少SDK
这是最常见的问题。DevEco Studio会自动下载SDK,但CI服务器上没有IDE,SDK得手动装。
解决方案:
# 方案一:手动下载SDK并解压到CI服务器
# 从华为开发者网站下载Command Line Tools
wget https://developer.huawei.com/.../commandline-tools.zip
unzip commandline-tools.zip -d /opt/HarmonyOS/
# 方案二:用Docker镜像统一环境
# Dockerfile
FROM node:18
RUN apt-get update && apt-get install -y openjdk-17-jdk
COPY commandline-tools /opt/HarmonyOS/
ENV HARMONYOS_SDK_HOME=/opt/HarmonyOS/sdk
ENV OHPM_HOME=/opt/HarmonyOS/tools/ohpm
ENV PATH=$OHPM_HOME/bin:$PATH
RUN ohpm --version
推荐方案二,Docker镜像一劳永逸,所有CI节点环境一致。
坑2:签名文件在CI环境不可用
本地开发时签名是DevEco Studio自动处理的,CI环境里得自己搞定。
解决方案:把签名证书和Profile存到CI系统的凭据管理中,构建时动态注入。
# 构建前注入签名配置
# 修改build-profile.json5中的签名路径
SIGN_CERT_PATH=$SIGN_CERT # 从CI凭据中获取
SIGN_PROFILE_PATH=$SIGN_PROFILE
# 使用sed替换配置文件中的签名路径
sed -i "s|/local/sign/cert.p12|${SIGN_CERT_PATH}|g" build-profile.json5
sed -i "s|/local/sign/profile.p7b|${SIGN_PROFILE_PATH}|g" build-profile.json5
坑3:hvigorw守护进程导致构建卡死
CI环境里hvigorw默认会启动守护进程,构建完了进程不退出,CI任务永远跑不完。
解决方案:始终加--no-daemon参数。
# ❌ 错误写法
./hvigorw assembleHap
# ✅ 正确写法
./hvigorw assembleHap --no-daemon
坑4:ohpm依赖下载超时
ohpm默认从华为官方源下载,CI服务器网络不好的话经常超时。
解决方案:配置ohpm镜像源和超时时间。
# 配置ohpm镜像源
ohpm config set registry https://ohpm.harmonyos.com/ohpm/
# 增加超时时间
ohpm config set fetch_timeout 120000
# 或者搭建内部ohpm代理
ohpm config set registry https://internal-mirror.your-company.com/ohpm/
坑5:并行构建导致资源争抢
多个CI任务同时跑,CPU和内存不够用,构建速度反而变慢甚至OOM。
解决方案:限制并发构建数,或者按模块串行构建。
// Jenkins限制并发
options {
disableConcurrentBuilds()
}
// GitLab CI资源限制
build_hap:
stage: build
resource_group: harmonyos-build // 同一资源组互斥
HarmonyOS 6适配说明
HarmonyOS 6对CI流水线有几个重要影响:
-
SDK版本升级:HarmonyOS 6对应API 16+,CI环境需要更新SDK。旧版SDK编译的HAP无法在新系统上运行,确保CI始终使用最新SDK。
-
构建工具版本:hvigorw 5.x版本对HarmonyOS 6做了适配,低版本可能构建失败。检查
hvigor-config.json5中的版本号:
// hvigor-config.json5
{
"modelVersion": "5.0.0",
"dependencies": {
}
}
-
ohpm版本兼容:HarmonyOS 6的部分新API依赖新版ohpm包,CI环境中的ohpm需要升级到5.0+。
-
签名机制变更:HarmonyOS 6强化了应用签名验证,CI中的签名配置需要同步更新,特别是debug签名和release签名的区分。
-
构建产物格式:HarmonyOS 6支持新的应用包格式,CI产物归档时注意收集所有必要文件(HAP、APP、SO等)。
总结
CI流水线搭建是鸿蒙项目工程化的基础。核心就三件事:让构建能在命令行跑、让流水线能自动触发、让问题能及时暴露。
| 维度 | 评价 |
|---|---|
| 学习难度 | ⭐⭐⭐⭐ 需要理解CI/CD概念,熟悉DevEco命令行工具和至少一种CI平台 |
| 使用频率 | ⭐⭐⭐⭐⭐ 每次代码提交都会触发,是开发流程的核心基础设施 |
| 重要程度 | ⭐⭐⭐⭐⭐ 没有CI的团队就像没有安全带的汽车——能开,但出事就是大事 |
几个关键提醒:
- 先搞定命令行构建,再搞CI配置。命令行都跑不通,CI配置写得再漂亮也没用
- Docker化你的CI环境,环境一致性是CI可靠性的前提
- 签名文件走凭据管理,千万别把证书提交到代码仓库
--no-daemon是CI环境的标配,忘了这个能让你调试半天- 从简单流水线开始,先跑通"提交→构建→归档",再逐步加测试、代码检查等阶段
CI搭建好了,下一步就是CD——让构建产物自动部署到测试环境。那才是真正实现"提交即发布"的闭环。
- 点赞
- 收藏
- 关注作者
评论(0)