zoukankan      html  css  js  c++  java
  • 钉钉开发系列(十三)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% 
    提交版本:%REV% 
    作者:%AUTHOR%
    提交备注:%MESSAGE%
    修改目录:%CHANGEDDIRS% " 
    "C:DingDingRobotNotify.exe" XXX %CONTENT%
    其中XXX是钉钉机器人的access_token。

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

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

    转载请注明出处。




  • 相关阅读:
    让c像python一样可以在命令行写代码并且编译
    动态链接库找不到 : error while loading shared libraries: libgsl.so.0: cannot open shared object file: No such file or directory
    为什么shell中变量赋值不能有空格
    在hyper安装openwrt
    linux扩展lvm磁盘
    docker的基本使用
    tmux与vim主题不一致
    linux centos cli all proxy
    couchDB入门
    tmux复制到windows剪贴板/粘贴板的坑
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604885.html
Copyright © 2011-2022 走看看