yellfly 2008-7-18 17:09
将CVS代码提交信息记录到Bugzilla系统中的方法
在软件开发过程,我们可能会想要知道一个bug的解决到底改动了哪些代码。这也是变更控制中的一个重要的方面:配置变更记录。我在公司的配置管理实践过程中,利用cvs的钩子脚本技术将bugzilla和cvs集成起来,实现了将CVS代码提交信息记录到Bugzilla系统中的功能。
1.在cvs仓库根目录的CVSROOT子目录中有一个loginfo文件,该文件用于在cvs提交成功后调用自己编写的钩子脚本。在loginfo中按如下格式添加一行:
^源代码对应的cvs模块目录 钩子脚本 %{sVv}
其中,%{sVv}是传给钩子脚本的参数,其含义如下:
s = file name
V = old version number (pre-checkin)
v = new version number (post-checkin)
在我的机器上的一个配置实例如下:
^starsms-3.x/develop/4.implement /var/sscript/log2bugzilla %{sVv}
2.建立钩子脚本log2bugzilla,代码如下:
#!/bin/sh
username=${USER}@startimes.com.cn
bugzilla_tools_url=http://192.168.18.18/tools/bugzilla
loginfo=`cat`
chginfo=`/var/sscript/cvs_echo_files $1`
comment=`echo "$chginfo" && echo "" && echo "CVS日志信息:" && echo "$loginfo"`
bugids=`echo "$loginfo" | grep bug:`
echo $bugids | awk -f /var/sscript/bugdone.awk
while read bugid
do
/usr/local/bin/python /var/sscript/bugzilla-commit -l ${bugzilla_tools_url}/CommentBugResult.php -u $username -p bvt -b $bugid -c "$co
mment"
done < /tmp/bugdone.awk.output
3.在上面的代码中,调用了cvs_echo_files脚本。这个脚本的作用是解析cvs文件变更信息(文件名、原版本、新版本)。由于loginfo传给log2bugzilla的命令行参数%{sVv}是做为一个参数传入的(以空格分开),它实际上代表了三个参数,因此需要将它解析出来。我采用的办法是调用另外一个脚本cvs_echo_files进行处理。cvs_echo_files的代码如下:
echo "代码变更信息:"
if [ "$2" = "-" ] && [ "$3" = "New" ] && [ "$4" = "directory" ] ; then
echo " 添加了新目录: $1"
exit 0
fi
if [ "$1" != "" ] ; then
echo " 在 $1 目录中修改了以下文件: "
fi
shift
while test "$1" != ""
do
echo $1 | awk -F , '{system("echo " $1 ": " $2 "→" $3 "; ")}'
#echo -n "$1; "
shift
done
exit 0
[[i] 本帖最后由 yellfly 于 2008-7-18 17:54 编辑 [/i]]
yellfly 2008-7-18 17:45
4.为了将cvs提交信息与bug id关联起来,我们要求开发人员在提交代码时,必须输入提交信息,且提交信息的第一行必须按如下格式:
bug: <bugid1>,<bugid2>,...
如:bug: 1358,1429
cvs提交信息中的bug字串需要用unix下的awk命令解析。首先用grep命令取出bug id列表:bugids=`echo "$loginfo" | grep bug:`
然后,将bugids传给awk脚本进行处理:echo $bugids | awk -f /var/sscript/bugdone.awk
bugdone.awk脚本的内容如下:
BEGIN {
}
{
str=$0
str=substr(str,5)
count=split(str,bugs,",")
for(i=1;i<=count;i++) {
printf("%s\n", bugs[i]) > "/tmp/bugdone.awk.output"
}
}
END {
}
5.提交信息都准备好了,放在$comment中,bug id也取出来了,列在/tmp/bugdone.awk.output文件中,下一步需要针对每一个bug,向bugzilla中提交数据。为了能够向bugzilla中提交数据,还要准备一个提交bug的网页CommentBugResult.php(原来打算利用bugzilla页面提交,但不知页面参数,没有成功)。将CommentBugResult.php网页放到web服务器的文档目录下:
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$bug_id = $_POST['bug_id'];
$comment = $_POST['comment'];
if (!$username) {
header("Location:error.php?errcode=no_username&redirect_url=CommentBug.php");
exit;
}
if (!$password) {
header("Location:error.php?errcode=no_password&redirect_url=CommentBug.php");
exit;
}
if (!$bug_id) {
header("Location:error.php?errcode=no_bug_id&redirect_url=CommentBug.php");
exit;
}
if (!$comment) {
header("Location:error.php?errcode=no_comment&redirect_url=CommentBug.php");
exit;
}
function connectBugzillaDB()
{
//下面的$bugzilla_db_host, $bugzilla_db_username, $bugzilla_db_passwd, $bugzilla_db_name几个参数需要改为实际的数据库连接值
$db = mysql_connect($bugzilla_db_host, $bugzilla_db_username, $bugzilla_db_passwd);
if (!$db) {
return 0;
}
mysql_select_db($bugzilla_db_name, $db);
return $db;
}
function closeBugzillaDB($db)
{
mysql_close($db);
}
$db = connectBugzillaDB();
$sql = "select userid, cryptpassword from profiles";
$sql .= " where login_name='" . $username . "'";
$result = mysql_query($sql);
if ($row = mysql_fetch_array($result)) {
$cryptpasswd = $row['cryptpassword'];
}
if (!isset($cryptpasswd)) {
header("Location:error.php?errcode=password_error&redirect_url=CommentBug.php");
exit;
}
if ($password != "bvt") {
if (crypt($password, $cryptpasswd) != $cryptpasswd) {
header("Location:error.php?errcode=password_error&redirect_url=CommentBug.php");
exit;
}
}
?>
<body>
<h1>Bugzilla添加Bug注释结果</h1>
<hr/>
<?php
$sql2 = "select bug_id from bugs where bug_id=" . $bug_id;
$result2 = mysql_query($sql2);
$row2 = mysql_fetch_array($result2);
if ($row && $row2) {
$sql3 = "insert longdescs(bug_id,who,bug_when,work_time,thetext,isprivate) values(";
$sql3 .= $bug_id . "," . $row['userid'] . ",'" . date("Y-m-d H:i:s") . "','0:00','" . $comment . "',0)";
mysql_query($sql3);
echo "添加Bug注释成功!<br>";
echo "<input type=\"hidden\" name=\"result\" value=\"success\">";
}
else {
echo "添加Bug注释失败!<br>";
echo "<input type=\"hidden\" name=\"result\" value=\"failure\">";
}
closeBugzillaDB($db);
?>
</body>
</html>
[[i] 本帖最后由 yellfly 于 2008-7-18 18:04 编辑 [/i]]
yellfly 2008-7-18 17:50
6.最后,要实现向web服务器提交数据,还需要一个bugzilla提交脚本。我采用python语言编写了一个bugzilla-commit脚本(改自开源工具bugzilla-submit),代码如下:
#!/usr/bin/env python
import optparse,urllib,sys
def setup_parser():
parser = optparse.OptionParser(usage="usage: %prog [options] bugzilla-url")
parser.add_option('-l', '--url', dest='url',
help='Set the bug comment url.')
parser.add_option('-u', '--username', dest='username',
help='Set the user name.')
parser.add_option('-p', '--password', dest='password',
help='Set the login password.')
parser.add_option('-b', '--bugid', dest='bug_id',
help='Set the bug id.')
parser.add_option('-c', '--comment', dest='comment',
help='Set the additional comment.')
return parser
def process_options(options):
data = {}
for (key, value) in options.__dict__.items():
if key != 'read' and value != None:
data[key] = value
return data
def error(m):
sys.stderr.write("bugzilla-comment: %s\n" % m)
sys.stderr.flush()
sys.exit(1)
def check_result_POST(ret, data):
if ret.find("success") == -1:
error("bugzilla-comment: add comment to bug %s failure!" % data['bug_id'])
print "bugzilla-comment: add comment to bug %s success!" % data['bug_id']
if __name__ == "__main__":
parser = setup_parser()
(options, args) = parser.parse_args()
data = process_options(options)
url=data['url']
del data['url']
postdata=urllib.urlencode(data)
url=urllib.URLopener().open(url, postdata)
ret = url.read()
check_result_POST(ret, data)
sys.exit(0)
经过以上步骤,就实现了将CVS代码提交信息记录到Bugzilla系统中的功能。
[[i] 本帖最后由 yellfly 于 2008-7-18 17:57 编辑 [/i]]