python实现代码审查自动回复消息


Posted in Python onFebruary 01, 2021

在一个规范化的研发流程中,一般遵循如下流程:

  1. 开发阶段:研发功能或者修复bug,在本地自测。
  2. 代码审核阶段:提交代码,并请求团队内人员做code review。
  3. 测试环境测试阶段:部署到测试环境并请求测试。
  4. 发布线上待测阶段:测试环境通过测试发布到线上进行测试。
  5. 验收完成任务:线上验证成功,关闭这个任务。

实际上这只是一种最理想化的过程,因为我们默认每次状态流转都是顺利的,开发没有毛病,测试一次就通过,现实中的研发

流程的情况更复杂,如图所示。

python实现代码审查自动回复消息

整个过程一气呵成,环环相扣。而其中可以被自动化的正好是第二步:请求他人进行code review的时候的反馈消息。

根据实践的经验,比较好的内容格式如下(包含Markdown格式,因为跟踪任务的系统支持这种格式):

**Changes has been committed to feature/xxx-xxx**

- https://git.xxx.com/xxxx/ddaf18f9be4613c31363d4c92b8bafc3sdfdsf

**Details**
Remove invalid logic for admin pannel

由于每次走到Code Review的步骤的时候都需要写类似的回复在任务管理系统中,所以考虑使用Python脚本去自动生成这段文字,简化工作。

根据样例回复进行分析,需要获取项目的分支名(任务目标分支),项目最后一次提交的commit id去组装第二行的git commit的链接,然后Details的内容可以从git log中的提交信息里面提取。

第一步:获取分支名称。

为了简化过程,默认项目的当前分支就是我们需要的分支,那么问题简化为获取当前分支名。可以利用git的相关命令实现,如下:

git branch | sed -n '/\* /s///p'

第二步:获取commit id。

而获取commit id也非常简单,只需要如下命令:

git rev-parse HEAD

第三步:获取提交信息。

还需要获取提交信息,利用git log的命令进行过滤也能得到:

git log --pretty=format:"%s" -1

git log --pretty=format命令很强大,除了获得提交信息外,还有如下参数可以使用。

%H 提交对象(commit)的完整哈希字串 
%h 提交对象的简短哈希字串 
%T 树对象(tree)的完整哈希字串 
%t 树对象的简短哈希字串 
%P 父对象(parent)的完整哈希字串 
%p 父对象的简短哈希字串 
%an 作者(author)的名字 
%ae 作者的电子邮件地址 
%ad 作者修订日期(可以用 -date= 选项定制格式) 
%ar 作者修订日期,按多久以前的方式显示 
%cn 提交者(committer)的名字 
%ce 提交者的电子邮件地址 
%cd 提交日期 
%cr 提交日期,按多久以前的方式显示 
%s 提交说明

所以第二步也可以使用git log命令实现,如下所示:

git log --pretty=format:"%H" -1

当然还需要在后面加一点人性化的感谢的话,毕竟是麻烦其他人来对你代码进行审核,说一些感谢的话吧,这里我就用一个list来装一些感谢的话,然后随机获取一段贴到最后。
如果是以面向过程的方式去编写,那么可以编写如下代码:

#coding=utf-8
#!/usr/bin/python

import os, subprocess
import random

# use subprocess to get the current branch name from output
def get_branch_name(cd_path):
 os.chdir(cd_path)
 status, branch_name = subprocess.getstatusoutput("git branch | sed -n '/\* /s///p'")
 # print(output)
 # exit(0)
 return branch_name

def get_latest_git_log(cd_path):
 """
 docstring
 """
 os.chdir(cd_path)
 status, log_info = subprocess.getstatusoutput("git log --pretty=format:\"%s\" -1")
 return log_info

def get_latest_commit_id(cd_path):
 os.chdir(cd_path)
 status, commit_id = subprocess.getstatusoutput("git rev-parse HEAD")
 return commit_id

def get_reviewer_by_random(reviewers):
 return random.choice(reviewers)

def get_thanks_words_by_random(thanks_words):
 return random.choice(thanks_words)

def create_comment(reviewers, branch_name, log_info, commit_id, thanks_words):
 print(get_reviewer_by_random(reviewers))
 print("*Changes made has been committed to " + branch_name + "*")
 print("- https://git.xxxxx.com/someproject/subname/-/commit/" + commit_id)
 print("*Details*")
 print("-" + log_info)
 print(get_thanks_words_by_random(thanks_words))

