在《钉钉开发系列-机器人》中已经介绍了钉钉机器人的创建与通知,那SVN提交时是否也可以自动发出通知呢?我们来思考一下原理,钉钉机器人的通知,本质上就是调用一个URL,然后POST数据,如果SVN中能够调起该URL并POST,那么理论上就应可以的。现在我们来开始实践。
我们用的是VisualSVN-Server作为SVN的服务器,SVN客户端用TortoiseSVN。在VisualSVN-Server是免费的,新版的要求在WIN2008以上安装,所以只要在虚拟机中装WIN2008,然后装VisualSVN-Server就可以了。安装时一路默认即可。安装后创建一个DDRobotTest的库。
在Users文件夹下右键,然后创建用户,比如test.
VisualSVN-Server有钩子来实现客制化的方式,所以我们利用钩子hook来发起钉钉机器人的通知请求。在DDRobotTest上右键,如下图
我们要用到的是Pre-commit hook和Post-commit hook,Pre-commit hook是提交代码前的钩子,Post-commit hook是提交完成后的钩子。为了能够在通知时更规范,我们有必要对提交代码作一些要求,比如必须输入日志内容,为此我们先在Pre-commit hook中实现一个控制提交代码日志的钩子。代码如下
@echo off :: :: Stops commits that have empty log messages. :: @echo off setlocal rem Subversion sends through the path to the repository and transaction id set REPOS=%1 set TXN=%2 rem check for an empty log message svnlook log %REPOS% -t %TXN% | findstr "..." > nul if %errorlevel% gtr 0 (goto err) else exit 0 :err echo 1>&2 echo 抱歉,由于您没有正确填写Log或者Log字数过少(必须大于3),系统拒绝提交! 1>&2 echo Log格式: 新增/修改/删除: 提交内容 1>&2 echo 请详细描述提交内容,然后再提交. -- 谢谢! 1>&2 exit 1将上面的代码直接贴到Pre-commit hook中就可以了。其中findstr中的"..."是控制日志内容的文字个数,几个点就是几个字。
测试一下
如果输入的日志符合长度,则提交成功。
SVN日志已经规范,接下来就是在Post-commit hook发出通知。由于Post-commit hook中没有办法直接发起https请求,但是可以调用相关的应用程序,所以如果我们能够写一个控制台程序供其调用,然后将通知的内容传入,那通知也就应该可以成功发出了。下面是控制台的代码
class Program { static void Main(string[] args) { if (args == null || args.Length < 2) { Console.WriteLine("请输入机器人票据和通知内容"); return; } var token = args[0]; var msg = args[1]; var result = Notify(token, msg); Console.WriteLine(result); } #region Notify public static string Notify(string token, string msg) { var robotUrl = $"https://oapi.dingtalk.com/robot/send?access_token={token}"; String textMsg = "{ "msgtype": "text", "text": {"content": "" + msg + ""}}"; string s = Post(robotUrl, textMsg, null); return s; } #endregion #region Post /// <summary> /// 以Post方式提交命令 /// </summary> /// <param name="apiurl">请求的URL</param> /// <param name="jsonString">请求的json参数</param> /// <param name="headers">请求头的key-value字典</param> private static String Post(string apiurl, string jsonString, Dictionary<String, String> headers = null) { WebRequest request = WebRequest.Create(@apiurl); request.Method = "POST"; request.ContentType = "application/json"; if (headers != null) { foreach (var keyValue in headers) { if (keyValue.Key == "Content-Type") { request.ContentType = keyValue.Value; continue; } request.Headers.Add(keyValue.Key, keyValue.Value); } } if (String.IsNullOrEmpty(jsonString)) { request.ContentLength = 0; } else { byte[] bs = Encoding.UTF8.GetBytes(jsonString); request.ContentLength = bs.Length; Stream newStream = request.GetRequestStream(); newStream.Write(bs, 0, bs.Length); newStream.Close(); } WebResponse response = request.GetResponse(); Stream stream = response.GetResponseStream(); Encoding encode = Encoding.UTF8; StreamReader reader = new StreamReader(stream, encode); string resultJson = reader.ReadToEnd(); return resultJson; } #endregion }编译生成控制台程序 DingDingRobotNotify.exe,我们可以对该程序用cmd测试一下。
现在我们将DingDingRobotNotify.exe放到VisualSVN-Server所在的服务器上,比如放到C盘,然后在Post-commit hook中调用,hook的代码如下
@echo off set REPOS=%1 set REV=%2 set tttt=%date:~0,10% %time:~0,8% for /f "tokens=1,2 delims=:" %%a in ('svnlook author -r %REV% %REPOS%') do ( if not defined AUTHOR set AUTHOR=%%a ) for /f "tokens=1,2 delims=:" %%a in ('svnlook dirs-changed %REPOS%') do ( if not defined CHANGEDDIRS set CHANGEDDIRS=%%a ) for /f "tokens=1,2 delims=:" %%a in ('svnlook log -r %REV% %REPOS%') do ( if not defined MESSAGE set MESSAGE=%%a ) set CONTENT="提交时间:%tttt% 提交版本:%REV% 作者:%AUTHOR% 提交备注:%MESSAGE% 修改目录:%CHANGEDDIRS% " "C:DingDingRobotNotify.exe" XXX %CONTENT%其中XXX是钉钉机器人的access_token。
现在我们要SVN的客户端提交修改,如下图
欢迎打描左侧二维码打赏。
转载请注明出处。