钩子使用教程

## 钩子是什么? 其实和回调是一个概念,当某个事情发生时就会调用你提供的方法,利用好SVN钩子可以大大的方便你的开发。 web开发人员,每次提交了代码都需要手动到服务器更新下代码才能看到效果。 今天我就教大家如何利用钩子自动化更新。 ## 怎么使用? 下面我将以 [SVNBucket](SVNBucket) 为例,如果你还没有 [SVNBucket](SVNBucket) 帐号,[点击注册](点击注册) ![1.png](https://cos.easydoc.net/46901064/files/lcx6vjsn.png) 如上图,点击添加钩子,我们需要填入 链接、token、触发条件 > **链接**:就好比我们的回调方法,在你提交代码后就会自动调用这个链接,你收到调用后就可以执行代码更新了。 **token**:是一个可选的参数,在调用链接时会带上这个参数,可以用来检查调用是否来自SVNBucket。这里可以随意填写一个自己想要的参数就行了 **触发条件**:触发条件我们选择提交后,这样代码提交之后就会调用链接。 那么我们的链接填写什么呢?你需要自己写一个http服务,用来接收调用。 ## 编写更新脚本 下面我以Python代码为例(PHP版本看文章最后),写一个简单的http服务来接收调用 ```python # -*- coding:utf8 -*- import os # 你需要安装 flask:pip install flask from flask import Flask, request app = Flask(__name__) @app.route('/onCommit', methods=['POST']) def onCommit(): # 参数有: # event: 事件名字,有 start-commit(提交前), post-commit(提交后) # token: 校验字符串,你在配置钩子那里填写的值 # projectId: 项目ID # projectName: 项目名字 # rev: 版本号( post-commit 事件才有值) # txnName:事务名,例如:44-23 # log:提交描述内容, # user:提交者用户名 # changedDirs: 本次提交涉及哪些目录更新,多个用冒号拼接,例如:"trunk/src:trunk/static"( post-commit 事件才有值), # 高级技巧:利用好 log、user、changedDirs 参数可以做选择性的更新,比如判断 log 中包含 “update” 才进行服务器更新; # 判断更新了某个目录中的文件才更新; param = request.form # 打印收到的参数 keys = param.keys() for key in keys: print('%s=%s' % (key, param.get(key, ''))) # 校验token,检查是不是自己在 SVNBucket 上配置的,防止恶意请求 if param.get('token', '') != 'YourToken': print('token校验不对,忽略') return 'invalid request' # 提交成功后,进行服务器代码更新、重启服务器等操作 if param.get('event') == 'post-commit': # 任何提交都更新 # 调用shell脚本进行svn update output = os.popen('./up_and_restart.sh') print(output.read()) ## 高级用法:当log中包含udpate才更新 # if 'update' in param.get('log', ''): # output = os.popen('./up_and_restart.sh') # print output.read() ## 高级用法:/trunk/src 目录变动了才更新 # if 'trunk/src' in param.get('changedDirs', ''): # output = os.popen('./up_and_restart.sh') # print output.read() # 这个响应内容会在钩子记录那里显示 return 'ok' elif param.get('event') == 'start-commit': # 如果是 start-commit 事件,必须返回 ok 才能提交,否则禁止提交并且会把返回的内容显示在 SVN 客户端。 # 可以用来判断 log 是否符合规范,然后决定是否允许提交。 # if len(param.get('log')) == 0: # return '必须填写提交日志' return 'ok' # 测试钩子时事件名是 test elif param.get('event') == 'test': return 'test ok' if __name__ == '__main__': app.run(host='0.0.0.0', port=8080) ``` 这里我们用 python 的 flask 框架搭建了一个简单的 http 服务来处理代码更新。根据这个可以自己实现一个其他语言的版本 在收到请求后我们就执行了一个shell脚本,这个shell脚本就是调用svn update去更新我们的代码了。 `up_and_restart.sh`脚本内容类似以下内容(根据你的业务需求写) ``` sh svn update /path/to/your/code/dir service restart xxxx ``` 假设你的服务器IP是`119.29.35.39`,http 服务的端口是8080,接口为 /afterCommit,那么我们就应该配置上面的链接地址为:![2.png](https://cos.easydoc.net/46901064/files/lcx6w4fq.png) 配置好了后,我们可以点击测试按钮进行测试,这样就会手动的触发一次链接请求,并且在下面区域显示调用记录、是否成功 ![3.png](https://cos.easydoc.net/46901064/files/lcx6wjhh.png) 上面讲解的是提交后钩子的经典应用(更新代码) 提交前钩子最经典的应用是判断是否有填写描述内容,我们可以限制不填写提交描述就不给提交,SVNBucket 已经为你做好了这个功能,只需要在设置页面开启下就可以了。 ![4.jpg](https://cos.easydoc.net/46901064/files/lcx6x83r.jpg) 最后再提供一个PHP版本的供参考: ```php <?php header("Content-Type: text/html; charset=utf-8"); header("Cache-Control:no-cache,must-revalidate"); // 参数有: // event: 事件名字,有 start-commit(提交前), post-commit(提交后) // token: 校验字符串,你在配置钩子那里填写的值 // projectId: 项目ID // projectName: 项目名字 // rev: 版本号( post-commit 事件才有值) // txnName:事务名,例如:44-23 // log:提交描述内容, // user:提交者用户名 // changedDirs: 本次提交涉及哪些目录更新,多个用冒号拼接,例如:"trunk/src:trunk/static"( post-commit 事件才有值), // 高级技巧:利用好 log、user、changedDirs 参数可以做选择性的更新,比如判断 log 中包含 “update” 才进行服务器更新; // 判断更新了某个目录中的文件才更新; if($_POST['token'] === '你填写的Token值') { $username = '你的SVN用户名'; $password = '你的SVN密码'; $target_dir = '/data/www'; exec("svn up --username $username --password $password --no-auth-cache $target_dir 2>&1", $output, $outresult); print_r("\noutput:$output, result:$outresult"); if ($outresult ===0 ) { echo '更新成功!'; //echo print_r($output); return 'ok'; } else { echo '更新失败!'; echo print_r($output); return 'failed'; } } else { echo '数据校验失败,无效更新!'; return 'failed'; } ```