branch_name = get_branch_name('/Users/tony/www/autoWork')
log_info = get_latest_git_log('/Users/tony/www/autoWork')
commit_id = get_latest_commit_id('/Users/tony/www/autoWork')

reviewers = [
 '[~Harry]',
 '[~Tom]'
]

random_thanks_words = [
 'Review it please, thanks.',
 'Actually, I am glad to see you have time to review it, thanks a lot.',
 'Please check it if you have free time, thanks.',
 'Check it please.'
 'Waiting for your code review, thank you.'
]

create_comment(reviewers, branch_name, log_info, commit_id, random_thanks_words)

由于Python脚本和项目没有放在一个目录下面,所以每次在执行git相关命令之前都需要先cd到目标项目目录下。而分别执行git命令的时候使用subprocess.getstatusoutput()来执行,方便获取标准化输出的结果。这里之所以不使用os.system来执行命令,是因为os.system运行命令的返回值里面包括两个部分,第一部分是命令的结果输出,第二部分是结果是否成功的标识符。

例如执行os.system("git branch | sed -n '/* /s///p'")会返回如下内容:

feature/ST-247
0

第一行是我们获取到的分支名,第二行是成功的标识符,0表示命令没有任何问题。

所以我考虑使用subprocess.getstatusoutput来运行命令,这个函数会分别返回结果标识和输出,方便得到想要的执行输出结果。

虽然代码还可以进一步优化,但是已经能满足我的需求了,运行这个脚本就能得到如下的输出结果:

[~Harry]
*Changes made has been committed to feature/ST-247*
- https://git.xxxxx.com/someproject/subname/-/commit/d21033057677e6d49d9cea07c64c49e35529545dx
*Details*
- Remove some invalid logic
Please check it if you have free time, thanks.

如果改写成面向对象的方式会更好,调用更简单,传递参数也更少,采用Python3语法编写的代码如下所示:

#coding=utf-8
#!/usr/bin/python
import os
import subprocess
import random

class CommitComment:
 def __init__(self, project_path: str, reviewers: list, thanks_words: list):
  self.project_path = project_path
  self.reviewers = reviewers
  self.thanks_words = thanks_words
 # use subprocess to get the current branch name from output
 def get_branch_name(self) -> str:
  os.chdir(self.project_path)
  status, branch_name = subprocess.getstatusoutput("git branch | sed -n '/\* /s///p'")
  return branch_name
 # use subprocess to get the latest commit message from git log 
 def get_latest_git_log(self) -> str:
  os.chdir(self.project_path)
  status, log_info = subprocess.getstatusoutput("git log --pretty=format:\"%s\" -1")
  return log_info

 # use subprocess to get the latest commit id from git log
 def get_latest_commit_id(self) -> str:
  os.chdir(self.project_path)
  status, commit_id = subprocess.getstatusoutput("git rev-parse HEAD")
  return commit_id

 def get_reviewer_by_random(self) -> str:
  return random.choice(self.reviewers)

 def get_thanks_words_by_random(self) -> str:
  return random.choice(self.thanks_words)

 def create_comment(self):
  print(self.get_reviewer_by_random())
  print("*Changes has been committed to " + self.get_branch_name() + "*")
  print("- https://git.xxxx.com/MyProject/ProjectName/-/commit/" + self.get_latest_commit_id())
  print("*Details*")
  print("-" + self.get_latest_git_log())
  print(self.get_thanks_words_by_random())


thanks_words = [
  'Review it please, thanks.',
  'Actually, I am glad to see you have time to review it, thanks a lot.',
  'Please check it if you have free time, thanks.',
  'Check it please.'
  'Waiting for your code review, thank you.'
 ]
reviewers = [
'[~Harry]',
'[~Tom]'
]

comment = CommitComment('/Users/tony/www/autoWork', reviewers, thanks_words)

comment.create_comment() # will print out the complete comment

thanks_words列表可以在增加多一点,这样随机获取之下重复的概率会更少。当然最后一段也可以自己每次diy,毕竟感谢要发自内心的最好。

这种简化工作流的脚本本质是减少重复性劳动,特别是一天完成了很多个任务的时候。但是反思本身是无法被简化的,不做工作的奴隶,而是工作的主人。
抛砖引玉,希望对自己和未来的自己也是一个还原镜像。

Todo:

