HarmonyOS开发:持续集成CI流水线搭建

举报
Jack20 发表于 2026/06/24 16:46:35 2026/06/24
【摘要】 HarmonyOS开发:持续集成CI流水线搭建📌 核心要点:CI流水线是鸿蒙项目工程化的第一道关——代码提交即触发自动构建和测试,把集成问题消灭在萌芽阶段,而不是等到发布前才发现一堆冲突。 背景与动机你有没有经历过这种场景?周五下午5点,大家兴冲冲准备下班,突然测试同学跑过来说"打包失败了"。你一看日志,A同学改了公共模块的接口,B同学还在用老接口,编译直接炸了。然后就是一通互相确认、改...

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"'

这里有几个关键设计点:

  1. --no-daemon参数:CI环境里一定要加这个,否则hvigorw会启动守护进程,CI任务结束后进程不退出,导致构建卡住
  2. 缓存配置:ohpm依赖下载很慢,缓存能节省大量时间
  3. needs关键字:GitLab CI的DAG模式,test和build可以并行(如果测试不依赖构建产物)
  4. 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流水线有几个重要影响:

  1. SDK版本升级:HarmonyOS 6对应API 16+,CI环境需要更新SDK。旧版SDK编译的HAP无法在新系统上运行,确保CI始终使用最新SDK。

  2. 构建工具版本:hvigorw 5.x版本对HarmonyOS 6做了适配,低版本可能构建失败。检查hvigor-config.json5中的版本号:

// hvigor-config.json5
{
  "modelVersion": "5.0.0",
  "dependencies": {
  }
}
  1. ohpm版本兼容:HarmonyOS 6的部分新API依赖新版ohpm包,CI环境中的ohpm需要升级到5.0+。

  2. 签名机制变更:HarmonyOS 6强化了应用签名验证,CI中的签名配置需要同步更新,特别是debug签名和release签名的区分。

  3. 构建产物格式:HarmonyOS 6支持新的应用包格式,CI产物归档时注意收集所有必要文件(HAP、APP、SO等)。

总结

CI流水线搭建是鸿蒙项目工程化的基础。核心就三件事:让构建能在命令行跑、让流水线能自动触发、让问题能及时暴露

维度 评价
学习难度 ⭐⭐⭐⭐ 需要理解CI/CD概念,熟悉DevEco命令行工具和至少一种CI平台
使用频率 ⭐⭐⭐⭐⭐ 每次代码提交都会触发,是开发流程的核心基础设施
重要程度 ⭐⭐⭐⭐⭐ 没有CI的团队就像没有安全带的汽车——能开,但出事就是大事

几个关键提醒:

  • 先搞定命令行构建,再搞CI配置。命令行都跑不通,CI配置写得再漂亮也没用
  • Docker化你的CI环境,环境一致性是CI可靠性的前提
  • 签名文件走凭据管理,千万别把证书提交到代码仓库
  • --no-daemon是CI环境的标配,忘了这个能让你调试半天
  • 从简单流水线开始,先跑通"提交→构建→归档",再逐步加测试、代码检查等阶段

CI搭建好了,下一步就是CD——让构建产物自动部署到测试环境。那才是真正实现"提交即发布"的闭环。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。