• JIRA对接钉钉群机器人-实现任务的自定义格式指派通知


    一、前提

    Jira Software、钉钉群、RESTful服务、LDAP服务

    二、流程图

     

    三、对接步骤

    1、创建项目群,把相关人员拉入群

    2、钉钉群的智能群助手里添加自定义机器人

    3、设置机器人,安全设置里建议勾选IP地址段,将RESTful服务所在的机器IP填入

    4、注意创建完成后的Webhook地址,RESTful服务用这个地址发送通知消息,后面步骤要用上

    5、RESTful服务新增一个POST接口,这里可以自定义通知内容,部署到服务器

     1 @ApiOperation(value = "JIRA网络钩子")
     2 @PostMapping("/jiraWebHook")
     3 @ResponseBody
     4 public Result<Boolean> jiraWebHook(HttpServletRequest request) {
     5     BufferedReader br = null;
     6     String str, wholeStr = "";
     7     try {
     8         br = request.getReader();
     9 
    10         while ((str = br.readLine()) != null) {
    11             wholeStr += str;
    12         }
    13         log.info("jiraWebHook body: {}", wholeStr);
    14     } catch (Exception e) {
    15         log.error("jiraWebHook error", e);
    16     } finally {
    17         if (br != null) {
    18             try {
    19                 br.close();
    20             } catch (Exception e) {
    21             }
    22         }
    23     }
    24     return Result.success(JiraWebHookUtil.hook(JSONObject.parseObject(wholeStr, JiraPostData.class)));
    25 }
    View Code
      1 @Slf4j
      2 public class JiraWebHookUtil {
      3 
      4     private static final String DING_TALK_ROBOT_URL = "https://oapi.dingtalk.com/robot/send" +
      5             "?access_token=xxxxxx";
      6     private static final String JIRA_BASE_URL = "http://xxx.xxx.xxx.xxx:38080/browse/";
      7     private static RestTemplate restTemplate = new RestTemplate();
      8 
      9     public static boolean hook(JiraPostData postData){
     10         try {
     11             if(postData != null){
     12                 if(StringUtils.equals(postData.getWebhookEvent(), "jira:issue_updated")){
     13                     //更新事件
     14                     List<Item> items = postData.getChangelog().getItems();
     15                     String toUserId = Strings.EMPTY;
     16                     String fromUserId = Strings.EMPTY;
     17                     for(Item item : items){
     18                         if(StringUtils.equals(item.getField(), "assignee")){
     19                             toUserId = item.getTo();
     20                             fromUserId = item.getFrom();
     21                             break;
     22                         }
     23                     }
     24                     if(StringUtils.isNotBlank(toUserId) && StringUtils.isNotBlank(fromUserId)){
     25                         String toMobile = getUserMobile(toUserId);
     26                         String fromMobile = getUserMobile(fromUserId);
     27                         if(StringUtils.isNotBlank(toMobile) && StringUtils.isNotBlank(fromMobile)){
     28                             String issueKey = postData.getIssue().getKey();
     29                             String issueSummary = postData.getIssue().getFields().getSummary();
     30                             DingTalkMarkdownMessage msg = new DingTalkMarkdownMessage();
     31                             msg.setMsgtype("markdown");
     32                             Markdown markdown = new Markdown();
     33                             markdown.setTitle(postData.getIssue().getKey());
     34                             markdown.setText("### @" + fromMobile + " 【转移任务给】@" + toMobile
     35                                     + "
    >任务编号:[" + issueKey + "](" + JIRA_BASE_URL + issueKey + ")"
     36                                     + "  
    任务标题:" + issueSummary);
     37                             msg.setMarkdown(markdown);
     38                             At at = new At();
     39                             at.setAtMobiles(Arrays.asList(toMobile, fromMobile));
     40                             msg.setAt(at);
     41                             return sendMsgToDingTalk(JSONObject.toJSONString(msg));
     42                         }
     43                     }
     44                 }else if(StringUtils.equals(postData.getWebhookEvent(), "jira:issue_created")){
     45                     //创建事件
     46                     String fromUserId = postData.getUser().getKey();
     47                     String toUserId = postData.getIssue().getFields().getAssignee().getKey();
     48                     if(StringUtils.isNotBlank(toUserId) && StringUtils.isNotBlank(fromUserId)){
     49                         String toMobile = getUserMobile(toUserId);
     50                         String fromMobile = getUserMobile(fromUserId);
     51                         if(StringUtils.isNotBlank(toMobile) && StringUtils.isNotBlank(fromMobile)){
     52                             String issueKey = postData.getIssue().getKey();
     53                             String issueSummary = postData.getIssue().getFields().getSummary();
     54                             DingTalkMarkdownMessage msg = new DingTalkMarkdownMessage();
     55                             msg.setMsgtype("markdown");
     56                             Markdown markdown = new Markdown();
     57                             markdown.setTitle(postData.getIssue().getKey());
     58                             markdown.setText("### @" + fromMobile + " 【指派任务给】@" + toMobile
     59                                     + "
    >任务编号:[" + issueKey + "](" + JIRA_BASE_URL + issueKey + ")"
     60                                     + "  
    任务标题:" + issueSummary);
     61                             msg.setMarkdown(markdown);
     62                             At at = new At();
     63                             at.setAtMobiles(Arrays.asList(toMobile, fromMobile));
     64                             msg.setAt(at);
     65                             return sendMsgToDingTalk(JSONObject.toJSONString(msg));
     66                         }
     67                     }
     68                 }
     69             }
     70 
     71         }catch (Exception e) {
     72             log.error("触发JIRA网络钩子失败", e);
     73         }
     74         return false;
     75     }
     76 
     77     private static boolean sendMsgToDingTalk(String msg){
     78         JSONObject postData = JSONObject.parseObject(msg);
     79         JSONObject result = restTemplate.postForObject(DING_TALK_ROBOT_URL, postData, JSONObject.class);
     80         if(result != null
     81                 && result.getIntValue("errcode") == 0
     82                 && StringUtils.equals(result.getString("errmsg"), "ok")){
     83             return true;
     84         }
     85         return false;
     86     }
     87 
     88     private static String getUserMobile(String userId){
     89         String mobile = Strings.EMPTY;
     90 
     91         Hashtable<String, String> env = new Hashtable<String, String>();
     92         env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
     93         env.put(Context.PROVIDER_URL, "ldap://xxxxxx:389");
     94         env.put(Context.SECURITY_AUTHENTICATION, "simple");
     95         env.put(Context.SECURITY_PRINCIPAL, "cn=xxx,dc=xxx,dc=xxx,dc=com");
     96         env.put(Context.SECURITY_CREDENTIALS, "xxxxxx");
     97         DirContext ctx = null;
     98         try{
     99             ctx = new InitialDirContext(env);
    100         }catch(Exception e){
    101             log.error("连接LDAP失败", e);
    102         }
    103 
    104         // 设置过滤条件
    105         String filter = "(&(objectClass=top)(objectClass=inetOrgPerson)(cn=" + userId + "))";
    106         // 限制要查询的字段内容
    107         String[] attrPersonArray = {"cn", "mobile"};
    108         SearchControls searchControls = new SearchControls();
    109         searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    110         // 设置将被返回的Attribute
    111         searchControls.setReturningAttributes(attrPersonArray);
    112         // 三个参数分别为:
    113         // 上下文;
    114         // 要搜索的属性,如果为空或 null,则返回目标上下文中的所有对象;
    115         // 控制搜索的搜索控件,如果为 null,则使用默认的搜索控件
    116         try {
    117             NamingEnumeration<SearchResult> answer = ctx.search(
    118                     "ou=People,dc=xxx,dc=xxx,dc=xxx", filter, searchControls);
    119             // 输出查到的数据
    120             while (answer.hasMore()) {
    121                 SearchResult result = answer.next();
    122                 Attribute attr = result.getAttributes().get("mobile");
    123                 mobile = attr.get().toString();
    124                 break;
    125             }
    126         }catch (Exception e){
    127             log.error("查询LDAP用户信息失败", e);
    128         }
    129         return mobile;
    130     }
    131 
    132 }
    View Code

    6、Jira Software配置网络钩子,使用第5步的接口地址

    四、验证效果

     

  • 相关阅读:
    【Redis】集群NetCore实战
    【Redis】集群教程(Windows)
    【Redis】入门
    【SQL SERVER】索引
    【SQL SERVER】锁机制
    【SQL SERVER】数据内部存储结构简单探索
    Windows软件包管理工具
    Git常用命令记录
    【ASP.NET Core学习】远程过程调用
    CouchDB学习-API
  • 原文地址:https://www.cnblogs.com/voyager-fu/p/jira-notice-dintalk.html
Copyright © 2020-2023  润新知