1.可以每天定时执行这个脚本去生成回复消息。
2.通过脚本传参来动态选择需要被处理的项目目录。在这个案例代码中是hard code的,默认是选择了autoWork这个项目。
3.还可以考虑接入语料库(thanks words),这样感谢的话永不重复,还能学点新单词。:)

以上就是python实现代码审查回复消息生成的详细内容,更多关于python 回复消息生成的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python SQLite3数据库操作类分享
Jun 10 Python
python实现生命游戏的示例代码(Game of Life)
Jan 24 Python
Tensorflow卷积神经网络实例进阶
May 24 Python
对pytorch网络层结构的数组化详解
Dec 08 Python
Python删除n行后的其他行方法
Jan 28 Python
Python使用Pickle模块进行数据保存和读取的讲解
Apr 09 Python
Python递归函数 二分查找算法实现解析
Aug 12 Python
PYTHON EVAL的用法及注意事项解析
Sep 06 Python
Python 实现使用空值进行赋值 None
Mar 12 Python
Python动态导入模块:__import__、importlib、动态导入的使用场景实例分析
Mar 30 Python
jupyter notebook 添加kernel permission denied的操作
Apr 21 Python
如何基于Python爬取隐秘的角落评论
Jul 02 Python
anaconda安装pytorch1.7.1和torchvision0.8.2的方法(亲测可用)
Feb 01 #Python
python 列表推导和生成器表达式的使用
Feb 01 #Python
matplotlib部件之矩形选区(RectangleSelector)的实现
Feb 01 #Python
深入理解Python变量的数据类型和存储
Feb 01 #Python
selenium3.0+python之环境搭建的方法步骤
Feb 01 #Python
Pytorch 图像变换函数集合小结
Feb 01 #Python
Scrapy+Selenium自动获取cookie爬取网易云音乐个人喜爱歌单
Feb 01 #Python
You might like
php 结果集的分页实现代码
2009/03/10 PHP
PHP面向对象概念
2011/11/06 PHP
thinkPHP5分页功能实现方法分析
2017/10/25 PHP
Laravel利用gulp如何构建前端资源详解
2018/06/03 PHP
php依赖注入知识点详解
2019/09/23 PHP
Aster vs Newbee BO5 第一场2.19
2021/03/10 DOTA
基于jquery的一个浮动框(扩展性比较好 )
2010/08/27 Javascript
jquery入门—访问DOM对象方法
2013/01/07 Javascript
调用HttpHanlder的几种返回方式小结
2013/12/20 Javascript
Javascript中引用示例介绍
2014/02/21 Javascript
nodejs开发环境配置与使用
2014/11/17 NodeJs
node.js中的url.parse方法使用说明
2014/12/10 Javascript
Node.js Streams文件读写操作详解
2016/07/04 Javascript
js前端导出Excel的方法
2017/11/01 Javascript
vue.js引入外部CSS样式和外部JS文件的方法
2019/01/06 Javascript
async/await让异步操作同步执行的方法详解
2019/11/01 Javascript
使用Python脚本对Linux服务器进行监控的教程
2015/04/02 Python
使用Python进行二进制文件读写的简单方法(推荐)
2016/09/12 Python
深入浅出分析Python装饰器用法
2017/07/28 Python
对python中的高效迭代器函数详解
2018/10/18 Python
利用python和ffmpeg 批量将其他图片转换为.yuv格式的方法
2019/01/08 Python
python3 enum模块的应用实例详解
2019/08/12 Python
利用python实现逐步回归
2020/02/24 Python
Pytorch转tflite方式
2020/05/25 Python
学习python需要有编程基础吗
2020/06/02 Python
服装设计师职业生涯规划范文
2014/02/28 职场文书
产品推广策划方案
2014/05/10 职场文书
施工安全汇报材料
2014/08/17 职场文书
争先创优心得体会
2014/09/12 职场文书
高等学院职业生涯规划书范文
2014/09/16 职场文书
共产党员批评与自我批评
2014/10/15 职场文书
学习党史心得体会2016
2016/01/23 职场文书
分享几个JavaScript运算符的使用技巧
2021/04/24 Javascript
8个JS的reduce使用实例和reduce操作方式
2021/10/05 Javascript
详解Go语言中配置文件使用与日志配置
2022/06/01 Golang
ubuntu端向日葵键盘输入卡顿问题及解决
2022/12/24 Servers