如何快速向RT-Thread提一个PR:以CI为例
本帖最后由 sunsili 于 2024-1-6 18:07 编辑如何快速向RT-Thread提一个PR:以CI为例
PR方法(Git操作)
01Fork
首先将官方仓库 fork 到我们自己的账号下,点击一下 fork 按钮,按照提示操作即可。回到自己的仓库中,将仓库clone到本地。git clone https://github.com/yourusername/rt-thread.git如果是较早之前fork的仓库,可以先和上游的仓库同步一下:1. 先在仓库页面Update branch2. 在本地仓库git fetch & git merge
02Commit & Push
一般来说,一个issue或者PR对应一个新的分支,所以需要创建一个分支git checkout -b <branchname>
更改相应的代码,然后提交代码git add .
git commit -m "message"
git push origin test-branch
03Pull Request
在仓库首页按操作提起一个PR
04Rollback
如果提交有误或者需要修改,可以进行回滚,然后重新pushgit reset HEAD^(回退到上一个版本)
05CI
查看CI结果,根据结果对代码进行修改
功能的修改和增加:以CI(issue 7458)为例
01理解issue
需要根据ignore_format 过滤掉不需要扫描的文件夹 · Issue #7458 · RT-Thread/rt-thread (github.com)https://github.com/RT-Thread/rt-thread/issues/7458
对问题本身的理解十分重要,issue里可能会有其他人对这个需求的或者问题详细讨论和思路的提供,所以仔细查看issue非常重要。根据这个issue的描述,主要是添加忽略一些文件和目录进行静态检查的功能。具体需求是:1. 添加对.ignore_format.yml配置文件检查
2. 如果新更新的文件在dir_path属性的目录下或者在file_path属性中3. 对这个文件就不启用静态检查并且这个issue中也提供了一种思路:1. 遍历一下ignore_format.yml文件找到所有需要忽略的文件夹,搞个大数组,然后过滤2. 参考一下https://github.com/RT-Thread/rt-thread/blob/master/tools/file_check.py
02代码定位
代码定位是对功能的修改和增加的第一步,对于Bug fix来说,代码定位可能比较困难,但是对于功能的修改和增加来说,是比较简单的。首先可以看出来这个issue的工作主要是CI这块,那么我们需要先了解github的CI工具:Github Action。最好的文档肯定就是GitHub Actions文档 - GitHub 文档。我们不需要全部了解之后再动手,只要了解一些基本概念之后就可以先动手。根据文档的描述,我们可以了解到github workflow使用yml来描述,并且放在了.github/workflow目录下,所以第一步可以定位到.github/workflow下的static_code_analysis.yml。在这个目录我们可以看到static_code_analysis.yml是直接在yaml中用shell编写工作流程,而还有其它文件如file_check.yml使用调用其它Python脚本来完成工作流程。所以基本可以确定我们需要修改或者增加的地方就在.github/workflow和tools/ci下。
03代码阅读
在这里,我们参考file_check.yml的实现。所以需要先理解file_check.yml的整体实现。file_check.yml主要先使用shell按照了Pyhon脚本中必须使用的库然后直接调用Python脚本,我们直接跳入这个被调用的脚本查看。代码阅读个人比较喜欢也觉得比较快速的方式是:先了解代码的某一部分(需要控制精度)的大致结构和功能,不关注其具体实现,之后再深入理解具体实现。在这个过程中有需要去猜测别人是如何写的代码,并且在一步步阅读代码的过程当中验证和纠正自己的想法。我们来看file_check.py。我们可以先忽略使用的click命令行库,或者也可以从命名和使用方式猜测出它们的功能。因为这个文件比较简单,所以我们可以猜测函数的入口就是check()。主函数里的逻辑是十分简单的,可以看到通过checkout.get_new_file()获得了一个文件列表,然后传递给了FormatCheck和LicenseCheck,它们又分别调用了自身的check函数,最后根据它们返回值判断是否检查出错误。所以我们可以猜测checkout.get_new_file()获得的文件列表是需要检查的文件列表,而FormatCheck和LicenseCheck执行各自的检查逻辑,我们可以不用关注。而get_new_file的就需要深入代码看具体实现,具体的逻辑也比较简单。1. 通过git命令获得新增和修改的文件列表2. 然后遍历这个文件列表3. 遍历这个文件列表中的文件路径的每一层目录,看是否存在.ignore_format.yml文件4. 然后根据.ignore_format.yml的属性来判断当前文件是否需要被检查所以我们实现的重点就是对需要检查的代码进行静态代码检查。
04功能增加
首先,因为获得需要检查的文件列表这个功能是可能会被多次利用,可以先提取出来作为一个独立功能,并且可以做一些优化(在获得新增和修改的文件列表时的写法可以优化)。其次,最重要的就是利用cppcheck完成静态代码检查的功能:1. 从文件列表中再一次过滤出C/C++相关文件2. 然后使用cppcheck逐个检查文件列表,并且捕获标准错误流class CPPCheck:
def __init__(self, file_list):
self.file_list = file_list
def check(self):
file_list_filtered =
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()
05功能测试
完成代码的修改之后最重要的就是通过测试,最基本也是最简单的测试就是功能测试。所以我们可以给这次的修改安排三个测试:修改cppcheck会出现错误的文件:case 1:不将文件加入.ignore_format.yml,CI报错case 2:将文件加入.ignore_format.yml的file_path,CI不报错case 3:将文件加入.ignore_format.yml的dir_path,CI不报错
PR心得
这次PR的提交有以下两个小心得。
01仔细沟通
第一点,也是最重要的一点就是和主动社区的前辈进行交流,对issue的问题和需求进行讨论。在这个PR被merge之前我就完成了其余两版,但是因为缺乏沟通,不是很适合当前的RT-Thread。
02Github Action 本地测试
在修改CI部分时,每次都需要推送到远端才能执行相关的action,这样比较麻烦。可以使用nektos/act: Run your GitHub Actions locally
页:
[1]