Commit a9a25331 authored by 黎博's avatar 黎博

新增发送进度报告功能

parent 766c98ae
package cn.qg.holmes.controller.jira; package cn.qg.holmes.controller.jira;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.jira.SendScheduleVo;
import cn.qg.holmes.service.jira.JiraIssueService; import cn.qg.holmes.service.jira.JiraIssueService;
import cn.qg.holmes.utils.DingdingUtils; import cn.qg.holmes.utils.DingdingUtils;
import com.atlassian.jira.rest.client.api.domain.Issue; import com.atlassian.jira.rest.client.api.domain.Issue;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@CrossOrigin @CrossOrigin
@RestController @RestController
...@@ -23,4 +22,17 @@ public class JiraController { ...@@ -23,4 +22,17 @@ public class JiraController {
String markdownMsg = DingdingUtils.buildMarkdownMsgForUnsolvedIssueList(issues); String markdownMsg = DingdingUtils.buildMarkdownMsgForUnsolvedIssueList(issues);
DingdingUtils.sendToDingding(markdownMsg, webhook); DingdingUtils.sendToDingding(markdownMsg, webhook);
} }
/**
* 发送测试进度
* @return
* @throws Exception
*/
@PostMapping("/send/schedule")
public JsonResult sendTestReport(@RequestBody SendScheduleVo sendScheduleVo) throws Exception {
String JQL = "project = " + sendScheduleVo.getJiraProjectKey() + " AND resolution = Unresolved AND text ~ \"" + sendScheduleVo.getTestProjectName() + "\" ORDER BY priority DESC, updated DESC";
Iterable<Issue> issues = jiraIssueService.getIssueListByJQL(JQL);
String markdownMsg = DingdingUtils.buildTestScheduleMarkdownMsg(issues, sendScheduleVo.getProgress(), sendScheduleVo.getRisk());
return JsonResult.buildSuccessResult(DingdingUtils.sendToDingding(markdownMsg, sendScheduleVo.getWebhook()));
}
} }
...@@ -3,6 +3,8 @@ package cn.qg.holmes.controller.jira; ...@@ -3,6 +3,8 @@ package cn.qg.holmes.controller.jira;
import cn.qg.holmes.common.JsonResult; import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.jira.DingRobot; import cn.qg.holmes.entity.jira.DingRobot;
import cn.qg.holmes.service.jira.DingRobotService; import cn.qg.holmes.service.jira.DingRobotService;
import cn.qg.holmes.service.jira.JiraIssueService;
import com.atlassian.jira.rest.client.api.domain.BasicProject;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -11,7 +13,9 @@ import org.springframework.web.bind.annotation.*; ...@@ -11,7 +13,9 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
@Slf4j @Slf4j
...@@ -23,6 +27,9 @@ public class JiraWebhookController { ...@@ -23,6 +27,9 @@ public class JiraWebhookController {
@Autowired @Autowired
DingRobotService dingRobotService; DingRobotService dingRobotService;
@Autowired
JiraIssueService jiraIssueService;
/** /**
* jira webhook * jira webhook
* @param request * @param request
...@@ -43,6 +50,25 @@ public class JiraWebhookController { ...@@ -43,6 +50,25 @@ public class JiraWebhookController {
} }
} }
/**
* 获取Jira项目列表
* @return
* @throws Exception
*/
@GetMapping("/list/project")
public JsonResult getJiraProjectKey() throws Exception {
List<Map<String, String>> jiraKeyList = new ArrayList<>();
Iterable<BasicProject> projects = jiraIssueService.getJiraProjectList();
for (BasicProject project: projects) {
Map<String, String> map = new HashMap<>();
map.put("id", project.getId().toString());
map.put("key", project.getKey());
map.put("name", project.getName());
jiraKeyList.add(map);
}
return JsonResult.buildSuccessResult(jiraKeyList);
}
/** /**
* 项目机器人列表 * 项目机器人列表
* @param pageNum 第几页 * @param pageNum 第几页
......
...@@ -14,6 +14,7 @@ public class DingRobot { ...@@ -14,6 +14,7 @@ public class DingRobot {
@TableId(type = IdType.AUTO) @TableId(type = IdType.AUTO)
private Integer id; private Integer id;
private String projectName; private String projectName;
private String jiraProjectKey;
private String dingUrl; private String dingUrl;
private String creator; private String creator;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
......
package cn.qg.holmes.entity.jira;
import lombok.Data;
/**
* 发送测试进度实体类
*/
@Data
public class SendScheduleVo {
private String jiraProjectKey;
private String testProjectName;
private String progress;
private String risk;
private String webhook;
}
package cn.qg.holmes.service.jira; package cn.qg.holmes.service.jira;
import com.atlassian.jira.rest.client.api.domain.BasicProject;
import com.atlassian.jira.rest.client.api.domain.Issue; import com.atlassian.jira.rest.client.api.domain.Issue;
public interface JiraIssueService { public interface JiraIssueService {
Iterable<Issue> getUnsolvedIssueListByProject(String project) throws Exception; Iterable<Issue> getUnsolvedIssueListByProject(String project) throws Exception;
Iterable<Issue> getIssueListByJQL(String JQL) throws Exception;
Iterable<BasicProject> getJiraProjectList() throws Exception;
} }
package cn.qg.holmes.service.jira.impl; package cn.qg.holmes.service.jira.impl;
import cn.qg.holmes.service.jira.JiraIssueService; import cn.qg.holmes.service.jira.JiraIssueService;
import cn.qg.holmes.utils.DingdingUtils;
import com.atlassian.jira.rest.client.api.JiraRestClient; import com.atlassian.jira.rest.client.api.JiraRestClient;
import com.atlassian.jira.rest.client.api.JiraRestClientFactory; import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
import com.atlassian.jira.rest.client.api.domain.BasicProject;
import com.atlassian.jira.rest.client.api.domain.Issue; import com.atlassian.jira.rest.client.api.domain.Issue;
import com.atlassian.jira.rest.client.api.domain.SearchResult; import com.atlassian.jira.rest.client.api.domain.SearchResult;
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory; import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
import io.atlassian.util.concurrent.Promise; import io.atlassian.util.concurrent.Promise;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
@Service @Service
public class JiraIssueServiceImpl implements JiraIssueService { public class JiraIssueServiceImpl implements JiraIssueService {
...@@ -21,6 +21,7 @@ public class JiraIssueServiceImpl implements JiraIssueService { ...@@ -21,6 +21,7 @@ public class JiraIssueServiceImpl implements JiraIssueService {
public static String url = "http://jira2.quantgroup.cn/"; public static String url = "http://jira2.quantgroup.cn/";
public static String username = "test1"; public static String username = "test1";
public static String password = "123456"; public static String password = "123456";
public static JiraRestClient jiraRestClient = createJiraRestClient();
public static JiraRestClient createJiraRestClient() { public static JiraRestClient createJiraRestClient() {
JiraRestClientFactory jiraRestClientFactory = new AsynchronousJiraRestClientFactory(); JiraRestClientFactory jiraRestClientFactory = new AsynchronousJiraRestClientFactory();
...@@ -41,10 +42,63 @@ public class JiraIssueServiceImpl implements JiraIssueService { ...@@ -41,10 +42,63 @@ public class JiraIssueServiceImpl implements JiraIssueService {
*/ */
@Override @Override
public Iterable<Issue> getUnsolvedIssueListByProject(String project) throws Exception{ public Iterable<Issue> getUnsolvedIssueListByProject(String project) throws Exception{
JiraRestClient jiraRestClient = createJiraRestClient();
Promise<SearchResult> resultPromise = jiraRestClient.getSearchClient().searchJql("project = " + project + " AND resolution = Unresolved ORDER BY priority DESC"); Promise<SearchResult> resultPromise = jiraRestClient.getSearchClient().searchJql("project = " + project + " AND resolution = Unresolved ORDER BY priority DESC");
Iterable<Issue> issues = resultPromise.get().getIssues(); Iterable<Issue> issues = resultPromise.get().getIssues();
return issues; return issues;
} }
/**
* 根据JQL获取BUG列表
* @param JQL jira JQL
* @return
* @throws Exception
*/
@Override
public Iterable<Issue> getIssueListByJQL(String JQL) throws Exception {
Promise<SearchResult> resultPromise = jiraRestClient.getSearchClient().searchJql(JQL);
Iterable<Issue> issues = resultPromise.get().getIssues();
return issues;
}
/**
* 获取Jira项目列表
* @return
* @throws Exception
*/
@Override
public Iterable<BasicProject> getJiraProjectList() throws Exception {
Promise<Iterable<BasicProject>> allProjects = jiraRestClient.getProjectClient().getAllProjects();
Iterable<BasicProject> basicProjects = allProjects.get();
return basicProjects;
}
/**
* 计算BUG修复时间
* @param createDate BUG创建时间
* @param updateDate BUG最近一次更新时间
* @return
*/
public Integer caculBugFixTime(DateTime createDate, DateTime updateDate) {
int createHour = createDate.getHourOfDay();
int updateHour = updateDate.getHourOfDay();
if (createHour > 19) {
createHour = 19;
} else if (createHour < 10) {
createHour = 10;
}
if (updateHour > 19) {
updateHour = 19;
}
int hourDiff;
if (updateHour > createHour) {
hourDiff = updateHour - createHour -1;
} else if (updateHour < createHour) {
hourDiff = updateHour - createHour + 1;
} else {
hourDiff = updateHour - createHour;
}
int days = Days.daysBetween(createDate, updateDate).getDays();
return (days+1) * 8 + hourDiff;
}
} }
...@@ -4,10 +4,9 @@ import com.alibaba.fastjson.JSON; ...@@ -4,10 +4,9 @@ import com.alibaba.fastjson.JSON;
import com.atlassian.jira.rest.client.api.domain.Issue; import com.atlassian.jira.rest.client.api.domain.Issue;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList; import java.text.DateFormat;
import java.util.HashMap; import java.text.SimpleDateFormat;
import java.util.List; import java.util.*;
import java.util.Map;
@Slf4j @Slf4j
public class DingdingUtils { public class DingdingUtils {
...@@ -28,7 +27,7 @@ public class DingdingUtils { ...@@ -28,7 +27,7 @@ public class DingdingUtils {
String title = creator + "提交了BUG:" + key; String title = creator + "提交了BUG:" + key;
String issueUrl = "http://jira2.quantgroup.cn/browse/" + key; String issueUrl = "http://jira2.quantgroup.cn/browse/" + key;
content.put("title", title); content.put("title", title);
content.put("text", "### " + title + "\n" content.put("text", "#### " + title + "\n"
+ "#### 概要:[" + summary + "](" + issueUrl + ")"+ "\n" + "#### 概要:[" + summary + "](" + issueUrl + ")"+ "\n"
+ "- 优先级:" + priority + "\n" + "- 优先级:" + priority + "\n"
+ "- 模块:" + module + "\n" + "- 模块:" + module + "\n"
...@@ -70,8 +69,42 @@ public class DingdingUtils { ...@@ -70,8 +69,42 @@ public class DingdingUtils {
return JSON.toJSONString(markdown); return JSON.toJSONString(markdown);
} }
public static String buildTestScheduleMarkdownMsg(Iterable<Issue> issues, String progress, String risk) {
Map<String, Object> markdown = new HashMap<>();
Map<String, String> contentMap = new HashMap<>();
Map<String, Object> atMap = new HashMap<>();
atMap.put("isAtAll", true);
markdown.put("at", atMap);
List<Issue> issueList = new ArrayList<>();
for (Issue issue: issues) {
issueList.add(issue);
}
markdown.put("msgtype", "markdown");
Date date=new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
contentMap.put("title", format.format(date) + "今日测试进度汇报");
String content = format.format(date) + "\n\n";
content += "今日测试进度:" + progress + " \n\n";
content = content + "剩余未解决BUG列表:" + "\n\n";
int count = 0;
for (Issue issue: issueList) {
count += 1;
String issueUrl = "http://jira2.quantgroup.cn/browse/" + issue.getKey();
content = content + count + "、[" + issue.getSummary().replace("\"", "") + "](" + issueUrl + ")\n";
content = content + "- 优先级:" + issue.getPriority().getName() + "\n";
content = content + "- 状态:" + issue.getStatus().getName() + "\n";
content = content + "- 经办人:" + issue.getAssignee().getDisplayName() + "\n\n";
}
if (risk != null && !risk.isEmpty()) {
content = content + "**风险:" + risk + "**\n";
}
contentMap.put("text", content);
markdown.put("markdown", contentMap);
return JSON.toJSONString(markdown);
}
public static void main(String[] args) { public static void main(String[] args) {
String markdown = buildMarkdownMsg("YXM-1499", "【羊小咩v7.6.00】【VCC首次交易率提升专题】巴拉巴拉", "黎博", "于巧玲", "p1", "kddsp"); // String markdown = buildMarkdownMsg("YXM-1499", "【羊小咩v7.6.00】【VCC首次交易率提升专题】巴拉巴拉", "黎博", "于巧玲", "p1", "kddsp");
sendToDingding(markdown, "https://oapi.dingtalk.com/robot/send?access_token=835663338d638e40daaf3ab358af741ef0680a826a962c91bedc53b149d85ee1"); // sendToDingding(markdown, "https://oapi.dingtalk.com/robot/send?access_token=835663338d638e40daaf3ab358af741ef0680a826a962c91bedc53b149d85ee1");
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment