干货分享!基于 Github Action 的 taosX CI 搭建

简介: 去年随着 3.1.1.0 版本的发布,TDengine 数据接入工具 taosX 正式推出。该工具具备强大的数据抓取、清洗、转换及加载(ETL)功能。它不仅能无缝对接物联网中的 MQTT 协议,更重要的是能够连接到工业数据源如 OPC-UA、OPC-DA、PI System 等。借助这一模块,工业场景中常用的 SCADA、DCS 等系统无需编写任何代码,仅需通过简单配置即可实现数据的实时、持续导入至 TDengine。

去年随着 3.1.1.0 版本的发布,TDengine 数据接入工具 taosX 正式推出。该工具具备强大的数据抓取、清洗、转换及加载(ETL)功能。它不仅能无缝对接物联网中的 MQTT 协议,更重要的是能够连接到工业数据源如 OPC-UA、OPC-DA、PI System 等。借助这一模块,工业场景中常用的 SCADA、DCS 等系统无需编写任何代码,仅需通过简单配置即可实现数据的实时、持续导入至 TDengine。

此外,该工具支持在 BI 和可视化工具中展示数据,实现远程监控、实时报警和可预测性维护等功能。用户还可以通过微信小程序直接查看设备的运行状态和生成报表。因此,taosX 不仅提升了企业的操作效率,还大幅简化了数据管理流程,助力企业更专注于核心业务的创新与发展,自推出以来,便获得了众多企业客户的关注。

在本篇文章中,我们将深入探讨 taosX 在持续集成(CI)流程优化以及其具体应用场景中的实践。在本次 CI 流程优化后,taosX 的工程质量得到了大幅提升,助力企业能够更有效地利用其数据资源。

使用 GitHub Action 优化现有 CI 流程

在优化之前,taosX 的 CI 流程是基于 Jenkins 构建的。具体来说,当 taosX/Explorer 的 main/3.0 分支有代码合并时,通过在 GitHub 仓库中配置的 webhook 自动触发编译和部署的 Jenkins 作业。该作业完成后,根据 Jenkins 作业之间配置的依赖关系,可以自动或手动触发自动化测试用例的执行作业。测试用例是通过 pytest 工具驱动的,执行完毕后会生成 Allure 测试报告。这一流程确保了代码变更的连续集成和质量控制。

为解决 CI 流程触发滞后性等问题,TDengine 研发团队决定采用 Github 提供的 CI/CD 解决方案 [Github Action](使用 GitHub Action 优化现有 CI 流程
在优化之前,taosX 的 CI 流程是基于 Jenkins 构建的。具体来说,当 taosX/Explorer 的 main/3.0 分支有代码合并时,通过在 GitHub 仓库中配置的 webhook 自动触发编译和部署的 Jenkins 作业。该作业完成后,根据 Jenkins 作业之间配置的依赖关系,可以自动或手动触发自动化测试用例的执行作业。测试用例是通过 pytest 工具驱动的,执行完毕后会生成 Allure 测试报告。这一流程确保了代码变更的连续集成和质量控制。

为解决 CI 流程触发滞后性等问题,TDengine 研发团队决定采用 Github 提供的 CI/CD 解决方案 Github Action 对 taosX 的 CI 流程进行优化。
在使用 Github Action 需要确定 workflow 中任务执行所使用的 runner。所谓 runner 就是可以运行 Github Action 中的任务的机器。在 runner 中可以执行仓库 clone,软件的安装等任务。Github 默认提供了 runner 来执行 Action 中的任务,这些 runner 其实是 Github 安装好的虚拟机,这些 runner 也被称为 Github-hosted runner。有 Github 提供的机器,相对的也可以用用户自己的机器来运行 workflow。这些机器作为 runner 时被称为 Self-hosted runner。在使用 Github-hosted runner 的时候无法自定义硬件资源(比如 cpu 核数,内存等)。而 Self-hosted runner 则可以控制硬件资源,操作系统以及安装的各个软件。
在 taosx 运行的过程中由于需要加快 CI 流程的运行,需要一个硬件配置较高的设备(taosx 在编译的时候耗时较长,实际测试中发现如果使用 2c4g 的虚拟机进行编译的话耗时在 20 分钟左右,而使用 40c256g 的物理机编译时,耗时在 3 分钟左右)。在执行端到端测试的时候可以提前将测试代码 clone 到一个固定位置,每次只需要 git pull 进行更新,这样也会节省代码拉取的时间。鉴于以上因素,在执行 taosx CI 的是时候选用了 Self-hosted runner。
注意:Self-hosted runner 并不局限在物理机或虚拟机上,可以是一个容器,也可以部署到云端。
Github-hosted runner 与 Self-hosted runner 的详细区别见 Differences between GitHub-hosted and self-hosted runners

在确定使用 Self-hosted runner 之后,就需要对现有的流程所使用的 workflow 文件进行编排,taosX CI 完整的 workflow 主要包含以下环节:
1.png
此流程是通过编写 YAML 格式的 workflow 文件来定义的,该文件需要放在 taosX 代码仓库的.github/workflows目录下。其定义分为以下几个部分:

# 名称
name: PR-QA-workflow

# 触发方式
on:
  workflow_dispatch:
  pull_request:

# 全局变量
env:
  RELEASE_HOST: 192.168.1.45
  RUSTFLAGS: "-C instrument-coverage --cfg tokio_unstable"
  ARTIFACT_BASE_DIR: /data/artifacts
  COVERAGE_BASE_DIR: /data/coverage
  DIR_PATH: ${
  
  { github.event.number }}
  RUN_UNIT_TEST_FILE_FLAG: /etc/taos/taosx_run_unit_test

# 具体的job
jobs:
  build_rust:
    ...
  build_go:
    ...

下文将按照 workflow 的顺序,对每个环节进行逐一介绍。

1. 触发

用于触发 workflow 的配置如下:

jon:
  workflow_dispatch:
  pull_request:

说明:

  • on.workflow_dispatch:表示该 workflow 可以手动触发,不过 GitHub 限制该 workflow 必须位于默认分支上才可以手动触发,并且也只会在默认分支上生效。
  • on.pull_request:表示当提交 PR 的时候对当前分支(PR 的源分支)触发。
    关于触发事件的完整描述可参考:Events that trigger workflows

    2. 全局环境变量

    在 workflow 中,我们设置了一些全局的环境变量,以供 workflow 中的 job 使用,具体如下所示:
    jenv:
    RELEASE_HOST: 192.168.1.45
    RUSTFLAGS: "-C instrument-coverage --cfg tokio_unstable" # rust 用于获取覆盖率的编译用环境变量
    ARTIFACT_BASE_DIR: /data/artifacts # 编译之后编译中间文件及可执行文件存放的根目录
    COVERAGE_BASE_DIR: /data/coverage # 生成报告后报告存放的根目录
    DIR_PATH_3_0: "3.0" # 下一级使用 3.0 或 PR Number
    DIR_PATH: ${
        
        { github.event.number }} # 下一级使用 3.0 或 PR Number
    RUN_UNIT_TEST_FILE_FLAG: /etc/taos/taosx_run_unit_test
    

    3. 编译

  1. 在编译过程中,taosx、taosx-agent、opc 以及 mqtt 各个组件需要设置特定的环境变量,以便输出插桩程序。由于这些组件在编译过程中没有相互依赖,因此设置了三个可以并行执行的任务,分别负责各自组件的编译工作。

    j  build_rust:
     runs-on: [self-hosted, linux, x64, qa, rust]
    
    build_go:
     runs-on: [self-hosted, linux, x64, qa, go]
    
    build_java:
     runs-on: [self-hosted, linux, x64, qa, java]
    

    三个编译任务—Rust编译、Go编译、Java编译—之间不存在依赖关系,且各自在不同的机器上运行。因此,这三个任务可以同时并行执行。

  2. 在 taosx 及 taox-agent 编译和单元测试执行完成之后,需要将编译过程中产生的中间文件及可执行程序拷贝至特定目录,用以留存和区分。
    j  - name: Copy files
     run: |
       ls $ARTIFACT_BASE_DIR/$DIR_PATH/bin || mkdir -p $ARTIFACT_BASE_DIR/$DIR_PATH/bin
       cp ./target/debug/taosx-build/debug/taosx ./target/debug/taosx-agent-build/debug/taosx-agent $ARTIFACT_BASE_DIR/$DIR_PATH/bin/
       cp -r ./target/debug/taosx-profraw/ $ARTIFACT_BASE_DIR/$DIR_PATH/
       cp -r ./target/debug/taosx-agent-profraw/ $ARTIFACT_BASE_DIR/$DIR_PATH/
       cd ..
       tar --exclude=./taosx/target/* -zcvf taosx.tar.gz ./taosx
       cp taosx.tar.gz $ARTIFACT_BASE_DIR/$DIR_PATH/
       rm taosx.tar.gz
       tar -xzf $ARTIFACT_BASE_DIR/$DIR_PATH/taosx.tar.gz -C $ARTIFACT_BASE_DIR/$DIR_PATH/
       rm $ARTIFACT_BASE_DIR/$DIR_PATH/taosx.tar.gz
    

4. 单元测试

目前运行了 taosx、opc、mqtt 三个组件的单元测试,单元测试的运行与编译处于同一阶段。

  1. 前期由于单元测试可能存在不稳定,或者单元测试耗时较长等问题的存在,添加了依据 /etc/taos/taosx_run_unit_test 该文件是否存在执行单元测试的逻辑。若该文件存在,则执行。
  2. taosx 编译及运行单元测试的配置如下:
    j      - name: Build taosx
         run: |
           # build taosx and taosx-agent
           # export RUSTFLAGS="-C instrument-coverage --cfg tokio_unstable"
           rm -rf ./target/debug/taosx-profraw/
           export LLVM_PROFILE_FILE="./target/debug/taosx-profraw/taosx-%p-%m.profraw"
           cargo build --target-dir ./target/debug/taosx-build/
       - name: taosx unit test
         continue-on-error: true
         run: |
           if [ -f "$RUN_UNIT_TEST_FILE_FLAG" ]; then
               echo "run taosx unit test"
               cargo llvm-cov nextest --workspace
               cargo llvm-cov report --lcov --output-path $ARTIFACT_BASE_DIR/$DIR_PATH/taosx-unit-test-lcov.info
           fi
    
    taosx 运行完单元测试之后,会输出单元测试覆盖率报告到 $ARTIFACT_BASE_DIR/$DIR_PATH/,用于之后与端到端测试的覆盖率结果进行合并。
  3. MQTT 编译机运行单元测试的配置如下:

    j- name: Build mqtt
         run: |
           cd plugins/mqtt
           go build -cover -o taosx-mqtt
    
       - name: Run Mqtt Unit Test
         continue-on-error: true
         run: |
           cd plugins/mqtt
           if [ -f "$RUN_UNIT_TEST_FILE_FLAG" ]; then
             echo "run mqtt unit test"
             go test -coverpkg=./... -coverprofile=mqtt_unit_report.txt  -timeout=5s ./...
           fi
       - name: Copy MQTT Files
         run: |
           cd plugins/mqtt
           if [ -f "mqtt_unit_report.txt" ]; then
             ssh root@$RELEASE_HOST "ls $ARTIFACT_BASE_DIR/$DIR_PATH/go_cover/mqtt_cover_data/ || mkdir -p $ARTIFACT_BASE_DIR/$DIR_PATH/go_cover/mqtt_cover_data/"
             scp mqtt_unit_report.txt root@$RELEASE_HOST:$ARTIFACT_BASE_DIR/$DIR_PATH/go_cover/mqtt_cover_data/
             rm mqtt_unit_report.txt
           fi
           ssh root@$RELEASE_HOST "ls $ARTIFACT_BASE_DIR/$DIR_PATH/bin/mqtt || mkdir -p $ARTIFACT_BASE_DIR/$DIR_PATH/bin/mqtt/"
           scp taosx-mqtt root@$RELEASE_HOST:$ARTIFACT_BASE_DIR/$DIR_PATH/bin/mqtt/
    

    同样,MQTT 的单元测试报告在单元测试完成之后会输出,并拷贝到 $ARTIFACT_BASE_DIR/$DIR_PATH/go_cover/mqtt_cover_data/,用于之后与端到端测试覆盖率报告合并。

5. 部署

  1. 在部署过程中,需要进行两次部署操作。首先是为 MQTT 用例的执行进行部署。在这一阶段,由于 taosx 或 taosx-agent 需要以子进程的形式启动 taosx-mqtt,因此在运行 MQTT 用例时,必须配置相应的环境变量。如下:

    jsteps:
       - name: Deploy taosx
         run: |
           pwd
           ls ${
        
        { github.workspace }}
           # run taosx
           ssh root@$RELEASE_HOST "ls $ARTIFACT_BASE_DIR/$DIR_PATH_3_0/go_cover/mqtt_cover_data/ || mkdir -p $ARTIFACT_BASE_DIR/$DIR_PATH_3_0/go_cover/mqtt_cover_data/"
           ssh root@$RELEASE_HOST "nohup sh -c 'DATABASE_URL=/var/lib/taos/taosx/taosx.db LLVM_PROFILE_FILE=$ARTIFACT_BASE_DIR/$DIR_PATH_3_0/taosx-profraw/taosx-%p-%m.profraw GOCOVERDIR=$ARTIFACT_BASE_DIR/$DIR_PATH_3_0/go_cover/mqtt_cover_data/ PLUGINS_HOME=$ARTIFACT_BASE_DIR/$DIR_PATH_3_0/bin/ ENABLE_COVERAGE=true nohup $ARTIFACT_BASE_DIR/$DIR_PATH_3_0/bin/taosx serve > $ARTIFACT_BASE_DIR/$DIR_PATH_3_0/bin/taosx.log 2>&1 &'"
    
       - name: Deploy taosx-agent
         run: |
           pwd
           ls ${
        
        { github.workspace }}
           # run taosx-agent
           ssh root@$RELEASE_HOST "nohup sh -c 'GOCOVERDIR=$ARTIFACT_BASE_DIR/$DIR_PATH_3_0/go_cover/mqtt_cover_data/ PLUGINS_HOME=$ARTIFACT_BASE_DIR/$DIR_PATH_3_0/bin/ ENABLE_COVERAGE=true LLVM_PROFILE_FILE=$ARTIFACT_BASE_DIR/$DIR_PATH_3_0/taosx-agent-profraw/taosx-agent-%p-%m.profraw nohup $ARTIFACT_BASE_DIR/$DIR_PATH_3_0/bin/taosx-agent > $ARTIFACT_BASE_DIR/$DIR_PATH_3_0/bin/taosx-agent.log 2>&1 &'"
    
  2. 第二次部署与第一次部署大体相同,区别是 GOCOVERDIR 的赋值会修改为 OPC 准备的目录。
    jGOCOVERDIR=$ARTIFACT_BASE_DIR/$DIR_PATH/go_cover/opc_cover_data
    

    6. 端到端测试

  3. 在部署完成之后,就可以执行端到端的测试。由于第一次部署设置的是 MQTT 的覆盖率文件的路径,所以第一次运行的测试也是 MQTT 的用例。
  4. 端到端测试的代码已经存放至 /data/github/TestNG_taosX,每次执行之前只需要使用 git pull 更新代码即可。
  5. 在执行完端到端测试之后应该停止 taosx 及 taosx-agent 用于获取 taosx 及 agent 的覆盖率信息。此时需要通过 kill -2 关闭,这样能够发送 SIGINT 信号给指定的进程,使得进程能够优雅退出,不能通过 kill -9 否则无法成功获取覆盖率信息。
  6. MQTT 的端到端测试用例的执行配置如下:
j  test_mqtt:
    runs-on: [self-hosted, linux, x64, qa, rust]
    needs: deploy_for_mqtt
    steps:
      - name: Update Repo
        run: |
          # 这里最好是 TestNG_taosx 已经被拉取到一个固定的位置
          # 重新登录执行 git pull,因为当前的 git 仓库对应的是 taosx
          ssh root@$RELEASE_HOST "cd /data/github/TestNG_taosX && git pull"

      - name: Run Test
        run: |
          ls $COVERAGE_BASE_DIR/$DIR_PATH/allure_profile || mkdir -p $COVERAGE_BASE_DIR/$DIR_PATH/allure_profile
          cd /data/github/TestNG_taosX && source ./setenv.sh && poetry install && cd tests && poetry run pytest --alluredir=$COVERAGE_BASE_DIR/$DIR_PATH/allure_profile --timeout=300 -m sanity mqtt_test.py

      - name: Stop taosx-agent & taosx
        run: |
          pids=$(pgrep taosx-agent); if [ -n "$pids" ]; then for pid in $pids; do "run kill -9 taosx-agent"; kill -2 "$pid"; done; fi
          pids=$(pgrep taosx); if [ -n "$pids" ]; then for pid in $pids; do "run kill -9 taosx"; kill -2 "$pid"; done; fi

      - name: Force stop taosx-agent & taosx
        if: always()
        run: |
          pids=$(pgrep taosx-agent); if [ -n "$pids" ]; then for pid in $pids; do "run kill -9 taosx-agent"; kill -9 "$pid"; done; fi
          pids=$(pgrep taosx); if [ -n "$pids" ]; then for pid in $pids; do "run kill -9 taosx"; kill -9 "$pid"; done; fi
  1. 执行除 MQTT 之外的用例的 pytest 命令:
    jcd /data/github/TestNG_taosX && source ./setenv.sh && poetry install && cd tests \
    && poetry run pytest --alluredir=$COVERAGE_BASE_DIR/$DIR_PATH_3_0/allure_profile \
    --timeout=300 -m sanity -k "not mqtt_test.py"
    
    说明:
  2. 执行 poetry install 安装测试依赖
  3. 执行 pytest 命令来运行自动化测试,通过-m 参数指定执行带有 sanity 标签的用例
  4. 通过 --alluredir 参数指定报告的目录
  5. 通过 --timeout 指定每个用例的超时时间,避免出现用例长时间挂起的情况

    7. 生成覆盖率报告

    Job 的日志截图:
    2.png
    taosX 的覆盖率报告截图:

3.png
OpenTSDB 的覆盖率报告截图:

4.png
OPC 的覆盖率报告截图:

5.png

8. 生成测试报告

这里的测试报告则是 pytest 运行完成之后,端到端测试的测试报告。测试报告生成的逻辑如下:

j- name: allure report
        run: |
          allure generate $COVERAGE_BASE_DIR/$DIR_PATH_3_0/allure_profile -o $COVERAGE_BASE_DIR/$DIR_PATH_3_0/allure_report/ --clean
          # 这里会直接输出报告的地址
          echo "see report at $REPORT_BASE_URL/$DIR_PATH_3_0/allure_report/"

Job 的日志如下:

6.png
其中的测试报告链接可以直接点击,测试报告如下图所示:

7.png

一个完整的例子

  1. 开发者通过提交 PR 触发 CI 运行。
    8.png
  2. 通过点击执行的 Action 可以查看执行的结果。

9.png
开发者在查看该 Action 的时候可以在底部看到流程中哪个 Job 的运行是出错了的。

  1. 可以通过点击下方的出错的任务查看任务出错的原因。

10.png

  1. 最后可以通过点击 generate_report 中查看报告的具体结果。
    11.png
    结语
    综上所述,我们已经实现了一项自动化功能:每当开发人员在 taosX 仓库提交 Pull Request(PR)时,即自动触发 CI 流程。通过这一流程,开发和测试人员能够利用生成的测试报告和覆盖率报告来评估 PR 中的代码变更。如果你也对 taosX 这一工具感兴趣,欢迎添加小T微信(tdengine)与 TDengine 的解决方案专家进行一对一沟通。我们将提供专业的指导,帮助你更深入地了解和应用 taosX。
相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
29天前
|
数据安全/隐私保护 开发者 Docker
国内docker公开镜像站的关闭!别急,docker_image_pusher 使用Github Action将国外的Docker镜像转存到阿里云私有仓库
通过使用 docker_image_pusher 这样的开源项目,我们能够轻松地解决国内访问 Docker 镜像拉取速度慢及拉去失败的问题,同时保证了镜像的稳定性和安全性。利用 Github Action 的自动化功能,使得这一过程更加简单和高效。
789 2
|
29天前
【完美解决】Github action报错remote: Write access to repository not granted.
【完美解决】Github action报错remote: Write access to repository not granted.
146 1
|
2月前
|
存储 JavaScript 测试技术
github action
github action
30 0
|
2月前
|
供应链 安全 jenkins
|
缓存 前端开发 持续交付
白嫖github的Action做定时任务
白嫖github的Action做定时任务
白嫖github的Action做定时任务
|
12月前
|
jenkins Java 应用服务中间件
SpringBoot+Jenkins+Github+Docker+Maven持续集成CI与持续部署CD全自动化部署
我们采用tomcat运行war包的这种方式,先来到官网下载war包:https://www.jenkins.io/download/ 然后把war包上传到tomcat的webapps里,自动就解压运行了,访问页面,然后查看并输入密码: cat /root/.jenkins/secrets/initialAdminPassword
201 0
GitHub Action中的github/super-linter作用是什么?
github/super-linter 是一个开源工具包,其中包含多个静态分析工具,用于对代码进行静态分析以查找潜在的错误、优化代码性能和提高代码可读性等。github/super-linter@v3.17.0 是一个版本号,表示这个版本使用了哪个静态分析工具。
89 0
|
存储
【版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数
【版本控制】GitHub图床服务Action---自动监视图床仓库的目录下的文件数
97 0
|
开发工具 git
【经验分享】【Github】Error: Action failed with “The process ‘/usr/bin/git‘ failed with exit code 128“
【经验分享】【Github】Error: Action failed with “The process ‘/usr/bin/git‘ failed with exit code 128“
257 0
|
缓存 Ubuntu Java
Github Action 快速上手指南
Github之前更新了一个Action功能(应该是很久以前了),可以实现很多自动化操作。用来替代用户自己设置的自动化脚本(比如:钩子+Jenkins)。 由于平时根本不会有需求用到它,毕竟平时都在用公司的CI/CD流程,所以一直没有机会玩Action。 借着春节放假,就自己写个小Demo体验一下。 本文通过实现一个提交代码后自动执行Junit单元测试并输出测试报告的自动化流程小Demo,来快速上手Github Action。
499 0