希望每次提交到分支上的代码自动提交到reviewboard,通过svn post-review hook脚本实现调用rbt工具发起code review。
python和svn绑定问题
运维同学在使用hook脚本时发现通过源码编译出来的python和svn无法关联使用,一方面是缺少python的svn库,另一方面是缺少相应动态库。
http://stackoverflow.com/questions/1448894/subversion-python-bindings-documentation 这里有介绍通过编译安装swig就可以获取python和svn关联的脚本及动态库。
依赖1.5.2版本apr库,但是svn服务器无法升级apr库问题
apr库由于影响范围较广,升级之后很多服务可能出现问题,后面就考虑将该脚本移出来,放到其他服务器,提供http服务让post-commit hook调用。
脚本提供branch review功能
如上提供的脚本中更多的是将当前revision提交上去会比较好用,但是当你有一个分支,提交多次修改和code review就比较麻烦。虽然reviewboard可以在多个diff之间再做比较,但是始终无法得到最初的版本和最新的版本的一个diff。
这里考虑先获取当前改动的branch,然后在脚本中提供获取整个branch diff的方法然后post到reviewboard,这样就对于想看整个分支改动的情况非常方便。
4. rbt post最新的到reviewboard时卡住,发现是reviewboard在读取diff时还要获取一些repository其他信息(暂时未跟进要啥信息),所以需要配置一个svn账号
找到reviewboard的python库路径,打开reviewboard/scmtools/svn/pysvn.py,找到_do_on_path方法,增加如下代码
def _do_on_path(self, cb, path, revision=HEAD):
# add
def login(*args):
#设置svn账号密码
return True, 'svn账号', 'svn密码', False
self.client.callback_get_login = login
#add end
if not path:
raise FileNotFoundError(path, revision)
第四条发现是repository里面配置的svn账号密码失效了,在admin页面可以更改。
5.邮件发送时报错SMTPDataError: (550, ‘5.7.1 Client does not have permissions to send as this sender’)
这个问题可能是因为配置的发送邮件的账号没有设置指定sender权限,没具体去了解过。修改reviewboard代码reviewboard/notifications/email.py的563行
# from_email = get_email_address_for_user(user)
from_email = settings.DEFAULT_FROM_EMAIL
下面开始介绍目前正在使用的模式。
1、SVN服务器上部署svn库,对应repository下的hook脚本会调用python svn hook服务
2、python svn hook服务提供http服务,接收参数repos和rev,执行rbt请求将diff发送到reviewboard
3、reviewboard服务器部署reviewboard
如果没冲突的情况都放一台机器上也OK。
在svn仓库服务器上找到svn目录下的hooks目录,创建或修改post-commit文件,
并且添加可执行权限,post-commit内容见https://github.com/zhouyuzhy/reviewboard-hook/blob/master/hook/post-commit
参考:https://github.com/reviewboard/reviewboard/blob/master/contrib/tools/svn-hook-postcommit-review
在该脚本基础上修改如下几点,详细内容见https://github.com/zhouyuzhy/reviewboard-hook
1、修改不依赖svn库,使用svn log解析得到author和提交msg
command = SVN_PATH + "svn log -r " + str(rev) + " -l 1 -v " + REPOSITORY +" --username " + SVN_USER + " --password "+ SVN_PASSWORD + " --non-interactive"
logData = execute(command,
env = {'LANG': 'en_US.UTF-8'}, shell=True)
for i in range(len(logDataLines)-2-logLineCount,len(logDataLines)-2):
log+=logDataLines[i]+"\n"
author = logDataLines[1].split(' ')[2]
2、增加branch判断,只针对branches下面的分支提交review
firstChangePath = logDataLines[3].split(' ')[4]
if firstChangePath.find('branch') < 0:
print 'no branch found in ',rev
return
branchSlashIndex = firstChangePath.find('/',firstChangePath.find('branches')+9,len(firstChangePath)-1)
branch = firstChangePath[0:branchSlashIndex]
3、增加branch review语法,可以将该分支下的所有修改一次提交
branchlog = ''
m = re.search(r'(?:branch)(?: )?review', log, re.M | re.I)
if m:
command = SVN_PATH + "svn log --stop-on-copy " + REPOSITORY + branch +" --username " + SVN_USER + " --password "+ SVN_PASSWORD + " --non-interactive"
if DEBUG:
print command
branchlog = execute(command,
env = {'LANG': 'en_US.UTF-8'}, shell=True)
branchloglines = branchlog.splitlines()
for branchlogline in reversed(branchloglines):
if len(branchlogline.split('|')) == 4:
prevrev = int(branchlogline.split(' ')[0][1:])
break
4、修改update review语法,支持在一个语句中做publish和update review
m = re.search(r'update(?: )?(?:branch)?(?: )?review:([0-9]+)', log, re.M | re.I)
if m:
reviewid = '--review-request-id=' + m.group(1)
else:
reviewid = ''
5、使用python django提供http服务封装hook脚本,django自己不太会用,就用最简单的模型封装了一层
1、在commit message中添加publish review则会自动添加新的review并且publish
2、在commit message中添加draft review则会自动添加新的review而不是publish状态
3、在commit message中添加publish/draft update review:1则会自动更新编号为1的review而不重新提交
4、在commit message中添加after revision:1则从1到当前revision全部提交review,可选,默认为一个revision
5、在commit message中添加publish branch review或者publish update branch review:1就会把整个分支的diff提交