RT-Thread中一共有五個(gè)Github Action(rt-thread/.github/workflow)
分別是:
-
RT-Thread BSP build check(.github/workflows/action.yml)
-
ToolsCI(.github/workflows/action_tools.yml)
-
AutoTestCI(.github/workflows/action_utest.yml)
-
Check File Format and License(.github/workflows/file_check.yml)
-
Static code analysis(.github/workflows/static_code_analysis.yml)
下面分別講解這五個(gè)Github Action。
RT-Thread BSP build check總的來說,這個(gè)Action會(huì)通過matrix嘗試編譯多個(gè)BSP,并記錄編譯成功和失敗的信息。執(zhí)行腳本中的每個(gè)BSP編譯步驟都在日志中創(chuàng)建了一個(gè)分組,以便在編譯成功或失敗時(shí)可以更好地顯示和記錄相關(guān)信息。
matrix列表中每個(gè)元素有三個(gè)屬性,分別是
-
RTT_BSP:這組BSP的名字,后續(xù)輸出日志時(shí)會(huì)用到
-
RTT_TOOL_CHAIN:編譯這組BSP使用的工具鏈
-
SUB_RTT_BSP:各個(gè)BSP的目錄
RT-Thread BSP build check的第一步:
-
首先先安裝gcc和menuconfig依賴的包
-
調(diào)用tools目錄下的menuconfig的touch_env
-
這個(gè)函數(shù)主要是創(chuàng)建一系列后續(xù)會(huì)使用到的文件夾,并且拉取遠(yuǎn)程的packages
-
以及修改Kconfig
-
設(shè)置一些RT-Thread自己的環(huán)境遍歷,供后續(xù)使用
1name:InstallTools
2shell:bash
3run:|
4sudoapt-getupdate
5sudoapt-get-qqinstallgcc-multiliblibncurses5libncurses5-devlibncursesw5-devscons
6sudopython-mpipinstall--upgradepip-qq
7pipinstallrequests-qq
8gitconfig--globalhttp.postBuffer524288000
9python-c"importtools.menuconfig;tools.menuconfig.touch_env()"
10echo"RTT_ROOT=${{github.workspace}}">>$GITHUB_ENV
11echo"RTT_CC=gcc">>$GITHUB_ENV
RT-Thread BSP build check的第二步:
-
會(huì)根據(jù)matrix.legs.RTT_TOOL_CHAIN判斷需要安裝什么工具鏈
RT-Thread BSP build check的第三步:
第三步是這次BSP編譯測(cè)試的核心
-
首先會(huì)遍歷所有的SUB_RTT_BSP
-
根據(jù)scons命令執(zhí)行的成功與否(||前一個(gè)命令執(zhí)行失敗、&&前一個(gè)命令執(zhí)行成功)來判斷執(zhí)行成功還是失敗的邏輯
-
輸出的時(shí)候會(huì)在GitHub Actions日志中創(chuàng)建一個(gè)分組,用于顯示BSP編譯的信息
-
計(jì)算總共花費(fèi)的時(shí)間,輸出BSP編譯成功或者失敗的信息,輸出至$GITHUB_STEP_SUMMARY
1name:BspSconsCompile
2if:${{success()}}
3shell:bash
4env:
5RTT_BSP:${{matrix.legs.RTT_BSP}}
6RTT_TOOL_CHAIN:${{matrix.legs.RTT_TOOL_CHAIN}}
7SRTT_BSP:${{join(matrix.legs.SUB_RTT_BSP,',')}}
8run:|
9source~/.env/env.sh
10failed=0
11count=0
12forbspin$(echo$SRTT_BSP|tr',''
');do
13count=$((count+1))
14echo"::CompilingBSP:==$count===$bsp===="
15echobsp/$bsp
16pushdbsp/$bsp&&pkgs--update&&popd
17scons-Cbsp/$bsp-j$(nproc)--debug=time|teeoutput.log||
18{total_time=$(grep"Totalcommandexecutiontime"output.log|awk'{print$5}');
19failed=$((failed+1));echo"::";echo"::build$bspfailed";
20echo"-build$bspfailedin$total_timeseconds">>$GITHUB_STEP_SUMMARY;}&&
21{total_time=$(grep"Totalcommandexecutiontime"output.log|awk'{print$5}');
22echo"-build$bspsuccessin$total_timeseconds">>$GITHUB_STEP_SUMMARY;echo"::";}
23done
24exit$failed
ToolsCI
總的來說,ToolsCI這個(gè)Action比較簡單,會(huì)去嘗試Build一個(gè)BSP、生成其它工程文件等等,用來測(cè)試使用。
關(guān)于scons一些參數(shù)的使用可以參考:SCons (rt-thread.org)
1name:ToolsCI
2#Controlswhentheactionwillrun.Triggerstheworkflowonpushorpullrequest
3#eventsbutonlyforthemasterbranch
4on:
5#Runsat16:00UTC(BeiJing00:00)onthe1stofeverymonth
6schedule:
7-cron:'0161**'
8push:
9branches:
10-master
11paths-ignore:
12-documentation/**
13-'**/README.md'
14-'**/README_zh.md'
15-'**/*.c'
16-'**/*.h'
17-'**/*.cpp'
18pull_request:
19branches:
20-master
21paths-ignore:
22-documentation/**
23-'**/README.md'
24-'**/README_zh.md'
25-'**/*.c'
26-'**/*.h'
27-'**/*.cpp'
28permissions:
29contents:read#tofetchcode(actions/checkout)
30jobs:
31test:
32runs-on:ubuntu-latest
33name:Tools
34strategy:
35fail-fast:false
36env:
37TEST_BSP_ROOT:bsp/stm32/stm32f407-atk-explorer
38steps:
39-uses:actions/checkout@v3
40-name:InstallTools
41shell:bash
42run:|
43sudoapt-getupdate
44sudoapt-get-yqqinstallscons
45-name:InstallArmToolChains
46if:${{success()}}
47shell:bash
48run:|
49wget-qhttps://github.com/RT-Thread/toolchains-ci/releases/download/v1.3/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
50sudotarxjfgcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2-C/opt
51/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc--version
52echo"RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin">>$GITHUB_ENV
53-name:BuildTools
54run:|
55scons--pyconfig-silent-C$TEST_BSP_ROOT
56scons-j$(nproc)-C$TEST_BSP_ROOT
57-name:ProjectgenerateTools
58if:${{success()}}
59run:|
60echo"Testtogenerateeclipseproject"
61scons--target=eclipse-s-C$TEST_BSP_ROOT
62echo"Testtogeneratecmakeproject"
63scons--target=cmake-s-C$TEST_BSP_ROOT
64echo"Testtogeneratemakefileproject"
65scons--target=makefile-s-C$TEST_BSP_ROOT
66-name:ProjectdistTools
67if:${{success()}}
68run:|
69echo"Testtodistproject"
70scons--dist-C$TEST_BSP_ROOT
71scons--dist-ide-C$TEST_BSP_ROOT
72ls$TEST_BSP_ROOT
73ls$TEST_BSP_ROOT/dist
74scons-C$TEST_BSP_ROOT/dist/project
75scons-C$TEST_BSP_ROOT/rt-studio-project
AutoTestCI
總的來說,這個(gè)Action的主要目標(biāo)是根據(jù)matrix中的不同參數(shù)組合,安裝必要的工具鏈、構(gòu)建和測(cè)試代碼。具體的步驟包括檢出代碼、安裝所需工具、設(shè)置環(huán)境變量、構(gòu)建代碼,然后在qemu中運(yùn)行測(cè)試并輸出日志。根據(jù)參數(shù)的不同,這個(gè)工作流可以自動(dòng)處理多個(gè)平臺(tái)和架構(gòu)的測(cè)試。
matrix列表中每個(gè)元素有五個(gè)屬性,分別是
-
UTEST:這組BSP的名字,后續(xù)輸出日志時(shí)會(huì)用到
-
RTT_BSP:測(cè)試使用的BSP
-
QEMU_ARCH:QEMU使用的平臺(tái)架構(gòu)
-
QEMU_MACHINE:選擇QEMU的板級(jí)支持包
-
CONFIG_FILE:RT-Thread條件編譯使用的CONFIG
-
SD_FILE:使用的sd.bin
-
RUN:是否啟動(dòng)
AutoTestCI的第一步:
安裝必要的工具:scons、qemu、git
AutoTestCI的第二步:
根據(jù)matrix的屬性選擇安裝相應(yīng)的編譯工具鏈
比如要測(cè)試arm架構(gòu)和rtsmart/arm時(shí),我們就選擇安裝arm-linux-musleabi_for_x86_64-pc-linux-g工具鏈
1name:InstallArmMuslToolChains
2if:${{matrix.legs.QEMU_ARCH=='arm'&&matrix.legs.UTEST=='rtsmart/arm'&&success()}}
3shell:bash
4run:|
5wget-qhttps://github.com/RT-Thread/toolchains-ci/releases/download/v1.7/arm-linux-musleabi_for_x86_64-pc-linux-g
6sudotarxjfarm-linux-musleabi_for_x86_64-pc-linux-gnu_stable.tar.bz2-C/opt
7/opt/arm-linux-musleabi_for_x86_64-pc-linux-gnu/bin/arm-linux-musleabi-gcc--version
8echo"RTT_EXEC_PATH=/opt/arm-linux-musleabi_for_x86_64-pc-linux-gnu/bin">>$GITHUB_ENV
9echo"RTT_CC_PREFIX=arm-linux-musleabi-">>$GITHUB_ENV
AutoTestCI的第三步:
第三步主要完成$TEST_BSP_ROOT下BSP的編譯,以供后續(xù)在qemu上使用
1name:BuildBSP
2run:|
3echoCONFIG_RT_USING_UTESTCASES=y>>$TEST_BSP_ROOT/.config
4catexamples/utest/configs/$TEST_CONFIG_FILE>>$TEST_BSP_ROOT/.config
5scons--pyconfig-silent-C$TEST_BSP_ROOT
6scons-j$(nproc)--strict-C$TEST_BSP_ROOT
AutoTestCI的第四步:
第四步也是最重要的一步,開始測(cè)試相關(guān)用例
1name:StartrunTest
2if:${{matrix.legs.RUN=='yes'&&success()}}
3run:|
4gitclonehttps://github.com/armink/UtestRunner.git
5pushd$TEST_BSP_ROOT
6ddif=/dev/zeroof=sd.binbs=1024count=65536
7popd
8pushdUtestRunner
9if[$TEST_SD_FILE!="None"];then
10python3qemu_runner.py--system$TEST_QEMU_ARCH--machine$TEST_QEMU_MACHINE--elf../$TEST_BSP_ROOT/rtthread
11else
12python3qemu_runner.py--system$TEST_QEMU_ARCH--machine$TEST_QEMU_MACHINE--elf../$TEST_BSP_ROOT/rtthread
13fi
14catrtt_console.log
15popd
-
拉取RT-Thread自動(dòng)化測(cè)試機(jī)器人
-
制作sd.bin
-
使用需要測(cè)試的BSP啟動(dòng)qemu
-
最后輸出相關(guān)日志
這個(gè)Action主要是用來檢查文件的格式化和版權(quán)信息的,主要工作都由tools/ci/file_check.py完成,在此之前主要先檢出當(dāng)前倉庫的代碼和安裝Python腳本依賴的包。
1name:CheckFileFormatandLicense
2on:[pull_request]
3jobs:
4scancode_job:
5runs-on:ubuntu-latest
6name:Scancodeformatandlicense
7steps:
8-uses:actions/checkout@v3
9-name:SetupPython
10uses:actions/setup-python@v3
11with:
12python-version:3.8
13-name:CheckFormatandLicense
14shell:bash
15run:|
16pipinstallclickchardetPyYaml
17pythontools/ci/file_check.pycheck'https://github.com/RT-Thread/rt-thread''master'
file_check.py
我們可以先忽略使用的click命令行庫,或者也可以從命名和使用方式猜測(cè)出它們的功能。
因?yàn)檫@個(gè)文件比較簡單,所以我們可以猜測(cè)函數(shù)的入口就是check()。主函數(shù)里的邏輯是十分簡單的,可以看到通過checkout.get_new_file()獲得了一個(gè)文件列表,然后傳遞給了FormatCheck和LicenseCheck,它們又分別調(diào)用了自身的check函數(shù),最后根據(jù)它們返回值判斷是否檢查出錯(cuò)誤。
1defcheck(check_license,repo,branch):
2"""
3checkfileslicenseandformat.
4"""
5init_logger()
6#getmodifiedfileslist
7checkout=CheckOut(repo,branch)
8file_list=checkout.get_new_file()
9iffile_listisNone:
10logging.error("checkoutfilesfail")
11sys.exit(1)
12#checkmodifiedfilesformat
13format_check=FormatCheck(file_list)
14format_check_result=format_check.check()
15license_check_result=True
16ifcheck_license:
17license_check=LicenseCheck(file_list)
18license_check_result=license_check.check()
19ifnotformat_check_resultornotlicense_check_result:
20logging.error("fileformatcheckorlicensecheckfail.")
21sys.exit(1)
22logging.info("checksuccess.")
23sys.exit(0)
checkout.get_new_file()獲得的文件列表是需要檢查的文件列表,而FormatCheck和LicenseCheck執(zhí)行各自的檢查邏輯。
首先是get_new_file,具體的邏輯也比較簡單:
1. 通過git命令獲得新增和修改的文件列表
2. 然后遍歷這個(gè)文件列表
3. 遍歷這個(gè)文件列表中的文件路徑的每一層目錄,看是否存在.ignore_format.yml文件
4. 然后根據(jù).ignore_format.yml的屬性來判斷當(dāng)前文件是否需要被檢查
而FormatCheck主要完成的工作是:
1. 搜索所有.c和.h文件
2. 然后檢查行首、行尾以及tab
而LicenseCheck的邏輯也比較簡單,主要就是判斷當(dāng)前的Copyright的年份是否正確。
1if'Copyright'infile[1]and'SPDX-License-Identifier:Apache-2.0'infile[3]:
2try:
3license_year=re.search(r'2006-d{4}',file[1]).group()
4true_year='2006-{}'.format(current_year)
5iflicense_year!=true_year:
6logging.warning("[{0}]:licenseyear:{}isnottrue:{},pleaseupdate.".fo
7else:
8logging.info("[{0}]:licensechecksuccess.".format(file_path))
9exceptExceptionase:
10logging.error(e)
11else:
12logging.error("[{0}]:licensecheckfail.".format(file_path))
13check_result=False
Static code analysis
這個(gè)Action和Check File Format and License是很類似的,主要流程都是相同的。
最重要的就是利用cppcheck完成靜態(tài)代碼檢查的功能:
1. 從文件列表中再一次過濾出C/C++相關(guān)文件2. 然后使用cppcheck逐個(gè)檢查文件列表,并且捕獲標(biāo)準(zhǔn)錯(cuò)誤流
1classCPPCheck:
2def__init__(self,file_list):
3self.file_list=file_list
4defcheck(self):
5file_list_filtered=[fileforfileinself.file_listiffile.endswith(('.c','.cpp','.cc','.cxx'))]
6logging.info("Starttostaticcodeanalysis.")
7check_result=True
8forfileinfile_list_filtered:
9result=subprocess.run(['cppcheck','--enable=warning','performance','portability','--inline-suppr','--error-exitcode=1','--force',file],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
10logging.info(result.stdout.decode())
11logging.info(result.stderr.decode())
12ifresult.stderr:
13check_result=False
14returncheck_result
15@click.group()
16@click.pass_context
17defcli(ctx):
18pass
19@cli.command()
20defcheck():
21"""
22staticcodeanalysis(cppcheck).
23"""
24format_ignore.init_logger()
25#getmodifiedfileslist
26checkout=format_ignore.CheckOut()
27file_list=checkout.get_new_file()
28iffile_listisNone:
29logging.error("checkoutfilesfail")
30sys.exit(1)
31#usecppcheck
32cpp_check=CPPCheck(file_list)
33cpp_check_result=cpp_check.check()
34ifnotcpp_check_result:
35logging.error("staticcodeanalysis(cppcheck)fail.")
36sys.exit(1)
37logging.info("checksuccess.")
38sys.exit(0)
39if__name__=='__main__':
40cli()
原文:https://club.rt-thread.org/ask/article/102cc126ad4dbfd8.html
———————End———————
RT-Thread線下入門培訓(xùn)
6月 - 鄭州、杭州、深圳
1.免費(fèi)2.動(dòng)手實(shí)驗(yàn)+理論3.主辦方免費(fèi)提供開發(fā)板4.自行攜帶電腦,及插線板用于筆記本電腦充電5.參與者需要有C語言、單片機(jī)(ARM Cortex-M核)基礎(chǔ),請(qǐng)?zhí)崆鞍惭b好RT-Thread Studio 開發(fā)環(huán)境
立即掃碼報(bào)名
報(bào)名鏈接
https://jinshuju.net/f/UYxS2k
巡回城市:青島、北京、西安、成都、武漢、鄭州、杭州、深圳、上海、南京
你可以添加微信:rtthread2020 為好友,注明:公司+姓名,拉進(jìn)RT-Thread官方微信交流群!
點(diǎn)擊閱讀原文,進(jìn)入RT-Thread 官網(wǎng)
原文標(biāo)題:RT-Thread中的Github Actions
文章出處:【微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
RT-Thread
+關(guān)注
關(guān)注
31文章
1285瀏覽量
40085
原文標(biāo)題:RT-Thread中的Github Actions
文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論