Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
CI/CD_持续集成部署
pkgs-test工具介绍
发布于 2023-07-27 13:32:03 浏览:499
订阅该版
[tocm] # pkgs-test工具介绍 仓库主页 [https://github.com/RT-Thread/pkgs-test](https://github.com/RT-Thread/pkgs-test) # 背景 目前社区软件包存在大量编译问题: - 版本迭代造成的编译问题(内核文件改动后,软件包没有去做版本控制) - 架构冲突以及 bsp 依赖问题(某些软件包只在特定的架构或 bsp 中可用) 针对上述的问题,诞生了 pkgs-test 工具,主要用于暴露出社区软件包的相关编译问题。 # 使用场景 1. **本地使用** 1. 对特定的软件包,在一些指定的bsp、rt-thread版本上进行测试。 2. 指定某一个特定的版本或所有版本。 3. 指定的软件包集合。 2. **作为Github Action使用**,测试软件包是否支持一些rtt版本和bsp。 1. **软件包开发者** 1. **软件包测试** 更新软件包的代码之后,自动对软件包进行测试。 2. **rt-thread的master测试** 定时对软件包进行测试,检查是否支持rt-thread的master版本。 2. **rt-thread社区维护人员** 1. **所有软件包测试** 定时对全部软件包在master 分支或指定的一些版本上进行测试,并发布测试结果到github pages。 2. **软件包索引更新测试** 软件包索引发生改动时,对改动的部分软件包进行测试,在github pages上面更新这部分测试结果。 3. **rt-thread版本发布测试** rt-thread版本发布后对全部的软件包进行测试。 4. **精品软件包集合测试**(TODO) 对一些制定的精品软件包集合进行测试,比如当rt-thread的master分支改动时,测试这些软件包。 # 使用方法 使用方法见仓库主页。 # pkgs-test的class pkgs-test工具内部一共有6个类。 1. PackagesIndex 1. 从软件包索引读取软件包信息,保存到一个字典中。 2. 根据运行时输入的参数来选择需要测试的软件包列表。 2. Config 1. 根据配置文件下载需要的资源rt-thread、toolchains。 2. 下载env工具和软件包索引。 3. 根据运行时输入的参数来修改配置文件。 3. Logs 1. 根据测试结果生成json。 2. 根据json生成html页面。 4. Build 1. 执行编译,并输出编译日志到文件。 5. Change 1. 检查软件包索引的改动。 6. Check 1. 检查Logs生成的json。 # pkgs-test的运行过程 首先使用Config读取配置文件。输入参数args.config是配置文件目录。 ```c config = Config(args.config) ``` 读取输入的软件包名称。 ```c pkgs_name = config.get_pkgs_name(args.pkg) ``` 如果有输入就保存输入的名称,输入为空就从配置文件内读取。 ```c def get_pkgs_name(self, pkg=[]): if pkg: return pkg elif not (self.config_data['pkgs'] == None or self.config_data['pkgs'] == []): return list(self.config_data['pkgs']) return [] ``` 接着下载需要的资源。这里在ci工具里面会事先下载好一些资源,比如软件包索引,如果该目录已经存在,则不会被覆盖,可以用于测试这些还没有发布的资源。 ```c config.get_resources() ``` 读取软件包索引。如果输入参数nolatest那么就不保存latest版本。 ```c packages_index = PackagesIndex(os.path.join( config.get_path('env'), 'packages/packages')) packages_index.nolatest(args.nolatest) ``` 接着选择测试的软件包。 ```c if args.repository: pkgs_config_dict = packages_index.repository_seek(args.repository) else: pkgs_config_dict = packages_index.name_seek(pkgs_name) ``` 这里分为两种情况,一种是作为ci使用,会输出参数repository,另一种是本地使用,读取前面保存的pkgs_name。 name_seek会判断是不是测试全部软件包,如果pkgs_name是all那么就会测试全部软件包。 ```python def name_seek(self, pkgs='all'): if pkgs == 'all': config_dict = self.dict else: config_dict = self.__get_config_pkgs(pkgs) print(config_dict) return config_dict ``` repository_seek会识别repository的类型,如果是软件包仓库就会在软件包索引里面寻找,如果是packages软件包索引仓库就会使用Change寻找软件包索引的改动,将改动的软件包保存到pkgs_config_dict里面。 ```c def repository_seek(self, repository): pkgs = [] repository_name = repository.split("/")[1] if repository_name == 'packages': change = Change(os.path.join(Config().get_path('env'),"packages/packages")) return self.name_seek(change.get_change_pkg_name()) for pkg in self.dict: if repository_name.lower() in pkg['repository'].lower(): pkgs.append(pkg) if len(pkgs) > 1: pkgs_copy = list(pkgs) for pkg in pkgs_copy: if not repository_name in pkg['repository']: pkgs_copy.remove(pkg) if pkgs_copy: pkgs = pkgs_copy if not pkgs: print('You may have changed the warehouse name while forking!!!') return [] for pkg in pkgs[0]['pkg']: if 'URL' in pkg: pkg['URL'] = 'https://github.com/' + repository + '.git' return pkgs ``` 创建一个Log类,用于生成测试结果,这里的append_res是开启从github pages下载旧的测试结果并且与新的合并。 ```c logs = Logs('artifacts_export', config.get_config_data(), pkgs_config_dict) if args.append_res: if args.pages_url: logs.pages_url = args.pages_url logs.append_res = True ``` 最后执行编译,并根据编译的log生成json和html。 ```c build = Build(config, pkgs_config_dict, logs, args.j) ``` 其中关于发布测试结果的部分在这里详细说明一下。 执行Logs.logs()会根据编译日志生成测试结果json与html页面。 其中有两个json文件,pkgs_res_single是本次执行pkgs-test产生的测试结果,pkgs_res是与旧的测试结果合并后的,如果没有合并那么两个json相同。这里从代码可以看到,两个json文件都使用__build_res生成,如果传入True那么就会合并,如果False那么就只有本次结果。 index.html则是根据pkgs_res生成的页面。 ```python def logs(self): pkgs_res_single_dict = self.__build_res(False) with open(os.path.join(self.logs_path, 'pkgs_res_single.json'), 'w') as f: json.dump(pkgs_res_single_dict, f) self.pkgs_res_dict = self.__build_res(self.append_res) with open(os.path.join(self.logs_path, 'pkgs_res.json'), 'w') as f: json.dump(self.pkgs_res_dict, f) logs_html = self.__html_report() with open(os.path.join(self.logs_path, 'index.html'), 'w') as f: for log in logs_html: f.write(log) ``` # Workflow的运行过程 workflow分为3个job,packages-test用于测试软件包,check-errors用于检查测试结果,Deploy-Pages发布测试结果页面。 ## packages-test 首先是下载运行的仓库和pkgs-tese仓库。 ```c - uses: actions/checkout@v3 with: path: repository - uses: actions/checkout@v3 with: repository: '${{ inputs.pkgs-test-repository }}' ref: '${{ inputs.pkgs-test-branch }}' path: pkgs-test ``` 接下来是安装一些软件和工具。 ```c - name: Install Tools shell: bash run: | sudo apt install python3 python3-pip gcc git libncurses5-dev tree -y python3 -m pip install scons==4.4.0 requests tqdm wget dominate PyGithub requests pytz ``` 如果运行的仓库是软件包索引,那么就把软件包索引仓库复制到后面需要下载软件包索引的路径。 ```c - name: Copy RT-Thread/packages to env if: "${{ endsWith(github.repository, '/packages') == true }}" shell: bash run: | cd ${{ github.workspace }} mkdir -p ./pkgs-test/env/packages cp -r ./repository ./pkgs-test/env/packages/packages ``` 根据输入的配置参数下载对应的资源,rt-thread、bsp对应的工具链、env工具、软件包索引。 ```c - name: Install Test Resources shell: bash run: | cd ${{ github.workspace }}/pkgs-test python pkgs-test.py config --rtthread='${{ inputs.rt-thread-versions }}' python pkgs-test.py config --bsps='${{ inputs.bsps }}' python pkgs-test.py download ``` 执行编译测试,这里根据输入的参数会选择是否测试全部软件包,是否测试软件包latest版本,是否合并测试结果。 ```c - name: Carry Out Packages Test shell: bash run: | cd ${{ github.workspace }}/pkgs-test echo 'Carry Out Packages Test.' if [[ ${{ inputs.package-test-all}} == true ]]; then COMMAND="python pkgs-test.py --pkg=all" else COMMAND="python pkgs-test.py --repository=${{ inputs.package-repository }}" fi if [[ ${{ inputs.package-test-nolatest}} == true ]]; then echo 'nolatest.' COMMAND="$COMMAND --nolatest" fi if [[ ${{ inputs.package-append-res}} == true ]]; then echo 'Append test res to old res from githubpage.' COMMAND="$COMMAND --append_res --pages_url='${{ inputs.pages-url}}'" fi echo "$COMMAND" eval "$COMMAND" ``` 最后就是导出artifacts_export目录的测试结果、一个是方便维护者下载、一个是用来发布页面。 ```c - uses: actions/upload-artifact@v3 with: name: artifacts_export path: ${{ github.workspace }}/pkgs-test/artifacts_export ``` ## check-errors 这个job比较简单,就是根据下载的测试结果执行判断。 ```c check-errors: runs-on: ubuntu-latest needs: packages-test if: "${{ inputs.check-errors }}" steps: - uses: actions/checkout@v3 with: repository: '${{ inputs.pkgs-test-repository }}' ref: '${{ inputs.pkgs-test-branch }}' - name: Download artifacts_export uses: actions/download-artifact@v3 with: name: artifacts_export - name: Install Tools shell: bash run: | sudo apt install python3 python3-pip -y python3 -m pip install requests tqdm wget dominate PyGithub requests pytz - name: Packages test whether or not error shell: bash run: | python pkgs-test.py check --file='pkgs_res_single.json' ``` ## Deploy-Pages Deploy-Pages就是将artifacts_export发布到github pages。 ```c Deploy-Pages: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: packages-test if: "${{ inputs.deploy-pages }}" steps: - name: Download artifacts_export uses: actions/download-artifact@v3 with: name: artifacts_export - name: Setup Pages uses: actions/configure-pages@v3 - name: Upload artifact uses: actions/upload-pages-artifact@v1 with: # Upload entire repository path: '.' - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v2 ``` # **作为Github Action使用** 目前可以在软件包索引仓库和软件包仓库使用pkgs-test来测试软件包的编译情况。 ## Packages仓库 软件包索引仓库里面目前有两个功能,一个是当发生改动的时候测试改动的软件包,另外就是定时测试全部的软件包。 ### 改动测试 这里是Packages仓库的软件包测试workflow文件其中的一个job,目的是当发生改动的时候测试改动的软件包。 ```c change: if: ${{ github.event_name == 'pull_request' || github.event_name == 'push'}} uses: RT-Thread/pkgs-test/.github/workflows/pkgs-action.yml@main with: package-append-res: true deploy-pages: true ``` 这里使用if进行了判断,当workflow的触发事件是pull_request或者push的时候,执行change这个job。 传入的参数有两个,package-append-res用来开启从github pages下载旧的测试结果并且与新的合并,deploy-pages用来开启将测试结果发布到github pagses。 ### 定时全部测试 这里我举出两个jobs的例子,测试master内核版本下两个bsp的软件包编译情况。 ```c master-stm32h750-artpi-test: if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'}} uses: RT-Thread/pkgs-test/.github/workflows/pkgs-action.yml@main with: bsps: stm32/stm32h750-artpi:sourcery-arm rt-thread-versions: branch:master package-append-res: true package-test-all: true deploy-pages: true check-errors: false master-k210-test: if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'}} needs: master-stm32h750-artpi-test uses: RT-Thread/pkgs-test/.github/workflows/pkgs-action.yml@main with: bsps: k210:sourcery-riscv-none-embed rt-thread-versions: branch:master package-append-res: true package-test-all: true deploy-pages: true check-errors: false ``` 测试全部软件包的触发事件有两个,schedule定时测试和workflow_dispatch手动触发,这里也是使用if来判断的。 这里注意一下,测试全部软件包需要一个接着一个按顺序测试,不能并行进行测试,不然发布测试结果会产生冲突,workflow文件也用了concurrency这个参数来确保每次只有一个workflow在运行,让其余的进行等待。 ```c concurrency: group: pkgs-test cancel-in-progress: false # wait for finish. ``` 然后解释一下传入的参数。 1. bsps指的就是测试的bsp和其使用的工具链,用冒号进行分隔。 2. rt-thread-versions指的就是内核的版本,branch和tag有两种不同的输入方法`branch:master tag:v4.1.1` 3. package-append-res表示的是从github pages下载旧的测试结果并且与新的合并。 4. package-test-all就是最主要的一个参数,表示测试全部软件包。 5. deploy-pages表示发布测试结果到GitHub pages。 6. check-errors表示关闭错误检查,这里是因为主要目的是发布测试结果,所以用不需要检查是否有软件包没有通过编译测试。 ## 软件包仓库 软件包仓库的使用方法比较简单,不需要输入任何参数,它的测试过程和本地测试基本上一致。 这里有一个例子,[https://github.com/RT-Thread-packages/hello](https://github.com/RT-Thread-packages/hello) 它的workflow文件是这样的。 ```c name: RT-Thread_Packages_Test on: [push, pull_request] jobs: pkgs-test: uses: RT-Thread/pkgs-test/.github/workflows/pkgs-action.yml@main ``` # 未来会实现的功能 1. 定期测试全部软件包后会通知给软件包所有者:使用action打开一个issue,在里面@有问题的软件包作者。 2. 增加一个软件包可用性分级:1.有最新release版本可用。2.只有latest版本、或者最新版软件包不可用但有旧版可用 3.全部失败 3. 再完善一下结果报告页面,比如按类别给包分组。 4. 针对rt-thread内核的测试,对一个精选软件包集合进行测试。
7
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
vacabun
这家伙很懒,什么也没写!
文章
6
回答
0
被采纳
0
关注TA
发私信
相关文章
1
生成目标文件的时候,有什么好方法能读取两个不同的链接文件,来生成两个链接地址不同的目标文件(.bin .hex)
2
想在CI/CD中加入 RTT studio项目构建, 如果启用命令行方式的构建
3
RT1052的gcc后的bin执行异常
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
812
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部