rt-thread中一共有五個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)
下面分別講解這五個Github Action。
RT-Thread BSP build check
總的來說,這個Action會通過matrix嘗試編譯多個BSP,并記錄編譯成功和失敗的信息。執(zhí)行腳本中的每個BSP編譯步驟都在日志中創(chuàng)建了一個分組,以便在編譯成功或失敗時可以更好地顯示和記錄相關信息。
matrix列表中每個元素有三個屬性,分別是
RTT_BSP:這組BSP的名字,后續(xù)輸出日志時會用到
RTT_TOOL_CHAIN:編譯這組BSP使用的工具鏈
SUB_RTT_BSP:各個BSP的目錄
RT-Thread BSP build check的第一步:
首先先安裝gcc和menuconfig依賴的包
調用tools目錄下的menuconfig的touch_env
這個函數(shù)主要是創(chuàng)建一系列后續(xù)會使用到的文件夾,并且拉取遠程的packages
以及修改Kconfig
設置一些RT-Thread自己的環(huán)境遍歷,供后續(xù)使用
name: Install Tools
shell: bash
run: |
sudo apt-get update
sudo apt-get -qq install gcc-multilib libncurses5 libncurses5-dev libncursesw5-dev scons
sudo python -m pip install --upgrade pip -qq
pip install requests -qq
git config --global http.postBuffer 524288000
python -c "import tools.menuconfig; tools.menuconfig.touch_env()"
echo "RTT_ROOT=**{{ github.workspace }}" >> **GITHUB_ENV
echo "RTT_CC=gcc" >> $GITHUB_ENV
RT-Thread BSP build check的第二步:
會根據(jù)matrix.legs.RTT_TOOL_CHAIN判斷需要安裝什么工具鏈
RT-Thread BSP build check的第三步:
第三步是這次BSP編譯測試的核心
首先會遍歷所有的SUB_RTT_BSP
根據(jù)scons命令執(zhí)行的成功與否(||前一個命令執(zhí)行失敗、&&前一個命令執(zhí)行成功)來判斷執(zhí)行成功還是失敗的邏輯
輸出的時候會在GitHub Actions日志中創(chuàng)建一個分組,用于顯示BSP編譯的信息
計算總共花費的時間,輸出BSP編譯成功或者失敗的信息,輸出至$GITHUB_STEP_SUMMARY
name: Bsp Scons Compile
if: ${{ success() }}
shell: bash
env:
RTT_BSP: ${{ matrix.legs.RTT_BSP }}
RTT_TOOL_CHAIN: ${{ matrix.legs.RTT_TOOL_CHAIN }}
SRTT_BSP: ${{ join(matrix.legs.SUB_RTT_BSP, ',') }}
run: |
source ~/.env/env.sh
failed=0
count=0
for bsp in **(echo **SRTT_BSP | tr ',' '\\n'); do
count=$((count+1))
echo "::group::Compiling BSP: ==**count=== **bsp ===="
echo bsp/$bsp
pushd bsp/$bsp && pkgs --update && popd
scons -C bsp/bsp -j(nproc) --debug=time | tee output.log ||
{ total_time=$(grep "Total command execution time" output.log | awk '{print $5}');
failed=**((failed+1)) ; echo "::endgroup::" ; echo "::error::build **bsp failed" ;
echo "- build **bsp failed in **total_time seconds " >> $GITHUB_STEP_SUMMARY ; } &&
{ total_time=$(grep "Total command execution time" output.log | awk '{print $5}');
echo "- build **bsp success in **total_time seconds " >> $GITHUB_STEP_SUMMARY ; echo "::endgroup::" ; }
done
exit $failed
ToolsCI
總的來說,ToolsCI這個Action比較簡單,會去嘗試Build一個BSP、生成其它工程文件等等,用來測試使用。
關于scons一些參數(shù)的使用可以參考:SCons (rt-thread.org)
name: ToolsCI
Controls when the action will run. Triggers the workflow on push or pull request
events but only for the master branch
on:
Runs at 16:00 UTC (BeiJing 00:00) on the 1st of every month
schedule:
-
cron: '0 16 1 * *'
push:
branches:
-
master
paths-ignore:
-
documentation/**
-
'**/README.md'
-
'**/README_zh.md'
-
'**/*.c'
-
'**/*.h'
-
'**/*.cpp'
pull_request:
branches:
-
master
paths-ignore:
-
documentation/**
-
'**/README.md'
-
'**/README_zh.md'
-
'**/*.c'
-
'**/*.h'
-
'**/*.cpp'
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
test:
runs-on: ubuntu-latest
name: Tools
strategy:
fail-fast: false
env:
TEST_BSP_ROOT: bsp/stm32/stm32f407-atk-explorer
steps:
-
uses: actions/checkout@v3
-
name: Install Tools
shell: bash
run: |
sudo apt-get update
sudo apt-get -yqq install scons
-
name: Install Arm ToolChains
if: ${{ success() }}
shell: bash
run: |
wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.3/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt
/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version
echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin" >> $GITHUB_ENV
-
name: Build Tools
run: |
scons --pyconfig-silent -C $TEST_BSP_ROOT
scons -j**(nproc) -C **TEST_BSP_ROOT
-
name: Project generate Tools
if: ${{ success() }}
run: |
echo "Test to generate eclipse project"
scons --target=eclipse -s -C $TEST_BSP_ROOT
echo "Test to generate cmake project"
scons --target=cmake -s -C $TEST_BSP_ROOT
echo "Test to generate makefile project"
scons --target=makefile -s -C $TEST_BSP_ROOT
-
name: Project dist Tools
if: ${{ success() }}
run: |
echo "Test to dist project"
scons --dist -C $TEST_BSP_ROOT
scons --dist-ide -C $TEST_BSP_ROOT
ls $TEST_BSP_ROOT
ls $TEST_BSP_ROOT/dist
scons -C $TEST_BSP_ROOT/dist/project
scons -C $TEST_BSP_ROOT/rt-studio-project
AutoTestCI
總的來說,這個Action的主要目標是根據(jù)matrix中的不同參數(shù)組合,安裝必要的工具鏈、構建和測試代碼。具體的步驟包括檢出代碼、安裝所需工具、設置環(huán)境變量、構建代碼,然后在qemu中運行測試并輸出日志。根據(jù)參數(shù)的不同,這個工作流可以自動處理多個平臺和架構的測試。
matrix列表中每個元素有五個屬性,分別是
UTEST:這組BSP的名字,后續(xù)輸出日志時會用到
RTT_BSP:測試使用的BSP
QEMU_ARCH:QEMU使用的平臺架構
QEMU_MACHINE:選擇QEMU的板級支持包
CONFIG_FILE:RT-Thread條件編譯使用的CONFIG
SD_FILE:使用的sd.bin
RUN:是否啟動
AutoTestCI的第一步:
安裝必要的工具:scons、qemu、git
AutoTestCI的第二步:
根據(jù)matrix的屬性選擇安裝相應的編譯工具鏈
比如要測試arm架構和rtsmart/arm時,我們就選擇安裝arm-linux-musleabi_for_x86_64-pc-linux-g工具鏈
name: Install Arm Musl ToolChains
if: ${{ matrix.legs.QEMU_ARCH == 'arm' && matrix.legs.UTEST == 'rtsmart/arm' && success() }}
shell: bash
run: |
wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.7/arm-linux-musleabi_for_x86_64-pc-linux-g
sudo tar xjf arm-linux-musleabi_for_x86_64-pc-linux-gnu_stable.tar.bz2 -C /opt
/opt/arm-linux-musleabi_for_x86_64-pc-linux-gnu/bin/arm-linux-musleabi-gcc --version
echo "RTT_EXEC_PATH=/opt/arm-linux-musleabi_for_x86_64-pc-linux-gnu/bin" >> $GITHUB_ENV
echo "RTT_CC_PREFIX=arm-linux-musleabi-" >> $GITHUB_ENV
AutoTestCI的第三步:
第三步主要完成$TEST_BSP_ROOT下BSP的編譯,以供后續(xù)在qemu上使用
name: Build BSP
run: |
echo CONFIG_RT_USING_UTESTCASES=y >> $TEST_BSP_ROOT/.config
cat examples/utest/configs/**TEST_CONFIG_FILE >> **TEST_BSP_ROOT/.config
scons --pyconfig-silent -C $TEST_BSP_ROOT
scons -j**(nproc) --strict -C **TEST_BSP_ROOT
AutoTestCI的第四步:
第四步也是最重要的一步,開始測試相關用例
拉取RT-Thread自動化測試機器人
制作sd.bin
使用需要測試的BSP啟動qemu
最后輸出相關日志
name: Start run Test
if: ${{matrix.legs.RUN == 'yes' && success() }}
run: |
git clone https://github.com/armink/UtestRunner.git
pushd $TEST_BSP_ROOT
dd if=/dev/zero of=sd.bin bs=1024 count=65536
popd
pushd UtestRunner
if [ $TEST_SD_FILE != "None" ]; then
python3 qemu_runner.py --system **TEST_QEMU_ARCH --machine **TEST_QEMU_MACHINE --elf ../$TEST_BSP_ROOT/rtthread
else
python3 qemu_runner.py --system **TEST_QEMU_ARCH --machine **TEST_QEMU_MACHINE --elf ../$TEST_BSP_ROOT/rtthread
fi
cat rtt_console.log
popd
Check File Format and License
這個Action主要是用來檢查文件的格式化和版權信息的,主要工作都由tools/ci/file_check.py完成,在此之前主要先檢出當前倉庫的代碼和安裝Python腳本依賴的包。
name: Check File Format and License
on: [pull_request]
jobs:
scancode_job:
runs-on: ubuntu-latest
name: Scan code format and license
steps:
-
uses: actions/checkout@v3
-
name: Set up Python
uses: actions/setup-python@v3
with:
python-version: 3.8
-
name: Check Format and License
shell: bash
run: |
pip install click chardet PyYaml
python tools/ci/file_check.py check 'https://github.com/RT-Thread/rt-thread' 'master'
file_check.py
我們可以先忽略使用的click命令行庫,或者也可以從命名和使用方式猜測出它們的功能。
因為這個文件比較簡單,所以我們可以猜測函數(shù)的入口就是check()。主函數(shù)里的邏輯是十分簡單的,可以看到通過checkout.get_new_file()獲得了一個文件列表,然后傳遞給了FormatCheck和LicenseCheck,它們又分別調用了自身的check函數(shù),最后根據(jù)它們返回值判斷是否檢查出錯誤。
def check(check_license, repo, branch):
"""
check files license and format.
"""
init_logger()
get modified files list
checkout = CheckOut(repo, branch)
file_list = checkout.get_new_file()
if file_list is None:
logging.error("checkout files fail")
sys.exit(1)
check modified files format
format_check = FormatCheck(file_list)
format_check_result = format_check.check()
license_check_result = True
if check_license:
license_check = LicenseCheck(file_list)
license_check_result = license_check.check()
if not format_check_result or not license_check_result:
logging.error("file format check or license check fail.")
sys.exit(1)
logging.info("check success.")
sys.exit(0)
checkout.get_new_file()獲得的文件列表是需要檢查的文件列表,而FormatCheck和LicenseCheck執(zhí)行各自的檢查邏輯。
首先是get_new_file,具體的邏輯也比較簡單:
通過git命令獲得新增和修改的文件列表
然后遍歷這個文件列表
遍歷這個文件列表中的文件路徑的每一層目錄,看是否存在.ignore_format.yml文件
然后根據(jù).ignore_format.yml的屬性來判斷當前文件是否需要被檢查
而FormatCheck主要完成的工作是:
搜索所有.c和.h文件
然后檢查行首、行尾以及tab
而LicenseCheck的邏輯也比較簡單,主要就是判斷當前的Copyright的年份是否正確。
if 'Copyright' in file[1] and 'SPDX-License-Identifier: Apache-2.0' in file[3]:
try:
license_year = re.search(r'2006-\\d{4}', file[1]).group()
true_year = '2006-{}'.format(current_year)
if license_year != true_year:
logging.warning("[{0}]: license year: {} is not true: {}, please update.".fo
else:
logging.info("[{0}]: license check success.".format(file_path))
except Exception as e:
logging.error(e)
else:
logging.error("[{0}]: license check fail.".format(file_path))
check_result = False
Static code analysis
這個Action和Check File Format and License是很類似的,主要流程都是相同的。
最重要的就是利用cppcheck完成靜態(tài)代碼檢查的功能:
從文件列表中再一次過濾出C/C++相關文件
然后使用cppcheck逐個檢查文件列表,并且捕獲標準錯誤流
class CPPCheck:
def init (self, file_list):
self.file_list = file_list
def check(self):
file_list_filtered = [file for file in self.file_list if file.endswith(('.c', '.cpp', '.cc', '.cxx'))]
logging.info("Start to static code analysis.")
check_result = True
for file in file_list_filtered:
result = subprocess.run(['cppcheck', '--enable=warning', 'performance', 'portability', '--inline-suppr', '--error-exitcode=1', '--force', file], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
logging.info(result.stdout.decode())
logging.info(result.stderr.decode())
if result.stderr:
check_result = False
return check_result
@click.group()
@click.pass_context
def cli(ctx):
pass
@cli.command()
def check():
"""
static code analysis(cppcheck).
"""
format_ignore.init_logger()
get modified files list
checkout = format_ignore.CheckOut()
file_list = checkout.get_new_file()
if file_list is None:
logging.error("checkout files fail")
sys.exit(1)
use cppcheck
cpp_check = CPPCheck(file_list)
cpp_check_result = cpp_check.check()
if not cpp_check_result:
logging.error("static code analysis(cppcheck) fail.")
sys.exit(1)
logging.info("check success.")
sys.exit(0)
if name == ' main ':
cli()
-
BSP
+關注
關注
1文章
86瀏覽量
26092 -
python
+關注
關注
55文章
4774瀏覽量
84386 -
RT-Thread
+關注
關注
31文章
1265瀏覽量
39853 -
qemu
+關注
關注
0文章
57瀏覽量
5324
發(fā)布評論請先 登錄
相關推薦
評論