版本管理之SVN实践教程:基础篇(10):svn的hook机制

这里写图片描述

svn的hook机制,跟其他很多类似的工具一样,hook机制的本身就是在某个具体的时机所触发的内容,类似于事件驱动的回调。

场景说明

举个简单的例子,我们使用svn commit的时候如果希望对日志的信息进行判断,如果日志中没有包含指定格式的Ticket号时,提示相关的错误信息,不允许提交。这样的场景,就是hook机制起作用的最为常见的情形之一。这篇文章中会用最简单的方式来演示这个机制的设定和使用方式。

svn的hook

svn的hook模版

在创建的svn的仓库中,目前默认包含了如下9种hook的版本

  • start-commit
  • pre-commit
  • post-commit
  • pre-revprop-change
  • post-revprop-change
  • pre-lock
  • post-lock
  • pre-unlock
  • post-unlock

hook说明

这9种相关的hook所触发的时机相关的信息如下

类型触发时机常见用途备注
start-commit提交事务生成之前一般可根据用户名对提交进行权限控制,一般多用于对svn版本功能check的检查参数个数为2,svn 1.5为3个
pre-commit事务已生成,但是尚未提交可可根据提交的内容或者comment进行控制,比如提交日志不能为空-
post-commit提交之后数据进行备份,以及修改提示的mail操作,或者驱动自动构建-
pre-revprop-change属性变更前,尚未变化可以进行属性变更权限的控制-
post-revprop-change属性变更前进行版本属性的备份以及mail通知操作等-
pre-lock加锁之前可进行是否能加锁的控制-
post-lock加锁之后可进行mail通知,使开发成员了解此文件已经加锁往往有时结合特定流程,比如有提交冻结期的结束,可结合这个属性进行使用
pre-unlock解锁前可进行是否能解锁的控制-
post-unlock解锁之后可进行mail通知,使开发成员了解此文件已经解锁往往有时结合特定流程,比如有提交冻结期的结束,可结合这个属性进行使用

hook参数

当前版本的hook的相关参数信息如下所示:

