Commit aa5d6cc8 authored by 黎博's avatar 黎博

Merge branch 'master' into ldap

parents f3d3077d d0804b88
...@@ -136,6 +136,18 @@ ...@@ -136,6 +136,18 @@
<version>5.2.0</version> <version>5.2.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.offbytwo.jenkins</groupId>
<artifactId>jenkins-client</artifactId>
<version>0.3.8</version>
</dependency>
<dependency>
<groupId>org.gitlab</groupId>
<artifactId>java-gitlab-api</artifactId>
<version>4.1.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -4,15 +4,19 @@ import cn.qg.holmes.common.JsonResult; ...@@ -4,15 +4,19 @@ import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.auto.Interface; import cn.qg.holmes.entity.auto.Interface;
import cn.qg.holmes.service.auto.AutoModuleService; import cn.qg.holmes.service.auto.AutoModuleService;
import cn.qg.holmes.service.auto.InterfaceService; import cn.qg.holmes.service.auto.InterfaceService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* 接口相关controller * 接口相关controller
...@@ -106,4 +110,90 @@ public class InterfaceController { ...@@ -106,4 +110,90 @@ public class InterfaceController {
} }
return JsonResult.buildSuccessResult(interfaceService.removeById(interfaceId)); return JsonResult.buildSuccessResult(interfaceService.removeById(interfaceId));
} }
/**
* 解析CURL
* @param code curl代码
* @return
*/
@GetMapping("/curl")
public JsonResult resolutionCurl(@RequestParam String code) {
List<Map<String, String>> headersList = new ArrayList<>();
List<Map<String, String>> parametersList = new ArrayList<>();
Map<String, Object> resultMap = new HashMap<>();
if (code.contains("GET")) {
// 处理GET请求
String getParameters = code.split("\\?")[1];
// 去掉末尾的单引号
getParameters = getParameters.substring(0, getParameters.length()-1);
String[] paramPair = getParameters.split("&");
for (String pair: paramPair) {
String[] pairList = pair.split("=");
Map<String, String> map = new HashMap<>();
map.put("paramsName", pairList[0]);
map.put("paramsValue", pairList[1]);
parametersList.add(map);
}
} else if (code.contains("POST")) {
// 处理POST请求
String headerRegex = "--header '(.*)'";
String parameterDataRegex = "--data-urlencode '(.*)'";
String parameterFormRegex = "--form '(.*)'";
String parameterJsonRegex = "--data-raw '(.*)'";
Pattern headerPattern = Pattern.compile(headerRegex);
Pattern parameterDataPattern = Pattern.compile(parameterDataRegex);
Pattern parameterFormPattern = Pattern.compile(parameterFormRegex);
Pattern parameterJsonPattern = Pattern.compile(parameterJsonRegex, Pattern.DOTALL);
Matcher headerMatcher = headerPattern.matcher(code);
Matcher parameterDataMatcher = parameterDataPattern.matcher(code);
Matcher parameterFormMatcher = parameterFormPattern.matcher(code);
Matcher parameterJsonMatcher = parameterJsonPattern.matcher(code);
while (headerMatcher.find()) {
Map<String, String> headersMap = new HashMap<>();
String headerItem = headerMatcher.group(1);
String[] tempList = headerItem.split(":");
headersMap.put("paramsName", tempList[0].trim());
headersMap.put("paramsValue", tempList[1].trim());
headersList.add(headersMap);
}
while (parameterDataMatcher.find()) {
Map<String, String> parameterMap = new HashMap<>();
String parameterItem = parameterDataMatcher.group(1);
String[] tempList = parameterItem.split("=");
parameterMap.put("paramsName", tempList[0].trim());
if (tempList.length == 2) {
parameterMap.put("paramsValue", tempList[1].trim());
} else {
parameterMap.put("paramsValue", "");
}
parametersList.add(parameterMap);
}
while (parameterFormMatcher.find()) {
Map<String, String> parameterMap = new HashMap<>();
String parameterItem = parameterFormMatcher.group(1);
String[] tempList = parameterItem.split("=");
parameterMap.put("paramsName", tempList[0].trim());
if (tempList.length == 2) {
parameterMap.put("paramsValue", tempList[1].trim());
} else {
parameterMap.put("paramsValue", "");
}
parametersList.add(parameterMap);
}
while (parameterJsonMatcher.find()) {
Map<String, String> parameterMap = new HashMap<>();
String parameterItem = parameterJsonMatcher.group(1);
Map<String, Object> requestMap = JSON.parseObject(parameterItem, Map.class);
for (Map.Entry<String, Object> entry: requestMap.entrySet()) {
parameterMap.put("paramsName", entry.getKey());
parameterMap.put("paramsValue", entry.getValue().toString());
parametersList.add(parameterMap);
}
}
}
resultMap.put("headersList", headersList);
resultMap.put("parametersList", parametersList);
return JsonResult.buildSuccessResult(resultMap);
}
} }
package cn.qg.holmes.controller.auto; package cn.qg.holmes.controller.auto;
import cn.qg.holmes.common.JsonResult; import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.auto.AutoModule; import cn.qg.holmes.entity.auto.Scene;
import cn.qg.holmes.entity.auto.Interface;
import cn.qg.holmes.entity.auto.SceneTestcase; import cn.qg.holmes.entity.auto.SceneTestcase;
import cn.qg.holmes.entity.auto.SceneTestcaseUpdateVo; import cn.qg.holmes.entity.auto.SceneTestcaseUpdateVo;
import cn.qg.holmes.service.auto.AutoModuleService; import cn.qg.holmes.service.auto.AutoModuleService;
import cn.qg.holmes.service.auto.InterfaceService; import cn.qg.holmes.service.auto.InterfaceService;
import cn.qg.holmes.service.auto.SceneService;
import cn.qg.holmes.service.auto.SceneTestcaseService; import cn.qg.holmes.service.auto.SceneTestcaseService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -17,11 +17,15 @@ import java.util.HashMap; ...@@ -17,11 +17,15 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@Slf4j
@CrossOrigin @CrossOrigin
@RestController @RestController
@RequestMapping("/auto/sceneTestcase") @RequestMapping("/auto/sceneTestcase")
public class SceneTestcaseController { public class SceneTestcaseController {
@Autowired
SceneService sceneService;
@Autowired @Autowired
SceneTestcaseService sceneTestcaseService; SceneTestcaseService sceneTestcaseService;
...@@ -42,12 +46,12 @@ public class SceneTestcaseController { ...@@ -42,12 +46,12 @@ public class SceneTestcaseController {
return JsonResult.buildErrorStateResult("请传入场景id", false); return JsonResult.buildErrorStateResult("请传入场景id", false);
} }
List<SceneTestcase> sceneTestcaseList = sceneTestcaseService.getSceneTestcaseListBySceneId(sceneId); List<SceneTestcase> sceneTestcaseList = sceneTestcaseService.getSceneTestcaseListBySceneId(sceneId);
for (SceneTestcase sceneTestcase: sceneTestcaseList) { Scene scene = sceneService.getById(sceneId);
Interface anInterface = interfaceService.getById(sceneTestcase.getInterfaceId()); Map<String, Object> map = new HashMap<>();
sceneTestcase.setInterfaceName(anInterface.getName()); map.put("sceneId", scene.getId());
sceneTestcase.setModuleName(autoModuleService.getById(anInterface.getModuleId()).getName()); map.put("globalParameters", scene.getGlobalParameters());
} map.put("sceneTestcaseList", sceneTestcaseList);
return JsonResult.buildSuccessResult(sceneTestcaseList); return JsonResult.buildSuccessResult(map);
} }
/** /**
...@@ -100,17 +104,27 @@ public class SceneTestcaseController { ...@@ -100,17 +104,27 @@ public class SceneTestcaseController {
public JsonResult saveOrUpdateSceneTestcaseList(@RequestBody SceneTestcaseUpdateVo sceneTestcaseUpdateVo) { public JsonResult saveOrUpdateSceneTestcaseList(@RequestBody SceneTestcaseUpdateVo sceneTestcaseUpdateVo) {
List<SceneTestcase> sceneTestcaseList = sceneTestcaseUpdateVo.getSceneTestcaseList(); List<SceneTestcase> sceneTestcaseList = sceneTestcaseUpdateVo.getSceneTestcaseList();
Integer sceneId = sceneTestcaseUpdateVo.getSceneId(); Integer sceneId = sceneTestcaseUpdateVo.getSceneId();
String globalParameters = sceneTestcaseUpdateVo.getGlobalParameters();
Scene scene = sceneService.getById(sceneId);
scene.setGlobalParameters(globalParameters);
sceneService.saveOrUpdate(scene);
log.info("开始批量修改场景id为 {} 的场景用例:\n {}", sceneId, sceneTestcaseList);
List<SceneTestcase> sceneTestcaseListInDB = sceneTestcaseService.getSceneTestcaseListBySceneId(sceneId); List<SceneTestcase> sceneTestcaseListInDB = sceneTestcaseService.getSceneTestcaseListBySceneId(sceneId);
log.info("数据库中的场景用例为:{}", sceneTestcaseListInDB);
if (sceneTestcaseListInDB.size() > 0) { if (sceneTestcaseListInDB.size() > 0) {
for (SceneTestcase sceneTestcaseInDB: sceneTestcaseListInDB) { for (SceneTestcase sceneTestcaseInDB: sceneTestcaseListInDB) {
Integer DBId = sceneTestcaseInDB.getId(); Integer DBId = sceneTestcaseInDB.getId();
boolean flag = false; boolean flag = false;
for (SceneTestcase sceneTestcase: sceneTestcaseList) { for (SceneTestcase sceneTestcase: sceneTestcaseList) {
if (sceneTestcase.getId().equals(DBId)) { // 过滤掉新增的
flag = true; if (sceneTestcase.getId() != null) {
if (sceneTestcase.getId().equals(DBId)) {
flag = true;
}
} }
} }
if (!flag) { if (!flag) {
log.info("{}不在传入的list中,删除该条数据!", sceneTestcaseInDB);
sceneTestcaseService.removeById(sceneTestcaseInDB.getId()); sceneTestcaseService.removeById(sceneTestcaseInDB.getId());
} }
} }
......
package cn.qg.holmes.controller.auto; package cn.qg.holmes.controller.auto;
import cn.qg.holmes.common.JsonResult; import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.auto.Interface;
import cn.qg.holmes.entity.auto.Testcase; import cn.qg.holmes.entity.auto.Testcase;
import cn.qg.holmes.service.auto.InterfaceService;
import cn.qg.holmes.service.auto.TestcaseService; import cn.qg.holmes.service.auto.TestcaseService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
...@@ -9,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -9,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
...@@ -23,6 +26,9 @@ public class TestcaseController { ...@@ -23,6 +26,9 @@ public class TestcaseController {
@Autowired @Autowired
TestcaseService testcaseService; TestcaseService testcaseService;
@Autowired
InterfaceService interfaceService;
/** /**
* 获取单接口用例列表 * 获取单接口用例列表
* @param moduleId 模块id * @param moduleId 模块id
...@@ -51,7 +57,13 @@ public class TestcaseController { ...@@ -51,7 +57,13 @@ public class TestcaseController {
public JsonResult getTestcaseListByInterface(Integer interfaceId) { public JsonResult getTestcaseListByInterface(Integer interfaceId) {
QueryWrapper<Testcase> testcaseQueryWrapper = new QueryWrapper<>(); QueryWrapper<Testcase> testcaseQueryWrapper = new QueryWrapper<>();
testcaseQueryWrapper.eq("interface_id", interfaceId); testcaseQueryWrapper.eq("interface_id", interfaceId);
return JsonResult.buildSuccessResult(testcaseService.list(testcaseQueryWrapper)); List<Testcase> testcaseList = testcaseService.list(testcaseQueryWrapper);
Interface anInterface = interfaceService.getById(interfaceId);
for (Testcase testcase: testcaseList) {
testcase.setInterfaceName(anInterface.getName());
testcase.setInterfaceUrl(anInterface.getUrl());
}
return JsonResult.buildSuccessResult(testcaseList);
} }
/** /**
......
package cn.qg.holmes.controller.gitlab;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.utils.HttpClientUtils;
import com.alibaba.fastjson.JSON;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@CrossOrigin
@RestController
@RequestMapping("/gitlab")
public class GitlabController {
/**
* 获取项目名列表
* @return
*/
@GetMapping("/projects")
public JsonResult getProjectsList() {
String baseUrl = "http://qaapi.liangkebang.com/proconfig/get_project_for_jenkins?type=";
String javaResult = HttpClientUtils.doGet(baseUrl + "java");
String uiResult = HttpClientUtils.doGet(baseUrl + "ui");
String nodeResult = HttpClientUtils.doGet(baseUrl + "node");
List<String> javaList = Arrays.asList(javaResult.split("\n"));
List<String> uiList = Arrays.asList(uiResult.split("\n"));
List<String> nodeList = Arrays.asList(nodeResult.split("\n"));
List<Map<String, String>> serviceList = new ArrayList<>();
for (String service: javaList) {
Map<String, String> map = new HashMap<>();
map.put("name", service);
map.put("type", "java");
serviceList.add(map);
}
for (String service: uiList) {
Map<String, String> map = new HashMap<>();
map.put("name", service);
map.put("type", "ui");
serviceList.add(map);
}
for (String service: nodeList) {
Map<String, String> map = new HashMap<>();
map.put("name", service);
map.put("type", "node");
serviceList.add(map);
}
return JsonResult.buildSuccessResult(serviceList);
}
/**
* 根据项目名获取分支列表
* @param projectName 项目名
* @return
*/
@GetMapping("/branches")
public JsonResult getBranchesByProject(String projectName) {
String url = "https://qaapi.liangkebang.com/pipeline/getGitBranch?name=" + projectName;
return JsonResult.buildSuccessResult(JSON.parseObject(HttpClientUtils.doGet(url), Map.class));
}
}
package cn.qg.holmes.controller.gitlab;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.utils.JenkinsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/jenkins")
public class JenkinsController {
@Autowired
JenkinsService jenkinsService;
/**
* 构建指定的jenkins job
* @param type 类型,java/ui/node
* @param project 项目名
* @param branch 分支名
* @param namespace 环境
* @return
*/
@GetMapping("/build")
public JsonResult buildSpecifiedJob(@RequestParam String type,
@RequestParam String project,
@RequestParam String branch,
@RequestParam String namespace) {
try {
log.info("开始构建jenkins项目:项目类型:{}, 项目名:{}, 分支:{}, 部署至环境:{}", type, project, branch, namespace);
jenkinsService.buildJenkinsJob(type, project, branch, namespace);
return JsonResult.buildSuccessResult(true);
} catch (Exception e) {
e.printStackTrace();
return JsonResult.buildErrorStateResult("构建失败!", false);
}
}
}
package cn.qg.holmes.controller.gitlab;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.gitlab.DingRobotPipelineVo;
import cn.qg.holmes.entity.gitlab.Pipeline;
import cn.qg.holmes.entity.jira.DingRobot;
import cn.qg.holmes.service.gitlab.PipelineService;
import cn.qg.holmes.service.jira.DingRobotService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@CrossOrigin
@RequestMapping("/pipeline")
public class PipelineController {
@Autowired
PipelineService pipelineService;
@Autowired
DingRobotService dingRobotService;
/**
* gitlab webhook
* @param request
*/
@PostMapping("/webhook")
public void piplineWebhook(HttpServletRequest request) {
StringBuilder piplineData = new StringBuilder();
try {
BufferedReader br = request.getReader();
String str = "";
while((str = br.readLine()) != null){
piplineData.append(str);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
log.info("收到gitlab推送来的数据:{}", piplineData);
pipelineService.buildPipelineJob(String.valueOf(piplineData));
}
@GetMapping("/list")
public JsonResult getDingRobotAndPipelineList(@RequestParam Integer pageNum, @RequestParam Integer pageSize) {
IPage<DingRobot> page = new Page<>(pageNum, pageSize);
QueryWrapper<DingRobot> dingRobotQueryWrapper = new QueryWrapper();
dingRobotQueryWrapper.orderByDesc("id");
IPage<DingRobot> projectRobotIPage = dingRobotService.page(page, dingRobotQueryWrapper);
List<DingRobot> dingRobotList = projectRobotIPage.getRecords();
List<DingRobotPipelineVo> dingRobotPipelineVoList = new ArrayList<>();
for (DingRobot dingRobot: dingRobotList) {
DingRobotPipelineVo dingRobotPipelineVo = new DingRobotPipelineVo();
dingRobotPipelineVo.setDingRobot(dingRobot);
QueryWrapper<Pipeline> pipelineQueryWrapper = new QueryWrapper<>();
pipelineQueryWrapper.eq("ding_robot_id", dingRobot.getId());
List<Pipeline> pipelineList = pipelineService.list(pipelineQueryWrapper);
dingRobotPipelineVo.setPipelineList(pipelineList);
dingRobotPipelineVoList.add(dingRobotPipelineVo);
}
Map<String, Object> map = new HashMap<>();
map.put("total", projectRobotIPage.getTotal());
map.put("list", dingRobotPipelineVoList);
return JsonResult.buildSuccessResult(map);
}
/**
* 新增ding robot 以及对应的pipeline
* @return
*/
@PostMapping("/add")
public JsonResult addRobotAndPipeline(@RequestBody DingRobotPipelineVo dingRobotPipelineVo) {
try {
DingRobot dingRobot = dingRobotPipelineVo.getDingRobot();
String projectName = dingRobot.getProjectName();
String jiraProjectKey = dingRobot.getJiraProjectKey();
QueryWrapper<DingRobot> dingRobotQueryWrapper = new QueryWrapper<>();
dingRobotQueryWrapper.eq("jira_project_key", jiraProjectKey);
dingRobotQueryWrapper.eq("project_name", projectName);
// 根据jira project key和项目名判断是否已存在
if (dingRobotService.getOne(dingRobotQueryWrapper) != null) {
return JsonResult.buildErrorStateResult("项目已存在", false);
}
boolean dingRobotResult = dingRobotService.save(dingRobot);
if (!dingRobotResult) {
return JsonResult.buildErrorStateResult("服务器异常,保存失败!", false);
}
// 获取该robot id,并赋值给pipelineList
DingRobot dingRobotNew = dingRobotService.getOne(dingRobotQueryWrapper);
Integer dingRobotId = dingRobotNew.getId();
List<Pipeline> pipelineList = dingRobotPipelineVo.getPipelineList();
// 判断pipelineList是否为空
if (pipelineList.size() > 0) {
for (Pipeline pipeline: pipelineList) {
pipeline.setDingRobotId(dingRobotId);
}
pipelineService.saveBatch(pipelineList);
}
return JsonResult.buildSuccessResult(true);
} catch (Exception e) {
e.printStackTrace();
return JsonResult.buildErrorStateResult("新增失败", false);
}
}
/**
* 修改pipeline
* @param dingRobotPipelineVo
* @return
*/
@PostMapping("/modify")
public JsonResult modifyPipeline(@RequestBody DingRobotPipelineVo dingRobotPipelineVo) {
try {
DingRobot dingRobot = dingRobotPipelineVo.getDingRobot();
boolean dingRobotResult = dingRobotService.saveOrUpdate(dingRobot);
if (!dingRobotResult) {
return JsonResult.buildErrorStateResult("修改失败!", false);
}
Integer dingRobotId = dingRobot.getId();
List<Pipeline> pipelineList = dingRobotPipelineVo.getPipelineList();
QueryWrapper<Pipeline> pipelineQueryWrapper = new QueryWrapper<>();
pipelineQueryWrapper.eq("ding_robot_id", dingRobotId);
List<Pipeline> pipelineListInDb = pipelineService.list(pipelineQueryWrapper);
// 判断是否有删除的部分
if (pipelineListInDb.size() > 0) {
for (Pipeline pipelineDb: pipelineListInDb) {
boolean flag = false;
if (pipelineList.size() > 0) {
for (Pipeline pipeline: pipelineList) {
if (pipelineDb.getId().equals(pipeline.getId())) {
flag = true;
break;
}
}
}
if (!flag) {
pipelineService.removeById(pipelineDb.getId());
}
}
}
// 判断是否有新增的
for (Pipeline pipeline: pipelineList) {
if (pipeline.getId() == null) {
pipeline.setDingRobotId(dingRobotId);
}
}
// 剩下的直接更新
pipelineService.saveOrUpdateBatch(pipelineList);
return JsonResult.buildSuccessResult(true);
} catch (Exception e) {
e.printStackTrace();
return JsonResult.buildErrorStateResult("修改失败!", false);
}
}
/**
* 删除pipeline
* @param dingRobotId
* @return
*/
@GetMapping("/delete")
public JsonResult deletePipeline(@RequestParam Integer dingRobotId) {
try {
if (dingRobotService.getById(dingRobotId) != null) {
dingRobotService.removeById(dingRobotId);
}
QueryWrapper<Pipeline> pipelineQueryWrapper = new QueryWrapper<>();
pipelineQueryWrapper.eq("ding_robot_id", dingRobotId);
if (pipelineService.list(pipelineQueryWrapper) != null) {
pipelineService.remove(pipelineQueryWrapper);
}
return JsonResult.buildSuccessResult(true);
} catch (Exception e) {
return JsonResult.buildErrorStateResult("删除失败", false);
}
}
}
package cn.qg.holmes.controller.jira; package cn.qg.holmes.controller.jira;
import cn.qg.holmes.common.JsonResult; import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.jira.JiraBugPool; import cn.qg.holmes.entity.jira.DingRobot;
import cn.qg.holmes.entity.jira.SendScheduleVo; import cn.qg.holmes.entity.jira.SendScheduleVo;
import cn.qg.holmes.entity.jira.SendSmokingResultVo;
import cn.qg.holmes.service.jira.DingRobotService;
import cn.qg.holmes.service.jira.JiraBugPoolService; import cn.qg.holmes.service.jira.JiraBugPoolService;
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.BasicProject;
import com.atlassian.jira.rest.client.api.domain.Issue; import com.atlassian.jira.rest.client.api.domain.Issue;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.joda.time.DateTime; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.text.SimpleDateFormat; import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
...@@ -29,6 +34,114 @@ public class JiraController { ...@@ -29,6 +34,114 @@ public class JiraController {
@Autowired @Autowired
JiraBugPoolService jiraBugPoolService; JiraBugPoolService jiraBugPoolService;
@Autowired
DingRobotService dingRobotService;
/**
* jira webhook
* @param request
*/
@PostMapping("/webhook")
public void jiraWebhook(HttpServletRequest request) {
try {
BufferedReader br = request.getReader();
StringBuilder jiraData = new StringBuilder();
String str = "";
while((str = br.readLine()) != null){
jiraData.append(str);
}
br.close();
dingRobotService.sendMsgToDing(String.valueOf(jiraData));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取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 pageSize 每页多少个
* @return
*/
@GetMapping("/list/robot")
public JsonResult getProjectRobotList(Integer pageNum, Integer pageSize) {
IPage<DingRobot> page = new Page<>(pageNum, pageSize);
QueryWrapper<DingRobot> dingRobotQueryWrapper = new QueryWrapper();
dingRobotQueryWrapper.orderByDesc("id");
IPage<DingRobot> projectRobotIPage = dingRobotService.page(page, dingRobotQueryWrapper);
Map<String, Object> map = new HashMap<>();
map.put("total", projectRobotIPage.getTotal());
map.put("list", projectRobotIPage.getRecords());
return JsonResult.buildSuccessResult(map);
}
/**
* 新增项目机器人
* @param dingRobot 项目机器人实体
* @return
*/
@PostMapping("/add/robot")
public JsonResult addProjectRobot(@RequestBody DingRobot dingRobot) {
if (dingRobot.getProjectName() == null) {
return JsonResult.buildErrorStateResult("项目名称不能为空!", false);
}
if (dingRobot.getDingUrl() == null) {
return JsonResult.buildErrorStateResult("钉钉url不能为空!", false);
}
return JsonResult.buildSuccessResult(dingRobotService.save(dingRobot));
}
/**
* 修改项目机器人
* @param dingRobot 项目机器人实体
* @return
*/
@PostMapping("/modify/robot")
public JsonResult editProjectRobot(@RequestBody DingRobot dingRobot) {
if (dingRobot.getId() == null) {
return JsonResult.buildErrorStateResult("id不能为空!", false);
}
if (dingRobot.getProjectName() == null) {
return JsonResult.buildErrorStateResult("项目名称不能为空!", false);
}
if (dingRobot.getDingUrl() == null) {
return JsonResult.buildErrorStateResult("钉钉url不能为空!", false);
}
return JsonResult.buildSuccessResult(dingRobotService.updateById(dingRobot));
}
/**
* 删除项目机器人
* @param projectRobotId 项目机器人实体id
* @return
*/
@GetMapping("/delete/robot")
public JsonResult deleteProjectRobot(Integer projectRobotId) {
if (dingRobotService.getById(projectRobotId) == null) {
return JsonResult.buildErrorStateResult("项目机器人不存在!", false);
}
return JsonResult.buildSuccessResult(dingRobotService.removeById(projectRobotId));
}
@GetMapping("/report/project") @GetMapping("/report/project")
public void sendReportToDingdingGroup(String project, String webhook) throws Exception { public void sendReportToDingdingGroup(String project, String webhook) throws Exception {
Iterable<Issue> issues = jiraIssueService.getUnsolvedIssueListByProject(project); Iterable<Issue> issues = jiraIssueService.getUnsolvedIssueListByProject(project);
...@@ -49,51 +162,51 @@ public class JiraController { ...@@ -49,51 +162,51 @@ public class JiraController {
return JsonResult.buildSuccessResult(DingdingUtils.sendToDingding(markdownMsg, sendScheduleVo.getWebhook())); return JsonResult.buildSuccessResult(DingdingUtils.sendToDingding(markdownMsg, sendScheduleVo.getWebhook()));
} }
@GetMapping("/test") /**
public JsonResult test() throws Exception{ * 发送冒烟测试进度
String JQL = "project = XCX AND text ~ KA乐信 ORDER BY key ASC, priority DESC, updated DESC"; * @param sendSmokingResultVo 发送冒烟进度实体
* @return
*/
@PostMapping("/send/smoking")
public JsonResult sendSmokingResult(@RequestBody SendSmokingResultVo sendSmokingResultVo) throws Exception {
String JQL = "project = " + sendSmokingResultVo.getJiraProjectKey() + " AND resolution = Unresolved AND text ~ \""
+ sendSmokingResultVo.getTestProjectName() + "\" ORDER BY priority DESC, updated DESC";
Iterable<Issue> issues = jiraIssueService.getIssueListByJQL(JQL); Iterable<Issue> issues = jiraIssueService.getIssueListByJQL(JQL);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String markdownMsg = DingdingUtils.buildSmokingResultMarkdownMsg(issues, sendSmokingResultVo.getResult(), sendSmokingResultVo.getRisk());
List<Map<String, Object>> result = new ArrayList<>(); return JsonResult.buildSuccessResult(DingdingUtils.sendToDingding(markdownMsg, sendSmokingResultVo.getWebhook()));
for (Issue issue: issues) {
Map<String, Object> map = new HashMap<>();
map.put("标题", issue.getSummary());
map.put("报告人", issue.getReporter().getDisplayName());
map.put("经办人", issue.getAssignee().getDisplayName());
map.put("优先级", issue.getPriority().getName());
map.put("创建时间", simpleDateFormat.format(issue.getCreationDate().toDate()));
if (issue.getStatus().getName().equals("关闭") || issue.getStatus().getName().equals("已解决")) {
map.put("解决时间", simpleDateFormat.format(DateTime.parse(issue.getFieldByName("已解决").getValue().toString()).toDate()));
} else {
map.put("解决时间", null);
}
map.put("解决时长", jiraIssueService.calculateBugFixTime(issue.getCreationDate(), DateTime.parse(issue.getFieldByName("已解决").getValue().toString())).toString());
result.add(map);
}
return JsonResult.buildSuccessResult(result);
} }
@GetMapping("/bug/pool/caculate") /**
public JsonResult bugPoolCaculateFixTime() throws Exception { * 根据JIRA项目名称和项目关键字获取未解决BUG
QueryWrapper<JiraBugPool> jiraBugPoolQueryWrapper = new QueryWrapper<>(); * @param jiraProjectKey
jiraBugPoolQueryWrapper.eq("enable", 1); * @param projectName
List<JiraBugPool> jiraBugPoolList = jiraBugPoolService.list(jiraBugPoolQueryWrapper); * @return
* @throws Exception
*/
@GetMapping("/issue/list")
public JsonResult getUnsolvedByProject(@RequestParam String jiraProjectKey,
@RequestParam String projectName,
@RequestParam boolean unsolved) throws Exception {
String JQL = null;
if (!unsolved) {
JQL = "project = " + jiraProjectKey + " AND text ~ \"" + projectName + "\" ORDER BY priority DESC, updated DESC";
} else {
JQL = "project = " + jiraProjectKey + " AND resolution = Unresolved AND text ~ \"" + projectName + "\" ORDER BY priority DESC, updated DESC";
}
Iterable<Issue> issues = jiraIssueService.getIssueListByJQL(JQL);
List<Map<String, Object>> mapList = new ArrayList<>(); List<Map<String, Object>> mapList = new ArrayList<>();
for (JiraBugPool jiraBugPool : jiraBugPoolList) { for (Issue issue: issues) {
Issue issue = jiraIssueService.getJiraIssueByKey(jiraBugPool.getKey()); Map<String, Object> map = new HashMap<>();
String resolveResult = issue.getStatus().getName(); map.put("key", issue.getKey());
DateTime startDate = issue.getCreationDate(); map.put("summary", issue.getSummary());
DateTime endDate; map.put("reporter", issue.getReporter().getDisplayName());
// 如果已解决或已关闭,仅修改状态 if (issue.getAssignee() != null) {
if (resolveResult.equals("已解决") || resolveResult.equals("关闭")) { map.put("assignee", issue.getAssignee().getDisplayName());
endDate = DateTime.parse(issue.getFieldByName("已解决").getValue().toString());
} else { } else {
endDate = new DateTime(); map.put("assignee", "未分配");
} }
int duration = jiraIssueService.calculateBugFixTime(startDate, endDate); map.put("priority", issue.getPriority().getName());
Map<String, Object> map = new HashMap<>(); map.put("status", issue.getStatus().getName());
map.put("title", issue.getSummary());
map.put("持续时长", duration);
mapList.add(map); mapList.add(map);
} }
return JsonResult.buildSuccessResult(mapList); return JsonResult.buildSuccessResult(mapList);
......
package cn.qg.holmes.controller.jira;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.jira.DingRobot;
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.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/jira")
public class JiraWebhookController {
@Autowired
DingRobotService dingRobotService;
@Autowired
JiraIssueService jiraIssueService;
/**
* jira webhook
* @param request
*/
@PostMapping("/webhook")
public void jiraWebhook(HttpServletRequest request) {
try {
BufferedReader br = request.getReader();
StringBuilder jiraData = new StringBuilder();
String str = "";
while((str = br.readLine()) != null){
jiraData.append(str);
}
br.close();
dingRobotService.sendMsgToDing(String.valueOf(jiraData));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取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 pageSize 每页多少个
* @return
*/
@GetMapping("/list/robot")
public JsonResult getProjectRobotList(Integer pageNum, Integer pageSize) {
IPage<DingRobot> page = new Page<>(pageNum, pageSize);
QueryWrapper<DingRobot> dingRobotQueryWrapper = new QueryWrapper();
dingRobotQueryWrapper.orderByDesc("id");
IPage<DingRobot> projectRobotIPage = dingRobotService.page(page, dingRobotQueryWrapper);
Map<String, Object> map = new HashMap<>();
map.put("total", projectRobotIPage.getTotal());
map.put("list", projectRobotIPage.getRecords());
return JsonResult.buildSuccessResult(map);
}
/**
* 新增项目机器人
* @param dingRobot 项目机器人实体
* @return
*/
@PostMapping("/add/robot")
public JsonResult addProjectRobot(@RequestBody DingRobot dingRobot) {
if (dingRobot.getProjectName() == null) {
return JsonResult.buildErrorStateResult("项目名称不能为空!", false);
}
if (dingRobot.getDingUrl() == null) {
return JsonResult.buildErrorStateResult("钉钉url不能为空!", false);
}
return JsonResult.buildSuccessResult(dingRobotService.save(dingRobot));
}
/**
* 修改项目机器人
* @param dingRobot 项目机器人实体
* @return
*/
@PostMapping("/modify/robot")
public JsonResult editProjectRobot(@RequestBody DingRobot dingRobot) {
if (dingRobot.getId() == null) {
return JsonResult.buildErrorStateResult("id不能为空!", false);
}
if (dingRobot.getProjectName() == null) {
return JsonResult.buildErrorStateResult("项目名称不能为空!", false);
}
if (dingRobot.getDingUrl() == null) {
return JsonResult.buildErrorStateResult("钉钉url不能为空!", false);
}
return JsonResult.buildSuccessResult(dingRobotService.updateById(dingRobot));
}
/**
* 删除项目机器人
* @param projectRobotId 项目机器人实体id
* @return
*/
@GetMapping("/delete/robot")
public JsonResult deleteProjectRobot(Integer projectRobotId) {
if (dingRobotService.getById(projectRobotId) == null) {
return JsonResult.buildErrorStateResult("项目机器人不存在!", false);
}
return JsonResult.buildSuccessResult(dingRobotService.removeById(projectRobotId));
}
}
...@@ -20,6 +20,7 @@ public class Scene { ...@@ -20,6 +20,7 @@ public class Scene {
private Integer id; private Integer id;
private String name; private String name;
private Integer projectId; private Integer projectId;
private String globalParameters;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime; private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
......
...@@ -20,6 +20,7 @@ public class SceneTestcase { ...@@ -20,6 +20,7 @@ public class SceneTestcase {
private Integer id; private Integer id;
private Integer sceneId; private Integer sceneId;
private Integer interfaceId; private Integer interfaceId;
private String name;
private String preAction; private String preAction;
private String postAction; private String postAction;
private String headers; private String headers;
...@@ -36,5 +37,7 @@ public class SceneTestcase { ...@@ -36,5 +37,7 @@ public class SceneTestcase {
@TableField(exist = false) @TableField(exist = false)
private String interfaceName; private String interfaceName;
@TableField(exist = false) @TableField(exist = false)
private String interfaceUrl;
@TableField(exist = false)
private String moduleName; private String moduleName;
} }
...@@ -21,6 +21,7 @@ public class SceneTestcaseReport { ...@@ -21,6 +21,7 @@ public class SceneTestcaseReport {
private Integer sceneTestcaseId; private Integer sceneTestcaseId;
private String interfaceUrl; private String interfaceUrl;
private String interfaceName; private String interfaceName;
private String testcaseName;
private String url; private String url;
private String headers; private String headers;
private String parameters; private String parameters;
......
...@@ -7,5 +7,6 @@ import java.util.List; ...@@ -7,5 +7,6 @@ import java.util.List;
@Data @Data
public class SceneTestcaseUpdateVo { public class SceneTestcaseUpdateVo {
Integer sceneId; Integer sceneId;
String globalParameters;
List<SceneTestcase> sceneTestcaseList; List<SceneTestcase> sceneTestcaseList;
} }
...@@ -35,5 +35,7 @@ public class Testcase { ...@@ -35,5 +35,7 @@ public class Testcase {
@TableField(exist = false) @TableField(exist = false)
private String interfaceName; private String interfaceName;
@TableField(exist = false) @TableField(exist = false)
private String interfaceUrl;
@TableField(exist = false)
private String moduleName; private String moduleName;
} }
package cn.qg.holmes.entity.gitlab;
import cn.qg.holmes.entity.jira.DingRobot;
import lombok.Data;
import java.util.List;
/**
* 新增/编辑jira通知-pipeline实体
*/
@Data
public class DingRobotPipelineVo {
private DingRobot dingRobot;
private List<Pipeline> pipelineList;
}
package cn.qg.holmes.entity.gitlab;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class Pipeline {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer dingRobotId;
private String serviceName;
private String serviceBranch;
private String serviceType;
private String namespace;
private Integer enable;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
...@@ -17,6 +17,7 @@ public class DingRobot { ...@@ -17,6 +17,7 @@ public class DingRobot {
private String jiraProjectKey; private String jiraProjectKey;
private String dingUrl; private String dingUrl;
private String creator; private String creator;
private String namespace;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime; private Date createTime;
@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 SendSmokingResultVo {
private String jiraProjectKey;
private String testProjectName;
private String progress;
private Boolean result;
private String risk;
private String webhook;
}
package cn.qg.holmes.mapper.gitlab;
import cn.qg.holmes.entity.gitlab.Pipeline;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface PipelineMapper extends BaseMapper<Pipeline> {
}
...@@ -6,13 +6,15 @@ import java.util.UUID; ...@@ -6,13 +6,15 @@ import java.util.UUID;
public interface AutoUtilsService { public interface AutoUtilsService {
Map<String, String> replaceHeaders(String headers, String variables, UUID uuid); boolean extractResponse(String response, String extract, UUID uuid);
Map<String, String> replaceParameters(String parameters, String variables, UUID uuid); Map<String, Object> extractResponseNew(String response, String extract);
Map<String, String> replaceVariables(String parameters, UUID uuid); Map<String, String> replaceVariables(String parameters, UUID uuid);
boolean extractResponse(String response, String extract, UUID uuid); Map<String, String> replaceVariablesNew(String parameters, Map<String, Object> globalMap);
boolean assertResponse(String response, List<Map> validateList); boolean assertResponse(String response, List<Map> validateList);
Map<String, Object> handlePreCondition(String namespace, String preString, Map<String, Object> globalMap);
} }
package cn.qg.holmes.service.auto.impl; package cn.qg.holmes.service.auto.impl;
import cn.qg.holmes.service.auto.AutoUtilsService; import cn.qg.holmes.service.auto.AutoUtilsService;
import cn.qg.holmes.utils.HttpClientUtils;
import cn.qg.holmes.utils.RedisUtils; import cn.qg.holmes.utils.RedisUtils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPath;
...@@ -8,9 +9,12 @@ import lombok.extern.slf4j.Slf4j; ...@@ -8,9 +9,12 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* @author libo * @author libo
...@@ -24,58 +28,38 @@ public class AutoUtilsServiceImpl implements AutoUtilsService { ...@@ -24,58 +28,38 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
RedisUtils redisUtils; RedisUtils redisUtils;
/** /**
* 将请求headers中的变量替换成对应的值 * 参数替换-新
* @param headers 请求头json * @param parameters headers或者parameters
* @param variables 参数json * @param uuid 唯一标识
* @return
*/
public Map<String, String> replaceHeaders(String headers, String variables, UUID uuid) {
log.info("开始执行请求头替换!");
Map<String, String> headersMap = JSON.parseObject(headers, Map.class);
Map<String, String> varMap = JSON.parseObject(variables, Map.class);
log.info("替换之前的headers:{}", headersMap);
log.info("参数列表:{}", varMap);
for (String key: varMap.keySet()) {
String value = varMap.get(key);
headersMap.put(key, redisUtils.get(uuid + "_" + value.substring(1)).toString());
}
log.info("替换之后的headers:{}", headersMap);
return headersMap;
}
/**
* 将请求体中的变量替换成对应的值
* @param parameters 请求参数json
* @param variables 变量json
* @return 替换后的参数Map
*/ */
public Map<String, String> replaceParameters(String parameters, String variables, UUID uuid) { @Override
log.info("开始执行请求参数替换!"); public Map<String, String> replaceVariables(String parameters, UUID uuid) {
Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class); Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class);
Map<String, String> varMap = JSON.parseObject(variables, Map.class);
log.info("替换之前的参数:{}", parameterMap); log.info("替换之前的参数:{}", parameterMap);
log.info("参数列表:{}", varMap); for (String key: parameterMap.keySet()) {
for (String key: varMap.keySet()) { String value = parameterMap.get(key);
String value = varMap.get(key); if (value.startsWith("$")) {
parameterMap.put(key, redisUtils.get(uuid + "_" + value.substring(1)).toString()); parameterMap.put(key, redisUtils.get(uuid + "_" + value.substring(1)).toString());
}
} }
log.info("替换之后的参数:{}", parameterMap); log.info("替换之后的参数:{}", parameterMap);
return parameterMap; return parameterMap;
} }
/** /**
* 参数替换-新 * 新的参数替换,不再从redis里取值,而是从全局Map中取值
* @param parameters headers或者parameters * @param parameters
* @param uuid 唯一标识 * @param globalMap
* @return
*/ */
@Override @Override
public Map<String, String> replaceVariables(String parameters, UUID uuid) { public Map<String, String> replaceVariablesNew(String parameters, Map<String, Object> globalMap) {
Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class); Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class);
log.info("替换之前的参数:{}", parameterMap); log.info("替换之前的参数:{}", parameterMap);
for (String key: parameterMap.keySet()) { for (String key: parameterMap.keySet()) {
String value = parameterMap.get(key); String value = parameterMap.get(key);
if (value.startsWith("$")) { if (value.startsWith("$")) {
parameterMap.put(key, redisUtils.get(uuid + "_" + value.substring(1)).toString()); parameterMap.put(key, globalMap.get(value.substring(1)).toString());
} }
} }
log.info("替换之后的参数:{}", parameterMap); log.info("替换之后的参数:{}", parameterMap);
...@@ -94,7 +78,20 @@ public class AutoUtilsServiceImpl implements AutoUtilsService { ...@@ -94,7 +78,20 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
for (String key: extractMap.keySet()) { for (String key: extractMap.keySet()) {
String value = extractMap.get(key); String value = extractMap.get(key);
String redisKey = uuid + "_" + key; String redisKey = uuid + "_" + key;
redisUtils.set(redisKey, JsonPath.read(response, value)); String redisValue = "";
if (value.startsWith("$")) {
redisValue = JsonPath.read(response, value);
} else {
Pattern pattern = Pattern.compile(value);
Matcher matcher = pattern.matcher(response);
if (matcher.find()) {
redisValue = matcher.group(1);
} else {
return false;
}
}
// redisUtils.set(redisKey, JsonPath.read(response, value));
redisUtils.set(redisKey, redisValue);
redisUtils.expire(redisKey, 120); redisUtils.expire(redisKey, 120);
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -104,6 +101,35 @@ public class AutoUtilsServiceImpl implements AutoUtilsService { ...@@ -104,6 +101,35 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
return true; return true;
} }
@Override
public Map<String, Object> extractResponseNew(String response, String extract) {
Map<String, Object> resultMap = new HashMap<>();
try {
Map<String, String> extractMap = JSON.parseObject(extract, Map.class);
for (String key: extractMap.keySet()) {
String value = extractMap.get(key);
String extractValue = "";
// 如果以$开头,则使用JsonPath解析
if (value.startsWith("$")) {
extractValue = JsonPath.read(response, value);
} else {
Pattern pattern = Pattern.compile(value);
Matcher matcher = pattern.matcher(response);
if (matcher.find()) {
extractValue = matcher.group(1);
} else {
return null;
}
}
resultMap.put(key, extractValue);
}
return resultMap;
} catch (Exception e) {
e.printStackTrace();
return resultMap;
}
}
/** /**
* 响应断言 * 响应断言
* @return * @return
...@@ -121,6 +147,65 @@ public class AutoUtilsServiceImpl implements AutoUtilsService { ...@@ -121,6 +147,65 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
return true; return true;
} }
/**
*
* @param namespace
* @param preString
* @return
*/
@Override
public Map<String, Object> handlePreCondition(String namespace, String preString, Map<String, Object> globalMap) {
log.info("开始处理前置动作!");
Map<String, Object> resultMap = new HashMap<>();
try {
List<Map> preList = JSON.parseArray(preString, Map.class);
for (Map<String, Object> map: preList) {
String db = map.get("db").toString();
String sql = map.get("sql").toString();
String key = null;
String type = null;
if (map.get("key") != null) {
key = map.get("key").toString();
}
if (map.get("type") != null) {
type = map.get("type").toString();
}
// 确认SQL中是否需要变量替换
String regex = "(\\{\\{[A-Za-z0-9]+}})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sql);
while (matcher.find()) {
String replace = matcher.group();
// 去掉首位的{{和}}
String tempKey = replace.substring(2, replace.length() -2);
sql = sql.replace(replace, "'" + globalMap.get(tempKey).toString() + "'");
}
Map<String, String> params = new HashMap<>();
params.put("namespace", namespace);
params.put("database", db);
params.put("sql", sql);
params.put("type", type);
String url = "https://qa-platform-yxm.liangkebang.net/sql/execute";
String result = HttpClientUtils.doGet(url, params);
log.info("开始执行SQL:{}", sql);
log.info("SQL返回结果:{}", result);
// 只有select才需要加入Map
if (sql.startsWith("select") || sql.startsWith("SELECT")) {
if (type.equals("map")) {
resultMap.put(key, JsonPath.read(result, "$.data." + key));
} else if (type.equals("list")) {
resultMap.put(key, JsonPath.read(result, "$.data."));
}
}
}
log.info("前置动作获取到的值:{}", resultMap);
return resultMap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/** /**
* *
* @param comparator * @param comparator
......
...@@ -47,16 +47,41 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S ...@@ -47,16 +47,41 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
@Autowired @Autowired
SceneService sceneService; SceneService sceneService;
/**
* 执行场景用例
* @param namespace 环境
* @param sceneId 场景id
* @param batch 批次号
* @return
*/
@Override @Override
public String executeSceneTestcase(String namespace, Integer sceneId, String batch) { public String executeSceneTestcase(String namespace, Integer sceneId, String batch) {
UUID uuid = UUID.randomUUID(); QueryWrapper<SceneTestcase> queryWrapper = new QueryWrapper<>();
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("scene_id", sceneId); queryWrapper.eq("scene_id", sceneId);
queryWrapper.orderByAsc("sequence"); queryWrapper.orderByAsc("sequence");
List<SceneTestcase> sceneTestcaseList = sceneTestcaseMapper.selectList(queryWrapper); List<SceneTestcase> sceneTestcaseList = sceneTestcaseMapper.selectList(queryWrapper);
List<Map<String, Object>> resultList = new ArrayList<>(); List<Map<String, Object>> resultList = new ArrayList<>();
String globalParameters = sceneService.getById(sceneId).getGlobalParameters();
// 全局变量Map
Map<String, Object> globalMap = new HashMap<>();
if (globalParameters != null) {
globalMap.putAll(JSON.parseObject(globalParameters, Map.class));
}
for (SceneTestcase sceneTestcase: sceneTestcaseList) { for (SceneTestcase sceneTestcase: sceneTestcaseList) {
resultList.add(JSON.parseObject(sceneTestcaseExecution(namespace, sceneId, sceneTestcase.getInterfaceId(), uuid, batch), Map.class)); String preAction = sceneTestcase.getPreAction();
if (preAction != null && !preAction.isEmpty()) {
Map<String, Object> preMap = autoUtilsService.handlePreCondition(namespace, preAction, globalMap);
if (preMap != null) {
globalMap.putAll(preMap);
}
}
// resultList.add(JSON.parseObject(sceneTestcaseExecution(namespace, sceneId, sceneTestcase.getInterfaceId(), sceneTestcase.getSequence(), uuid, batch), Map.class));
Map<String, Object> tempMap = sceneTestcaseExecution(namespace, sceneId, sceneTestcase.getInterfaceId(), sceneTestcase.getSequence(), batch, globalMap);
Map<String, Object> reportMap = (Map<String, Object>) tempMap.get("report");
Map<String, Object> extractMap = (Map<String, Object>) tempMap.get("extract");
resultList.add(reportMap);
// 将解析出来的值放入全局变量Map
globalMap.putAll(extractMap);
} }
return JSON.toJSONString(resultList); return JSON.toJSONString(resultList);
} }
...@@ -71,10 +96,11 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S ...@@ -71,10 +96,11 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
return sceneTestcaseMapper.getSceneTestcaseListBySceneId(sceneId); return sceneTestcaseMapper.getSceneTestcaseListBySceneId(sceneId);
} }
public String sceneTestcaseExecution(String namespace, Integer sceneId, Integer interfaceId, UUID uuid, String batch) { public Map<String, Object> sceneTestcaseExecution(String namespace, Integer sceneId, Integer interfaceId, Integer sequence, String batch, Map<String, Object> globalMap) {
QueryWrapper queryWrapper = new QueryWrapper(); QueryWrapper<SceneTestcase> queryWrapper = new QueryWrapper();
queryWrapper.eq("scene_id", sceneId); queryWrapper.eq("scene_id", sceneId);
queryWrapper.eq("interface_id", interfaceId); queryWrapper.eq("interface_id", interfaceId);
queryWrapper.eq("sequence", sequence);
SceneTestcase sceneTestcase = sceneTestcaseMapper.selectOne(queryWrapper); SceneTestcase sceneTestcase = sceneTestcaseMapper.selectOne(queryWrapper);
Interface anInterface = interfaceService.getById(interfaceId); Interface anInterface = interfaceService.getById(interfaceId);
AutoModule autoModule = autoModuleService.getById(anInterface.getModuleId()); AutoModule autoModule = autoModuleService.getById(anInterface.getModuleId());
...@@ -90,19 +116,13 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S ...@@ -90,19 +116,13 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
String validate = sceneTestcase.getValidate(); String validate = sceneTestcase.getValidate();
Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class); Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class);
Map<String, String> headersMap = JSON.parseObject(headers, Map.class); Map<String, String> headersMap = JSON.parseObject(headers, Map.class);
// 使用变量替换headers
// if (variables != null && !variables.isEmpty() && headers != null && !headers.isEmpty()) {
// headersMap = autoUtilsService.replaceHeaders(headers, variables, uuid);
// }
if (headers != null && !headers.isEmpty()) { if (headers != null && !headers.isEmpty()) {
headersMap = autoUtilsService.replaceVariables(headers, uuid); // headersMap = autoUtilsService.replaceVariables(headers, uuid);
headersMap = autoUtilsService.replaceVariablesNew(headers, globalMap);
} }
// 使用变量替换参数
// if (variables != null && !variables.isEmpty() && parameters != null && !parameters.isEmpty()) {
// parameterMap = autoUtilsService.replaceParameters(parameters, variables, uuid);
// }
if (parameters != null && !parameters.isEmpty()) { if (parameters != null && !parameters.isEmpty()) {
parameterMap = autoUtilsService.replaceVariables(parameters, uuid); // parameterMap = autoUtilsService.replaceVariables(parameters, uuid);
parameterMap = autoUtilsService.replaceVariablesNew(parameters, globalMap);
} }
// 创建断言列表 // 创建断言列表
List<Map> validateList = new ArrayList<>(); List<Map> validateList = new ArrayList<>();
...@@ -136,17 +156,23 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S ...@@ -136,17 +156,23 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
assertResult = autoUtilsService.assertResponse(response, validateList); assertResult = autoUtilsService.assertResponse(response, validateList);
} }
// 解析响应 // 解析响应
Map<String, Object> extractMap = new HashMap<>();
if (extract != null && !extract.isEmpty()) { if (extract != null && !extract.isEmpty()) {
autoUtilsService.extractResponse(response, extract, uuid); // autoUtilsService.extractResponse(response, extract, uuid);
extractMap = autoUtilsService.extractResponseNew(response, extract);
}
Map<String, Object> reportMap = new HashMap<>();
reportMap.put("url", url);
reportMap.put("name", interfaceName);
reportMap.put("headers", headersMap);
reportMap.put("parameters", parameterMap);
reportMap.put("assertResult", assertResult);
reportMap.put("elapsedTime", elapsedTime);
try {
reportMap.put("response", JSON.parseObject(response, Map.class));
} catch (Exception e) {
reportMap.put("response", response);
} }
Map<String, Object> map = new HashMap<>();
map.put("url", url);
map.put("name", interfaceName);
map.put("headers", headersMap);
map.put("parameters", parameterMap);
map.put("assertResult", assertResult);
map.put("response", JSON.parseObject(response, Map.class));
map.put("elapsedTime", elapsedTime);
// 插入测试报告 // 插入测试报告
SceneTestcaseReport sceneTestcaseReport = new SceneTestcaseReport(); SceneTestcaseReport sceneTestcaseReport = new SceneTestcaseReport();
...@@ -155,6 +181,7 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S ...@@ -155,6 +181,7 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
sceneTestcaseReport.setSequence(sceneTestcase.getSequence()); sceneTestcaseReport.setSequence(sceneTestcase.getSequence());
sceneTestcaseReport.setInterfaceUrl(anInterface.getUrl()); sceneTestcaseReport.setInterfaceUrl(anInterface.getUrl());
sceneTestcaseReport.setInterfaceName(anInterface.getName()); sceneTestcaseReport.setInterfaceName(anInterface.getName());
sceneTestcaseReport.setTestcaseName(sceneTestcase.getName());
sceneTestcaseReport.setUrl(url); sceneTestcaseReport.setUrl(url);
sceneTestcaseReport.setHeaders(JSON.toJSONString(headersMap)); sceneTestcaseReport.setHeaders(JSON.toJSONString(headersMap));
sceneTestcaseReport.setParameters(JSON.toJSONString(parameterMap)); sceneTestcaseReport.setParameters(JSON.toJSONString(parameterMap));
...@@ -171,7 +198,10 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S ...@@ -171,7 +198,10 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
sceneTestcaseReport.setNamespace(namespace); sceneTestcaseReport.setNamespace(namespace);
log.info("保存测试报告:{}", sceneTestcaseReport); log.info("保存测试报告:{}", sceneTestcaseReport);
sceneTestcaseReportService.save(sceneTestcaseReport); sceneTestcaseReportService.save(sceneTestcaseReport);
return JSON.toJSONString(map); Map<String, Object> resultMap = new HashMap<>();
resultMap.put("report", reportMap);
resultMap.put("extract", extractMap);
return resultMap;
} }
} }
package cn.qg.holmes.service.gitlab;
import cn.qg.holmes.entity.gitlab.Pipeline;
import com.baomidou.mybatisplus.extension.service.IService;
public interface PipelineService extends IService<Pipeline> {
void buildPipelineJob(String gitlabData);
}
package cn.qg.holmes.service.gitlab.impl;
import cn.qg.holmes.entity.gitlab.Pipeline;
import cn.qg.holmes.mapper.gitlab.PipelineMapper;
import cn.qg.holmes.service.gitlab.PipelineService;
import cn.qg.holmes.service.jira.DingRobotService;
import cn.qg.holmes.utils.DingdingUtils;
import cn.qg.holmes.utils.JenkinsService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jayway.jsonpath.JsonPath;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
@Slf4j
@Service
public class PipelineServiceImpl extends ServiceImpl<PipelineMapper, Pipeline> implements PipelineService {
@Autowired
PipelineMapper pipelineMapper;
@Autowired
JenkinsService jenkinsService;
@Autowired
DingRobotService dingRobotService;
/**
* 构建pipeline
* @param gitlabData gitlab发送过来的推送事件
*/
@Override
public void buildPipelineJob(String gitlabData) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String projectName = JsonPath.read(gitlabData, "$.project.name");
String branch = JsonPath.read(gitlabData, "$.ref").toString().substring(11);
Integer totalCommitCount = JsonPath.read(gitlabData, "$.total_commits_count");
if (totalCommitCount.equals(0)) {
return;
}
String message = JsonPath.read(gitlabData, "$.commits[-1].message");
String author = JsonPath.read(gitlabData, "$.user_username");
// push event给过来的日期为带T的,需要进行转换
String commitDate = simpleDateFormat.format(DateTime.parse(JsonPath.read(gitlabData, "$.commits[-1].timestamp")).toDate());
QueryWrapper<Pipeline> pipelineQueryWrapper = new QueryWrapper<>();
pipelineQueryWrapper.eq("service_name", projectName);
pipelineQueryWrapper.eq("service_branch", branch);
Pipeline pipeline = pipelineMapper.selectOne(pipelineQueryWrapper);
if (pipeline != null) {
if (pipeline.getEnable() == 1) {
log.info("pipeline中找到对应项目,且项目是启动状态,开始构建:{}", pipeline.toString());
Integer buildNum = jenkinsService.buildJenkinsJob(pipeline.getServiceType(), projectName, branch, pipeline.getNamespace());
String markdown = DingdingUtils.buildPipelineMarkdownMsg(projectName, branch, pipeline.getServiceType(), author, message, commitDate, pipeline.getNamespace(), buildNum.toString());
DingdingUtils.sendToDingding(markdown, dingRobotService.getById(pipeline.getDingRobotId()).getDingUrl());
} else {
log.info("pipeline中找到项目,但是项目状态为不启用,因此不构建!");
}
} else {
log.info("pipeline中未找到该项目相关信息,不触发自动构建!");
}
}
}
...@@ -14,6 +14,6 @@ public interface JiraIssueService { ...@@ -14,6 +14,6 @@ public interface JiraIssueService {
Integer calculateBugFixTime(DateTime startDate, DateTime endDate); Integer calculateBugFixTime(DateTime startDate, DateTime endDate);
Issue getJiraIssueByKey(String key) throws Exception; Issue getJiraIssueByKey(String key);
} }
...@@ -31,7 +31,12 @@ public class DingRobotServiceImpl extends ServiceImpl<DingRobotMapper, DingRobot ...@@ -31,7 +31,12 @@ public class DingRobotServiceImpl extends ServiceImpl<DingRobotMapper, DingRobot
String webhookEvent = JsonPath.read(jiraData, "$.webhookEvent"); String webhookEvent = JsonPath.read(jiraData, "$.webhookEvent");
if (StringUtils.equals(webhookEvent, "jira:issue_created")) { if (StringUtils.equals(webhookEvent, "jira:issue_created")) {
String creator = JsonPath.read(jiraData, "$.issue.fields.creator.displayName"); String creator = JsonPath.read(jiraData, "$.issue.fields.creator.displayName");
String assignee = JsonPath.read(jiraData, "$.issue.fields.assignee.displayName"); String assignee = "";
if (JsonPath.read(jiraData, "$.issue.fields.assignee") == null) {
assignee = "未分配";
} else {
assignee = JsonPath.read(jiraData, "$.issue.fields.assignee.displayName");
}
String key = JsonPath.read(jiraData, "$.issue.key"); String key = JsonPath.read(jiraData, "$.issue.key");
String summary = JsonPath.read(jiraData, "$.issue.fields.summary"); String summary = JsonPath.read(jiraData, "$.issue.fields.summary");
String priority = JsonPath.read(jiraData, "$.issue.fields.priority.name"); String priority = JsonPath.read(jiraData, "$.issue.fields.priority.name");
...@@ -45,18 +50,21 @@ public class DingRobotServiceImpl extends ServiceImpl<DingRobotMapper, DingRobot ...@@ -45,18 +50,21 @@ public class DingRobotServiceImpl extends ServiceImpl<DingRobotMapper, DingRobot
break; break;
} }
} }
// 首次提交的BUG放入bug池子 // 只有创建了dingRobot的项目的BUG才会被放到BUG池子里
JiraBugPool jiraBugPool = new JiraBugPool(); if (robotUrl != null) {
jiraBugPool.setKey(key); // 首次提交的BUG放入bug池子
jiraBugPool.setSummary(summary); JiraBugPool jiraBugPool = new JiraBugPool();
jiraBugPool.setPriority(priority); jiraBugPool.setKey(key);
jiraBugPool.setReporter(creator); jiraBugPool.setSummary(summary);
jiraBugPool.setAssignee(assignee); jiraBugPool.setPriority(priority);
jiraBugPool.setUrl("http://jira2.quantgroup.cn/browse/" + key); jiraBugPool.setReporter(creator);
jiraBugPool.setDingUrl(robotUrl); jiraBugPool.setAssignee(assignee);
jiraBugPoolService.save(jiraBugPool); jiraBugPool.setUrl("http://jira2.quantgroup.cn/browse/" + key);
jiraBugPool.setDingUrl(robotUrl);
jiraBugPoolService.save(jiraBugPool);
}
if (robotUrl != null) { if (robotUrl != null) {
String markdownMsg = DingdingUtils.buildMarkdownMsg(key, summary, creator, assignee, priority, module); String markdownMsg = DingdingUtils.buildBugCommitMarkdownMsg(key, summary, creator, assignee, priority, module);
return DingdingUtils.sendToDingding(markdownMsg, robotUrl); return DingdingUtils.sendToDingding(markdownMsg, robotUrl);
} }
} }
......
...@@ -76,8 +76,14 @@ public class JiraIssueServiceImpl implements JiraIssueService { ...@@ -76,8 +76,14 @@ public class JiraIssueServiceImpl implements JiraIssueService {
} }
@Override @Override
public Issue getJiraIssueByKey(String key) throws Exception { public Issue getJiraIssueByKey(String key) {
return jiraRestClient.getIssueClient().getIssue(key).get(); try {
Issue issue = jiraRestClient.getIssueClient().getIssue(key).get();
return issue;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} }
/** /**
......
...@@ -13,7 +13,6 @@ import org.springframework.beans.factory.annotation.Value; ...@@ -13,7 +13,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
...@@ -55,7 +54,7 @@ public class JiraToDingding { ...@@ -55,7 +54,7 @@ public class JiraToDingding {
* bug池里BUG循环 * bug池里BUG循环
* @throws Exception * @throws Exception
*/ */
@Scheduled(cron = "0 0 10-20 ? * 2-6") @Scheduled(cron = "0 0 10-20 ? * MON-FRI")
public void cycleJiraBugPool() throws Exception { public void cycleJiraBugPool() throws Exception {
if (taskDebug.equals("true")) { if (taskDebug.equals("true")) {
log.info("开始执行jira bug pool定时任务!"); log.info("开始执行jira bug pool定时任务!");
...@@ -64,22 +63,26 @@ public class JiraToDingding { ...@@ -64,22 +63,26 @@ public class JiraToDingding {
List<JiraBugPool> jiraBugPoolList = jiraBugPoolService.list(jiraBugPoolQueryWrapper); List<JiraBugPool> jiraBugPoolList = jiraBugPoolService.list(jiraBugPoolQueryWrapper);
for (JiraBugPool jiraBugPool: jiraBugPoolList) { for (JiraBugPool jiraBugPool: jiraBugPoolList) {
Issue issue = jiraIssueService.getJiraIssueByKey(jiraBugPool.getKey()); Issue issue = jiraIssueService.getJiraIssueByKey(jiraBugPool.getKey());
String resolveResult = issue.getStatus().getName(); if (issue != null) {
// 如果已解决或已关闭,仅修改状态 String resolveResult = issue.getStatus().getName();
if (resolveResult.equals("已解决") || resolveResult.equals("关闭")) { // 如果已解决或已关闭,仅修改状态
jiraBugPool.setEnable(0); if (resolveResult.equals("已解决") || resolveResult.equals("关闭")) {
// 更新状态 jiraBugPool.setEnable(0);
jiraBugPoolService.saveOrUpdate(jiraBugPool); // 更新状态
} else { jiraBugPoolService.saveOrUpdate(jiraBugPool);
DateTime startDate = issue.getCreationDate(); } else {
DateTime curDate = new DateTime(); DateTime startDate = issue.getCreationDate();
int duration = jiraIssueService.calculateBugFixTime(startDate, curDate); DateTime curDate = new DateTime();
log.info("{} BUG持续时间:{}小时", issue.getKey(), duration); int duration = jiraIssueService.calculateBugFixTime(startDate, curDate);
// DingdingUtils.sendToDingding(DingdingUtils.buildBugFixRemindMsg(issue), jiraBugPool.getDingUrl()); log.info("{} BUG持续时间:{}小时", issue.getKey(), duration);
// 如果已超过4个小时,则发送钉钉通知 // 如果已超过4个小时,则发送钉钉通知
if (duration >= 4) { if (duration >= 4) {
DingdingUtils.sendToDingding(DingdingUtils.buildBugFixRemindMsg(issue, duration), "https://oapi.dingtalk.com/robot/send?access_token=835663338d638e40daaf3ab358af741ef0680a826a962c91bedc53b149d85ee1"); DingdingUtils.sendToDingding(DingdingUtils.buildBugFixRemindMsg(issue, duration), jiraBugPool.getDingUrl());
}
} }
} else {
log.info("JIRA上未找到该issue,将BUG: {} 置为无效", jiraBugPool.getKey());
jiraBugPool.setEnable(0);
} }
} }
} }
......
...@@ -3,14 +3,27 @@ package cn.qg.holmes.utils; ...@@ -3,14 +3,27 @@ package cn.qg.holmes.utils;
import com.alibaba.fastjson.JSON; 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 org.joda.time.DateTime;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 钉钉发送消息类
* @author libo
*/
@Slf4j @Slf4j
public class DingdingUtils { public class DingdingUtils {
/**
* 发送钉钉消息基本方法
* @param jsonString 发送的json字符串
* @param webhook 钉钉webhook
* @return 是否发送成功,true/false
*/
public static boolean sendToDingding(String jsonString, String webhook) { public static boolean sendToDingding(String jsonString, String webhook) {
Map<String, String> headers = new HashMap<>(); Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json; charset=utf-8"); headers.put("Content-Type", "application/json; charset=utf-8");
...@@ -20,39 +33,59 @@ public class DingdingUtils { ...@@ -20,39 +33,59 @@ public class DingdingUtils {
return resultMap.get("errmsg").equals("ok"); return resultMap.get("errmsg").equals("ok");
} }
public static String buildMarkdownMsg(String key, String summary, String creator, String assignee, String priority, String module) { /**
* 构建markdown消息基础类
* @param title 标题
* @param content 内容
* @param atAll 是否at所有人
* @return markdown消息的json字符串
*/
public static String buildMarkdownMsg(String title, String content, boolean atAll) {
Map<String, Object> markdown = new HashMap<>(); Map<String, Object> markdown = new HashMap<>();
Map<String, String> content = new HashMap<>(); Map<String, String> contentMap = new HashMap<>();
Map<String, Object> atMap = new HashMap<>();
atMap.put("isAtAll", atAll);
markdown.put("at", atMap);
markdown.put("msgtype", "markdown"); markdown.put("msgtype", "markdown");
String title = creator + "提交了BUG:" + key; contentMap.put("title", title);
contentMap.put("text", content);
markdown.put("markdown", contentMap);
return JSON.toJSONString(markdown);
}
/**
* 构建BUG刚提交时,发送给钉钉的markdown消息
* @param key jira issue key
* @param summary 标题
* @param creator 创建人
* @param assignee 经办人
* @param priority 优先级
* @param module 模块
* @return json字符串类型的markdown消息
*/
public static String buildBugCommitMarkdownMsg(String key, String summary, String creator, String assignee, String priority, String module) {
String title = "测试提交了BUG:" + key;
String issueUrl = "http://jira2.quantgroup.cn/browse/" + key; String issueUrl = "http://jira2.quantgroup.cn/browse/" + key;
content.put("title", title); String content = creator + "提交了BUG:" + key + "\n\n";
content.put("text", "#### " + title + "\n" content += "概要:[" + summary + "](" + issueUrl + ")"+ "\n\n"
+ "#### 概要:[" + summary + "](" + issueUrl + ")"+ "\n"
+ "- 优先级:" + priority + "\n" + "- 优先级:" + priority + "\n"
+ "- 模块:" + module + "\n" + "- 模块:" + module + "\n"
+ "- 经办人:" + assignee); + "- 经办人:" + assignee;
markdown.put("markdown", content); return buildMarkdownMsg(title, content, true);
return JSON.toJSONString(markdown);
} }
/** /**
* for 数据工单
* 根据issueList构建未解决issueList的markdown格式 * 根据issueList构建未解决issueList的markdown格式
* @param issues Issue的迭代器 * @param issues Issue的迭代器
* @return * @return
*/ */
public static String buildMarkdownMsgForUnsolvedIssueList(Iterable<Issue> issues) { public static String buildMarkdownMsgForUnsolvedIssueList(Iterable<Issue> issues) {
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<>(); List<Issue> issueList = new ArrayList<>();
for (Issue issue: issues) { for (Issue issue: issues) {
issueList.add(issue); issueList.add(issue);
} }
markdown.put("msgtype", "markdown"); String title = "今日剩余未解决BUG统计";
contentMap.put("title", "今日剩余未解决BUG统计");
String content = "#### 今日剩余未解决BUG数:" + issueList.size() + "\n"; String content = "#### 今日剩余未解决BUG数:" + issueList.size() + "\n";
int count = 0; int count = 0;
for (Issue issue: issueList) { for (Issue issue: issueList) {
...@@ -63,25 +96,24 @@ public class DingdingUtils { ...@@ -63,25 +96,24 @@ public class DingdingUtils {
content = content + "- 状态:" + issue.getStatus().getName() + "\n"; content = content + "- 状态:" + issue.getStatus().getName() + "\n";
content = content + "- 经办人:" + issue.getAssignee().getDisplayName() + "\n\n"; content = content + "- 经办人:" + issue.getAssignee().getDisplayName() + "\n\n";
} }
contentMap.put("text", content); return buildMarkdownMsg(title, content, true);
markdown.put("markdown", contentMap);
return JSON.toJSONString(markdown);
} }
/**
* 构建测试进度的markdown消息
* @param issues issue迭代器
* @param progress 测试进度
* @param risk 风险点
* @return 测试进度markdown消息的json字符串
*/
public static String buildTestScheduleMarkdownMsg(Iterable<Issue> issues, String progress, String risk) { 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<>(); List<Issue> issueList = new ArrayList<>();
for (Issue issue: issues) { for (Issue issue: issues) {
issueList.add(issue); issueList.add(issue);
} }
markdown.put("msgtype", "markdown");
Date date=new Date(); Date date=new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd"); DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
contentMap.put("title", format.format(date) + "今日测试进度汇报"); String title = format.format(date) + "今日测试进度汇报";
String content = format.format(date) + "\n\n"; String content = format.format(date) + "\n\n";
content += "今日测试进度:" + progress + " \n\n"; content += "今日测试进度:" + progress + " \n\n";
content = content + "剩余未解决BUG列表:" + "\n\n"; content = content + "剩余未解决BUG列表:" + "\n\n";
...@@ -95,14 +127,23 @@ public class DingdingUtils { ...@@ -95,14 +127,23 @@ public class DingdingUtils {
content = content + count + "、[" + issue.getSummary().replace("\"", "") + "](" + issueUrl + ")\n"; content = content + count + "、[" + issue.getSummary().replace("\"", "") + "](" + issueUrl + ")\n";
content = content + "- 优先级:" + issue.getPriority().getName() + "\n"; content = content + "- 优先级:" + issue.getPriority().getName() + "\n";
content = content + "- 状态:" + issue.getStatus().getName() + "\n"; content = content + "- 状态:" + issue.getStatus().getName() + "\n";
content = content + "- 经办人:" + issue.getAssignee().getDisplayName() + "\n\n"; String assignee = "";
if (issue.getAssignee() == null) {
assignee = "未分配";
} else {
assignee = issue.getAssignee().getDisplayName();
}
content = content + "- 经办人:" + assignee + "\n\n";
} }
if (risk != null && !risk.isEmpty()) { if (risk != null && !risk.isEmpty()) {
content = content + "**风险:" + risk + "**\n"; content += "**风险:**\n\n";
List<String> riskList = Arrays.asList(risk.split("\n"));
for (String str: riskList) {
content += "**" + str + "**\n\n";
}
// content = content + "**风险:" + risk + "**\n";
} }
contentMap.put("text", content); return buildMarkdownMsg(title, content, true);
markdown.put("markdown", contentMap);
return JSON.toJSONString(markdown);
} }
/** /**
...@@ -118,26 +159,100 @@ public class DingdingUtils { ...@@ -118,26 +159,100 @@ public class DingdingUtils {
if (elapsed >= 8) { if (elapsed >= 8) {
duration = (elapsed / 8) + "天"; duration = (elapsed / 8) + "天";
} }
Map<String, Object> markdown = new HashMap<>(); String title = "BUG修复提醒";
Map<String, String> contentMap = new HashMap<>(); String content = issue.getAssignee().getDisplayName() + "同学,你有一个BUG已经超过" + duration + "未解决,测试同学等得花儿都谢啦,麻烦赶紧修复哦!\n\n";
Map<String, Object> atMap = new HashMap<>();
atMap.put("isAtAll", true);
markdown.put("at", atMap);
markdown.put("msgtype", "markdown");
contentMap.put("title", "BUG修复提醒");
String content = issue.getAssignee().getDisplayName() + "同学,你有一个BUG已经超过" + duration + "未解决,请多注意哦!\n\n";
String bugUrl = "http://jira2.quantgroup.cn/browse/" + issue.getKey(); String bugUrl = "http://jira2.quantgroup.cn/browse/" + issue.getKey();
content += "BUG具体信息:\n\n"; content += "BUG具体信息:\n\n";
content += "- 标题:[" + issue.getSummary().replace("\"", "") + "](" + bugUrl + ")\n"; content += "- 标题:[" + issue.getSummary().replace("\"", "") + "](" + bugUrl + ")\n";
content += "- 优先级:" + issue.getPriority().getName() + "\n"; content += "- 优先级:" + issue.getPriority().getName() + "\n";
content += "- 经办人:" + issue.getAssignee().getDisplayName() + "\n\n"; content += "- 经办人:" + issue.getAssignee().getDisplayName() + "\n\n";
contentMap.put("text", content); return buildMarkdownMsg(title, content, true);
markdown.put("markdown", contentMap); }
return JSON.toJSONString(markdown);
/**
* 构建pipeline钉钉消息
* @param serviceName 服务名
* @param serviceBranch 分支
* @param creator 创建人
* @param commitMsg 提交信息
* @param date 日期
* @param namespace 环境
* @return
*/
public static String buildPipelineMarkdownMsg(String serviceName, String serviceBranch, String serviceType,
String creator, String commitMsg, String date, String namespace, String buildNum) {
String title = "测试环境自动构建提醒";
String content = "> 项目名称:" + serviceName + "\n\n"
+ "> 分支名称:" + serviceBranch + "\n\n"
+ "> 部署空间:" + namespace + "\n\n"
+ "> 触发同学:" + creator + "\n\n"
+ "> 触发信息:" + commitMsg + "\n\n"
+ "> 触发时间:" + date + "\n\n"
+ "[查看详情](" + "http://172.29.1.15:8080/view/TKE/job/" + "tke-" + serviceType + "/" + buildNum + "/console" + ")";
return buildMarkdownMsg(title, content, false);
}
/**
* 构建冒烟测试结果的钉钉消息
* @param issues 未解决BUG列表
* @param result 冒烟结果,true-冒烟测试通过,false-冒烟测试未通过
* @param risk 风险点
* @return
*/
public static String buildSmokingResultMarkdownMsg(Iterable<Issue> issues, boolean result, String risk) {
String title = "";
String content = "";
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String today = format.format(new Date());
content = today + "\n\n";
if (result) {
title = "冒烟测试通过!";
content += "冒烟测试结果:✅\n\n亲爱的小伙伴们,经过冒烟测试,您的项目可以正式进入测试阶段,感谢您辛苦的努力,后面的bug还请多多支持呀!\n\n";
} else {
title = "冒烟测试未通过!";
content += "冒烟测试结果:❌\n\n亲爱的小伙伴们,经过冒烟测试,您的项目无法正式进入测试阶段。因为有严重问题阻塞流程,请尽快修复后再次提测。由此耽误的时间算做您开发改bug的时间喔,测试时间会顺延到冒烟测试通过后的时间!\n\n";
}
content += "冒烟测试BUG列表:\n\n";
int count = 0;
for (Issue issue: issues) {
count = 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";
String assignee = "";
if (issue.getAssignee() == null) {
assignee = "未分配";
} else {
assignee = issue.getAssignee().getDisplayName();
}
content = content + "- 经办人:" + assignee + "\n\n";
}
if (risk != null) {
content += "风险:" + risk;
}
return buildMarkdownMsg(title, content, true);
} }
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");
// String markdown = buildPipelineMarkdownMsg("holmes", "master", "bo.li", "测试", "2021-06-03 14:59:45", "fe");
// sendToDingding(markdown, "https://oapi.dingtalk.com/robot/send?access_token=835663338d638e40daaf3ab358af741ef0680a826a962c91bedc53b149d85ee1"); // sendToDingding(markdown, "https://oapi.dingtalk.com/robot/send?access_token=835663338d638e40daaf3ab358af741ef0680a826a962c91bedc53b149d85ee1");
// String str = "2021-06-03T09:23:00Z";
// SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// String commitDate = simpleDateFormat.format(DateTime.parse(str).toDate());
// System.out.println(commitDate);
String model = "(\\{\\{[A-Za-z0-9]+}})";
String sql = "select * from vcc_talos.risk_record where uuid={{uuid}} and userId={{userId}}";
Pattern pattern = Pattern.compile(model);
Matcher matcher = pattern.matcher(sql);
while (matcher.find()) {
String replace = matcher.group();
// 去掉首位的{{和}}
String tempKey = replace.substring(2, replace.length() -2);
sql = sql.replace(replace, "'" + "1234" + "'");
}
System.out.println(sql);
} }
} }
package cn.qg.holmes.utils;
import org.gitlab.api.GitlabAPI;
import org.gitlab.api.models.GitlabBranch;
import org.gitlab.api.models.GitlabProject;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GitlabService {
private static final String URL = "http://git.quantgroup.cn/";
private static final String TOKEN = "owKJZwenxNaypTAz4Zcd";
private GitlabAPI gitlabAPI;
public GitlabService() {
try {
gitlabAPI = GitlabAPI.connect(URL, TOKEN);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取所有的项目
* @return
*/
public List<Map<String, Object>> getProjectList() {
List<GitlabProject> gitlabProjectList = gitlabAPI.getProjects();
List<Map<String, Object>> projectMapList = new ArrayList<>();
for (GitlabProject gitlabProject: gitlabProjectList) {
Map<String, Object> map = new HashMap<>();
map.put("id", gitlabProject.getId());
map.put("name", gitlabProject.getName());
projectMapList.add(map);
}
return projectMapList;
}
public List<String> getBranchesByProjectName(String projectName) {
List<Map<String, Object>> projectList = getProjectList();
Integer projectId = null;
for (Map<String, Object> map: projectList) {
if (map.get("name").toString().equals(projectName)) {
projectId = (Integer) map.get("id");
}
}
List<GitlabBranch> gitlabBranchList = gitlabAPI.getBranches(projectId);
List<String> branches = new ArrayList<>();
for (GitlabBranch gitlabBranch: gitlabBranchList) {
branches.add(gitlabBranch.getName());
}
return branches;
}
public static void main(String[] args) {
GitlabService gitlabService = new GitlabService();
List<String> branches = gitlabService.getBranchesByProjectName("holmes");
System.out.println(branches);
}
}
package cn.qg.holmes.utils;
import com.offbytwo.jenkins.JenkinsServer;
import com.offbytwo.jenkins.client.JenkinsHttpClient;
import com.offbytwo.jenkins.model.Build;
import com.offbytwo.jenkins.model.Job;
import com.offbytwo.jenkins.model.JobWithDetails;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Jenkins 相关操作工具类
* @author libo
*/
@Component
public class JenkinsService {
// Jenkins 对象
private JenkinsServer jenkinsServer;
// http 客户端对象
private JenkinsHttpClient jenkinsHttpClient;
// 连接 Jenkins 需要设置的信息
static final String JENKINS_URL = "http://172.29.1.15:8080/";
static final String JENKINS_USERNAME = "qahome";
static final String JENKINS_PASSWORD = "Quantgroup123";
/**
* 构造方法中调用连接 Jenkins 方法
*/
public JenkinsService() {
// 连接 Jenkins
try {
jenkinsServer = new JenkinsServer(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
/**
* 构建jenkins job
* @param type 服务类型:java/node/ui
* @param project 项目名
* @param branch 分支名
* @param namespace 部署的环境
* @return
*/
public int buildJenkinsJob(String type, String project, String branch, String namespace) {
Map<String, String> buildParams = new HashMap<>();
buildParams.put("GIT_REPO", project);
buildParams.put("BRANCH_NAME", branch);
buildParams.put("DEPLOY", "true");
buildParams.put("NAMESPACE", namespace);
try {
jenkinsServer.getJob("tke-" + type).build(buildParams);
Build build = jenkinsServer.getJob("tke-" + type).getLastBuild();
return build.getNumber() + 1;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 根据job名称获取job信息
*/
public JobWithDetails getJobInfoByName(String jobName) {
try {
JobWithDetails job = jenkinsServer.getJob(jobName);
return job;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取job列表
* @return
*/
public List<Map<String, String>> getJobList() {
try {
Map<String, Job> jobs = jenkinsServer.getJobs();
List<Map<String, String>> jobList = new ArrayList<>();
for (Job job:jobs.values()){
Map<String, String> map = new HashMap<>();
map.put("value", job.getName());
map.put("label", job.getName());
jobList.add(map);
}
return jobList;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取Job Build列表
*/
public List<Build> getJobBuildList(String jobName, Integer num) {
try {
// 获取 Job 信息
JobWithDetails job = jenkinsServer.getJob(jobName);
// 获取全部 Build 信息
Build lastBuild = job.getLastBuild();
int lastBuildNumber = lastBuild.getNumber();
List<Build> buildList = new ArrayList<>();
for (int i = lastBuildNumber; i > lastBuildNumber - num; i--) {
Build tempBuild = job.getBuildByNumber(i);
if (tempBuild == null) {
return buildList;
} else {
buildList.add(job.getBuildByNumber(i));
}
}
return buildList;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 根据参数获取对应的build
*/
public List<Build> getJobBuildList(String jobName, Integer num, String project) {
try {
// 获取 Job 信息
JobWithDetails job = jenkinsServer.getJob(jobName);
int lastBuildNumber = job.getLastBuild().getNumber();
List<Build> buildList = new ArrayList<>();
int caculator = 0;
while (buildList.size() != num) {
Build build = job.getBuildByNumber(lastBuildNumber - caculator);
if (build == null) {
return buildList;
}
if (build.details().getParameters().get("GIT_REPO").equals(project)) {
buildList.add(build);
}
caculator += 1;
}
return buildList;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) throws IOException {
JenkinsService jenkinsApi = new JenkinsService();
// List<Build> buildList = jenkinsApi.getJobBuildList("tke-java", 1, "kdsp");
// List<String> userList = new ArrayList<>();
// for (Build build: buildList) {
// System.out.println(build.details().getParameters().get("BRANCH_NAME"));
// System.out.println(build.details().getParameters().get("NAMESPACE"));
// System.out.println(build.details().getCauses().get(0).getUserName());
// userList.add(build.details().getCauses().get(0).getUserName());
// BuildResult buildResult = build.details().getResult();
// System.out.println(buildResult);
// }
// System.out.println(userList.size());
System.out.println(jenkinsApi.buildJenkinsJob("ui", "qa-platform-ui", "xiaotong", "fe"));
}
}
...@@ -3,7 +3,12 @@ ...@@ -3,7 +3,12 @@
<mapper namespace="cn.qg.holmes.mapper.auto.SceneTestcaseMapper"> <mapper namespace="cn.qg.holmes.mapper.auto.SceneTestcaseMapper">
<select id="getSceneTestcaseListBySceneId" resultType="cn.qg.holmes.entity.auto.SceneTestcase"> <select id="getSceneTestcaseListBySceneId" resultType="cn.qg.holmes.entity.auto.SceneTestcase">
select stc.*,it.`name`,sc.`name`,am.`name` from `scene_testcase` as stc select stc.*,
it.`name` as interfaceName,
it.`url` as interfaceUrl,
sc.`name` as sceneName,
am.`name` as moduleName
from `scene_testcase` as stc
INNER JOIN `interface` as it ON stc.`interface_id` = it.`id` INNER JOIN `interface` as it ON stc.`interface_id` = it.`id`
INNER JOIN `scene` as sc ON stc.`scene_id` = sc.`id` INNER JOIN `scene` as sc ON stc.`scene_id` = sc.`id`
INNER JOIN `auto_module` as am ON it.`module_id` = am.id INNER JOIN `auto_module` as am ON it.`module_id` = am.id
......
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
<mapper namespace="cn.qg.holmes.mapper.auto.TestcaseMapper"> <mapper namespace="cn.qg.holmes.mapper.auto.TestcaseMapper">
<select id="getTestcaseList" resultType="cn.qg.holmes.entity.auto.Testcase"> <select id="getTestcaseList" resultType="cn.qg.holmes.entity.auto.Testcase">
SELECT tc.*, am.`name` as moduleName, it.`name` as interfaceName SELECT tc.*,
am.`name` as moduleName,
it.`name` as interfaceName,
it.`url` as interfaceUrl
FROM `testcase` as tc FROM `testcase` as tc
INNER JOIN `auto_module` as am ON tc.`module_id` = am.`id` INNER JOIN `auto_module` as am ON tc.`module_id` = am.`id`
INNER JOIN `interface` as it ON tc.`interface_id` = it.`id` INNER JOIN `interface` as it ON tc.`interface_id` = it.`id`
......
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