pkgs-test工具介绍及其使用方法

电子说

1.3w人已加入

描述

背景

目前社区软件包存在大量编译问题:

版本迭代造成的编译问题(内核文件改动后,软件包没有去做版本控制)
架构冲突以及 bsp 依赖问题(某些软件包只在特定的架构或 bsp 中可用)
针对上述的问题,诞生了 pkgs-test 工具,主要用于暴露出社区软件包的相关编译问题。

使用场景

本地使用

对特定的软件包,在一些指定的bsp、rt-thread版本上进行测试。
指定某一个特定的版本或所有版本。
指定的软件包集合。
作为Github Action使用,测试软件包是否支持一些rtt版本和bsp。

软件包开发者

软件包测试

更新软件包的代码之后,自动对软件包进行测试。

rt-thread的master测试

定时对软件包进行测试,检查是否支持rt-thread的master版本。

rt-thread社区维护人员

所有软件包测试

定时对全部软件包在master 分支或指定的一些版本上进行测试,并发布测试结果到github pages。

软件包索引更新测试

软件包索引发生改动时,对改动的部分软件包进行测试,在github pages上面更新这部分测试结果。

rt-thread版本发布测试

rt-thread版本发布后对全部的软件包进行测试。

精品软件包集合测试(TODO)

对一些制定的精品软件包集合进行测试,比如当rt-thread的master分支改动时,测试这些软件包。

pkgs-test的class
pkgs-test工具内部一共有6个类。

‎PackagesIndex
从软件包索引读取软件包信息,保存到一个字典中。
根据运行时输入的参数来选择需要测试的软件包列表。
Config
根据配置文件下载需要的资源rt-thread、toolchains。
下载env工具和软件包索引。
根据运行时输入的参数来修改配置文件。
Logs
根据测试结果生成json。
根据json生成html页面。
Build
执行编译,并输出编译日志到文件。
Change
检查软件包索引的改动。
Check
检查Logs生成的json。
pkgs-test的运行过程
首先使用Config读取配置文件。输入参数args.config是配置文件目录。

config = Config(args.config)
读取输入的软件包名称。

pkgs_name = config.get_pkgs_name(args.pkg)
如果有输入就保存输入的名称,输入为空就从配置文件内读取。

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工具里面会事先下载好一些资源,比如软件包索引,如果该目录已经存在,则不会被覆盖,可以用于测试这些还没有发布的资源。

config.get_resources()
读取软件包索引。如果输入参数nolatest那么就不保存latest版本。

packages_index = PackagesIndex(os.path.join(
config.get_path('env'), 'packages/packages'))
packages_index.nolatest(args.nolatest)
接着选择测试的软件包。

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那么就会测试全部软件包。

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里面。

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下载旧的测试结果并且与新的合并。

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。

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生成的页面。

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仓库。

  • 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
      接下来是安装一些软件和工具。
  • 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
    如果运行的仓库是软件包索引,那么就把软件包索引仓库复制到后面需要下载软件包索引的路径。
  • 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工具、软件包索引。
  • 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版本,是否合并测试结果。
  • 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目录的测试结果、一个是方便维护者下载、一个是用来发布页面。
  • uses: actions/upload-artifact@v3
    with:
    name: artifacts_export
    path: ${{ github.workspace }}/pkgs-test/artifacts_export
    check-errors
    这个job比较简单,就是根据下载的测试结果执行判断。

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。

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,目的是当发生改动的时候测试改动的软件包。

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的软件包编译情况。

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:
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在运行,让其余的进行等待。

concurrency:
group: pkgs-test
cancel-in-progress: false # wait for finish.
然后解释一下传入的参数。

bsps指的就是测试的bsp和其使用的工具链,用冒号进行分隔。
rt-thread-versions指的就是内核的版本,branch和tag有两种不同的输入方法branch:master tag:v4.1.1
package-append-res表示的是从github pages下载旧的测试结果并且与新的合并。
package-test-all就是最主要的一个参数,表示测试全部软件包。
deploy-pages表示发布测试结果到GitHub pages。
check-errors表示关闭错误检查,这里是因为主要目的是发布测试结果,所以用不需要检查是否有软件包没有通过编译测试。

软件包仓库

软件包仓库的使用方法比较简单,不需要输入任何参数,它的测试过程和本地测试基本上一致。

它的workflow文件是这样的。

name: RT-Thread_Packages_Test
on:
[push, pull_request]
jobs:
pkgs-test:

未来会实现的功能

定期测试全部软件包后会通知给软件包所有者:使用action打开一个issue,在里面@有问题的软件包作者。
增加一个软件包可用性分级:1.有最新release版本可用。2.只有latest版本、或者最新版软件包不可用但有旧版可用 3.全部失败
再完善一下结果报告页面,比如按类别给包分组。
针对rt-thread内核的测试,对一个精选软件包集合进行测试。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分