类型参数1参数2参数3参数4参数5
start-commit代码库路径用户名---
pre-commit代码库路径事务名---
post-commit代码库路径版本号事务名--
pre-revprop-change代码库路径版本号用户名属性名ACTION
post-revprop-change代码库路径版本号用户名属性名ACTION
pre-lock代码库路径路径用户名CommentSTEAL(1
post-lock代码库路径用户名---
pre-unlock代码库路径路径用户名TOKENBREAK-UNLOCK(1
post-unlock代码库路径用户名---

起效方式

缺省创建的库中的9个文件均以tmpl结尾,而这样是不起作用的,在Unix/Linux下,删除tmpl的后缀才能起作用,而windows则需要将.tmpl改成.bat。
修改之后立即起效,无需重新启动svn服务。

注意事项

因为安全的考量,在钩子函数中是无法使用环境变量的。Unix/Linux下基础的PATH也是环境变量,因为这个的缘故,导致可执行文件必须使用全路径进行引用,这就是你在代码里面没有看到svnlook而是/usr/bin/svnlook的根本原因。

实例

场景说明:
在版本管理中,我们建议在提交的日志中结合Ticket番号,如果在svn commit的时候提交日志的信息为空或者不包含Ticket号的信息,则无法提交到代码库。日志格式一般为:# xxxx: 日志信息

事前准备

事前准备

准备镜像

可以使用前面文章中Dockerfile生成的alpine的svn的lts版本的镜像,也可以直接使用使用easypack打好的镜像。

[root@liumiaocn svn]# docker pull liumiaocn/svn:1.10.0
1.10.0: Pulling from liumiaocn/svn
8e3ba11ec2a2: Already exists 
4de3c6aa9a6d: Pull complete 
f64b6f3c550b: Pull complete 
Digest: sha256:c55a104e8f1cc10545b9e51aac4a40271540d0b13ab78c5c0e6ca40c0203f4f7
Status: Downloaded newer image for liumiaocn/svn:1.10.0
[root@liumiaocn svn]# docker images |grep liumiaocn/svn
liumiaocn/svn              1.10.0              15e2c7c993e6        Less than a second ago   12.4 MB
[root@liumiaocn svn]#

启动svn服务

[root@liumiaocn ~]# mkdir -p /usr/local/svn/hooktest
[root@liumiaocn ~]# cd /usr/local/svn/hooktest
[root@liumiaocn hooktest]# docker run -p 3690:3690 -v `pwd`/data:/data/svn --name svn -d liumiaocn/svn:1.10.0
cf3b9343e7245b5c0592b28f7386051cc5e403e962b97040078bd3e27e6f052b
[root@liumiaocn hooktest]# 

确认服务

[root@liumiaocn hooktest]# docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                    NAMES
cf3b9343e724        liumiaocn/svn:1.10.0   "/usr/bin/svnserve..."   23 seconds ago      Up 23 seconds       0.0.0.0:3690->3690/tcp   svn
[root@liumiaocn hooktest]#

仓库准备

进入svn容器中,创建演示用仓库:hook-repo

[root@liumiaocn hooktest]# docker exec -it svn sh
/data/svn # svnadmin create hook-repo
/data/svn # ls
hook-repo
/data/svn #

设定

svn服务的配置设定文件

对仓库的svn服务的配置设定文件,都做如下设定

设定项说明缺省值备考
anon-access匿名用户访问权限read有read/write/none三种取值
auth-access认证用户访问权限write有read/write/none三种取值
password-db用户名与密码信息passwd多仓库可使用相对路径
authz-db用户与组权限设定authz多仓库可使用相对路径
/data/svn/hook-repo/conf # vi svn*
/data/svn/hook-repo/conf # egrep 'anon-access|auth-access|password-db|authz-db' svnserve.conf |grep -v '#'
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
/data/svn/hook-repo/conf # 

用户信息:passwd

设定svn的用户信息passwd如下

[users]
devuser1  = devuser1pw
devuser2  = devuser2pw
testuser1 = testuser1pw

权限设定:authz

设定svn的权限信息authz如下

[groups]
group_dev = devuser1,devuser2

[hook-repo:/]
@group_dev = rw
testuser1  = r

重启svn镜像

[root@liumiaocn hooktest]# docker restart svn
svn
[root@liumiaocn hooktest]#

hook设定前确认

checkout出来hook-repo仓库

[root@platform ~]# svn co svn://192.168.163.129:3690/hook-repo --username devuser1 --password devuser1pw

-----------------------------------------------------------------------
ATTENTION!  Your password for authentication realm:

   <svn://192.168.163.129:3690> fd46fd0b-476c-4183-8596-4638ae6aff62

can only be stored to disk unencrypted!  You are advised to configure
your system so that Subversion can store passwords encrypted, if
possible.  See the documentation for details.

You can avoid future appearances of this warning by setting the value
of the 'store-plaintext-passwords' option to either 'yes' or 'no' in
'/root/.subversion/servers'.
-----------------------------------------------------------------------
Store password unencrypted (yes/no)? yes
Checked out revision 0.
[root@platform ~]# cd hook-repo/
[root@platform hook-repo]#

确认comment信息为空,是可以提交成功的。

[root@platform hook-repo]# touch C1; svn add C1; 
A         C1
[root@platform hook-repo]# svn commit -m ""
Adding         C1
Transmitting file data .
Committed revision 1.
[root@platform hook-repo]# svn log
------------------------------------------------------------------------
[root@platform hook-repo]# svn update
Updating '.':
At revision 1.
[root@platform hook-repo]# svn log
------------------------------------------------------------------------
r1 | devuser1 | 2018-08-26 18:32:55 -0400 (Sun, 26 Aug 2018) | 1 line


------------------------------------------------------------------------
[root@platform hook-repo]# 

comment的信息也没有过多其他的限制

[root@platform hook-repo]# ls
C1
[root@platform hook-repo]# touch C2; svn add C2; svn commit -m "add C2"
A         C2
Adding         C2
Transmitting file data .
Committed revision 2.
[root@platform hook-repo]# svn log
------------------------------------------------------------------------
r1 | devuser1 | 2018-08-26 18:32:55 -0400 (Sun, 26 Aug 2018) | 1 line


------------------------------------------------------------------------
[root@platform hook-repo]# svn update 
Updating '.':
At revision 2.
[root@platform hook-repo]# svn log
------------------------------------------------------------------------
r2 | devuser1 | 2018-08-26 18:35:05 -0400 (Sun, 26 Aug 2018) | 1 line

add C2
------------------------------------------------------------------------
r1 | devuser1 | 2018-08-26 18:32:55 -0400 (Sun, 26 Aug 2018) | 1 line


------------------------------------------------------------------------
[root@platform hook-repo]#

hook设定

在服务器侧的hooks目录下创建pre-commit文件,也可以由现有的文件进行修改。具体内容如下:

[root@liumiaocn hooks]# docker exec -it svn sh
/data/svn # cd hook-repo/hooks
/data/svn/hook-repo/hooks # vi pre-commit
/data/svn/hook-repo/hooks # cat pre-commit
#!/bin/sh

REPOS="$1"
TXN="$2"

LOG_INFO=`svnlook log -t "$TXN" "$REPOS"`

# check empty comment
if [ _"$LOG_INFO" = _"" ]; then
  echo "" 1>&2
  echo "   ## LOG CHECK : NG: [$LOG_INFO] does not match the rules." 1>&2
  exit 1
fi

# check log format with # :
TICKET_NO=`echo "$LOG_INFO" |sed s/#//g |awk -F : '{print $1}'`
COMMENT_MSG=`echo "$LOG_INFO" |sed s/#//g |awk -F : '{print $2}'`
if [ _"$TICKET_NO" = _"" -o _"$COMMENT_MSG" = _"" ]; then
    echo "" 1>&2
    echo "   ## LOG CHECK : NG: [$LOG_INFO] does not match the rules." 1>&2
    echo "      Sample : # BUG1002: feature F1001 bug fixed" 1>&2
    exit 1
fi

# pre-commit check passed.
exit 0
/data/svn/hook-repo/hooks # chmod 755 pre-commit
/data/svn/hook-repo/hooks #

执行确认

空COMMENT提交

[root@platform hook-repo]# touch C3; svn add C3;
A         C3
[root@platform hook-repo]# 

提交确认: 可以看到pre-commit的空comment的判断逻辑起作用了

[root@platform hook-repo]# svn commit -m ""
Adding         C3
Transmitting file data .svn: E165001: Commit failed (details follow):
svn: E165001: Commit blocked by pre-commit hook (exit code 1) with output:

   ## LOG CHECK : NG: [] does not match the rules.

[root@platform hook-repo]#

格式不符合的情况

[root@platform hook-repo]# svn commit -m "add file"
Adding         C3
Transmitting file data .svn: E165001: Commit failed (details follow):
svn: E165001: Commit blocked by pre-commit hook (exit code 1) with output:

   ## LOG CHECK : NG: [add file] does not match the rules.
      Sample : # BUG1002: feature F1001 bug fixed

[root@platform hook-repo]#

常见问题

hook文件缺少执行权限

hook文件会被调用,比如pre-commit文件,都需要具有x的执行权限,不然你很有可能在svn commit的时候得到如下的错误提示

Transmitting file data .svn: E165001: Commit failed (details follow):
svn: E165001: Commit blocked by pre-commit hook (exit code 255) with no output.

无法打印输出信息

echo输出的信息是标准输出,需要将其转化为标准错误,才能看到提示信息,这就是1>&2出现的原因(B-SHELL的输出转换方式)。

淼叔 CSDN认证博客专家 神经网络 TensorFlow NLP
资深架构师,PMP、OCP、CSM、HPE University讲师,EXIN DevOps Professional与DevOps Master认证讲师,曾担任HPE GD China DevOps & Agile Leader,帮助企业级客户提供DevOps咨询培训以及实施指导。熟悉通信和金融领域,有超过十年金融外汇行业的架构设计、开发、维护经验,在十几年的IT从业生涯中拥有了软件开发设计领域接近全生命周期的经验和知识积累,著有企业级DevOps技术与工具实战。
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页