钉钉开发系列(十三)SVN机器人通知

在《钉钉开发系列-机器人》中已经介绍了钉钉机器人的创建与通知,那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% \n提交版本:%REV% \n作者:%AUTHOR%\n提交备注:%MESSAGE%\n修改目录:%CHANGEDDIRS% " 
"C:\DingDingRobotNotify.exe" XXX %CONTENT%
其中XXX是钉钉机器人的access_token。

现在我们要SVN的客户端提交修改,如下图

欢迎打描左侧二维码打赏。

转载请注明出处。




posted @ 2017-06-14 17:19  _学而时习之  阅读(602)  评论(4编辑  收藏  举报