feat(测试跟踪): 缺陷管理MS同步禅道附件
--story=1008034 --user=宋昌昌 【Bug转需求】[缺陷管理]-github#9580-jira集成,缺陷模版使用 jira 缺陷模版,字段没有同步全 https://www.tapd.cn/55049933/s/1216936
This commit is contained in:
parent
f3a134c16f
commit
018af2ff32
|
@ -4,15 +4,9 @@ import com.alibaba.fastjson.JSON;
|
|||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.base.domain.IssuesExample;
|
||||
import io.metersphere.base.domain.IssuesWithBLOBs;
|
||||
import io.metersphere.base.domain.Project;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.domain.ext.CustomFieldResource;
|
||||
import io.metersphere.commons.constants.AttachmentSyncType;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.constants.IssuesStatus;
|
||||
import io.metersphere.commons.constants.ZentaoIssuePlatformStatus;
|
||||
import io.metersphere.commons.constants.*;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
|
@ -25,8 +19,10 @@ import io.metersphere.track.issue.domain.zentao.AddIssueResponse;
|
|||
import io.metersphere.track.issue.domain.zentao.GetIssueResponse;
|
||||
import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
|
||||
import io.metersphere.track.issue.domain.zentao.ZentaoConfig;
|
||||
import io.metersphere.track.request.attachment.AttachmentRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
@ -34,7 +30,6 @@ import org.springframework.http.HttpEntity;
|
|||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
@ -47,12 +42,13 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ZentaoPlatform extends AbstractIssuePlatform {
|
||||
protected final ZentaoClient zentaoClient;
|
||||
|
||||
protected final String[] imgArray = {
|
||||
"bmp", "jpg", "png", "tif", "gif", "jpeg"
|
||||
"bmp", "jpg", "png", "tif", "gif", "jpeg"
|
||||
};
|
||||
|
||||
|
||||
|
@ -226,6 +222,22 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
} else {
|
||||
MSException.throwException("请确认该Zentao账号是否开启超级modle调用接口权限");
|
||||
}
|
||||
|
||||
// 如果是复制新增, 同步MS附件到Zentao
|
||||
if (StringUtils.isNotEmpty(issuesRequest.getCopyIssueId())) {
|
||||
AttachmentRequest request = new AttachmentRequest();
|
||||
request.setBelongId(issuesRequest.getCopyIssueId());
|
||||
request.setBelongType(AttachmentType.ISSUE.type());
|
||||
List<String> attachmentIds = attachmentService.getAttachmentIdsByParam(request);
|
||||
if (CollectionUtils.isNotEmpty(attachmentIds)) {
|
||||
attachmentIds.forEach(attachmentId -> {
|
||||
FileAttachmentMetadata fileAttachmentMetadata = fileService.getFileAttachmentMetadataByFileId(attachmentId);
|
||||
File file = new File(fileAttachmentMetadata.getFilePath() + File.separator + fileAttachmentMetadata.getName());
|
||||
zentaoClient.uploadAttachment("bug", issuesRequest.getPlatformId(), file);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
|
@ -389,6 +401,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
customFieldMap.put(item.getId(), customFieldService.getCustomFieldResource(issue.getCustomFields()));
|
||||
issue.setId(item.getId());
|
||||
issuesMapper.updateByPrimaryKeySelective(issue);
|
||||
syncZentaoIssueAttachments(issue);
|
||||
});
|
||||
customFieldIssuesService.batchEditFields(customFieldMap);
|
||||
}
|
||||
|
@ -543,9 +556,69 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
|
||||
@Override
|
||||
public void syncIssuesAttachment(IssuesUpdateRequest issuesRequest, File file, AttachmentSyncType syncType) {
|
||||
// TODO: 同步缺陷MS附件到禅道
|
||||
if ("upload".equals(syncType.syncOperateType())) {
|
||||
zentaoClient.uploadAttachment("bug", issuesRequest.getPlatformId(), file);
|
||||
} else if ("delete".equals(syncType.syncOperateType())) {
|
||||
JSONObject bugInfo = zentaoClient.getBugById(issuesRequest.getPlatformId());
|
||||
JSONObject zenFiles = bugInfo.getJSONObject("files");
|
||||
for (String fileId : zenFiles.keySet()) {
|
||||
JSONObject fileInfo = zenFiles.getJSONObject(fileId);
|
||||
if (file.getName().equals(fileInfo.getString("title"))) {
|
||||
zentaoClient.deleteAttachment(fileId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void syncZentaoIssueAttachments(IssuesWithBLOBs issue) {
|
||||
List<String> znetaoAttachmentsName = new ArrayList<String>();
|
||||
AttachmentRequest request = new AttachmentRequest();
|
||||
request.setBelongType(AttachmentType.ISSUE.type());
|
||||
request.setBelongId(issue.getId());
|
||||
List<FileAttachmentMetadata> allMsAttachments = attachmentService.listMetadata(request);
|
||||
List<String> msAttachmentsName = allMsAttachments.stream().map(FileAttachmentMetadata::getName).collect(Collectors.toList());
|
||||
JSONObject bugInfo = zentaoClient.getBugById(issue.getPlatformId());
|
||||
JSONObject zenFiles = bugInfo.getJSONObject("files");
|
||||
// 同步Jira中新的附件
|
||||
if (zenFiles != null) {
|
||||
for (String fileId : zenFiles.keySet()) {
|
||||
JSONObject fileInfo = zenFiles.getJSONObject(fileId);
|
||||
String filename = fileInfo.getString("title");
|
||||
znetaoAttachmentsName.add(filename);
|
||||
if (!msAttachmentsName.contains(filename)) {
|
||||
try {
|
||||
byte[] bytes = zentaoClient.getAttachmentBytes(fileId);
|
||||
FileAttachmentMetadata fileAttachmentMetadata = fileService.saveAttachmentByBytes(bytes, AttachmentType.ISSUE.type(), issue.getId(), filename);
|
||||
AttachmentModuleRelation attachmentModuleRelation = new AttachmentModuleRelation();
|
||||
attachmentModuleRelation.setAttachmentId(fileAttachmentMetadata.getId());
|
||||
attachmentModuleRelation.setRelationId(issue.getId());
|
||||
attachmentModuleRelation.setRelationType(AttachmentType.ISSUE.type());
|
||||
attachmentModuleRelationMapper.insert(attachmentModuleRelation);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除Jira中不存在的附件
|
||||
if (CollectionUtils.isNotEmpty(allMsAttachments)) {
|
||||
List<FileAttachmentMetadata> deleteMsAttachments = allMsAttachments.stream()
|
||||
.filter(msAttachment -> !znetaoAttachmentsName.contains(msAttachment.getName())).collect(Collectors.toList());
|
||||
deleteMsAttachments.forEach(fileAttachmentMetadata -> {
|
||||
List<String> ids = List.of(fileAttachmentMetadata.getId());
|
||||
AttachmentModuleRelationExample example = new AttachmentModuleRelationExample();
|
||||
example.createCriteria().andAttachmentIdIn(ids).andRelationTypeEqualTo(AttachmentType.ISSUE.type());
|
||||
// 删除MS附件及关联数据
|
||||
fileService.deleteAttachment(ids);
|
||||
fileService.deleteFileAttachmentByIds(ids);
|
||||
attachmentModuleRelationMapper.deleteByExample(example);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<PlatformStatusDTO> getTransitions(String issueKey) {
|
||||
List<PlatformStatusDTO> platformStatusDTOS = new ArrayList<>();
|
||||
|
|
|
@ -9,13 +9,12 @@ import io.metersphere.commons.utils.UnicodeConvertUtils;
|
|||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.track.issue.domain.zentao.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class ZentaoClient extends BaseClient {
|
||||
|
@ -215,4 +214,38 @@ public abstract class ZentaoClient extends BaseClient {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void uploadAttachment(String objectType, String objectId, File file) {
|
||||
String sessionId = login();
|
||||
HttpHeaders authHeader = new HttpHeaders();
|
||||
authHeader.setContentType(MediaType.parseMediaType("multipart/form-data; charset=UTF-8"));
|
||||
|
||||
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
FileSystemResource fileResource = new FileSystemResource(file);
|
||||
paramMap.add("files", fileResource);
|
||||
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(paramMap, authHeader);
|
||||
|
||||
try {
|
||||
restTemplate.exchange(requestUrl.getFileUpload(), HttpMethod.POST, requestEntity,
|
||||
String.class, objectType, objectId, sessionId);
|
||||
} catch (Exception e) {
|
||||
LogUtil.info("upload zentao attachment error");
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAttachment(String fileId) {
|
||||
String sessionId = login();
|
||||
try {
|
||||
restTemplate.exchange(requestUrl.getFileDelete(), HttpMethod.GET, null, String.class, fileId, sessionId);
|
||||
} catch (Exception e) {
|
||||
LogUtil.info("delete zentao attachment error");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getAttachmentBytes(String fileId) {
|
||||
String sessionId = login();
|
||||
ResponseEntity<byte[]> response = restTemplate.exchange(requestUrl.getFileDownload(), HttpMethod.GET,
|
||||
null, byte[].class, fileId, sessionId);
|
||||
return response.getBody();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ public class ZentaoGetClient extends ZentaoClient {
|
|||
private static final String STORY_GET="&module=story&methodName=getProductStories¶ms=productID={key}&t=json&zentaosid=";
|
||||
private static final String USER_GET="&module=user&methodName=getList&t=json&zentaosid=";
|
||||
private static final String BUILDS_GET="&module=build&methodName=getProductBuildPairs&productID={0}&zentaosid={1}";
|
||||
private static final String FILE_UPLOAD="&module=file&methodName=saveUpload&t=json&zentaosid=";
|
||||
private static final String FILE_UPLOAD="&module=file&methodName=saveUpload¶ms=objectType={1},objectID={2},zentaosid={3}";
|
||||
private static final String FILE_DELETE="/?m=file&f=delete&t=json&fileID={1}&confirm=yes&zentaosid={2}";
|
||||
private static final String FILE_DOWNLOAD="/?m=file&f=download&t=json&fileID={1}&mouse=click&zentaosid={2}";
|
||||
private static final String CREATE_META_DATA="?m=bug&f=create&productID={0}&t=json&zentaosid={1}";
|
||||
private static final String REPLACE_IMG_URL="<img src=\"%s/index.php?m=file&f=read&fileID=$1\"/>";
|
||||
private static final Pattern IMG_PATTERN = Pattern.compile("m=file&f=read&fileID=(.*?)\"/>");
|
||||
|
@ -45,6 +47,8 @@ public class ZentaoGetClient extends ZentaoClient {
|
|||
request.setBugList(getNotSuperModelUrl(BUG_LIST_URL));
|
||||
request.setCreateMetaData(getNotSuperModelUrl(CREATE_META_DATA));
|
||||
request.setProductGet(getUrl(PRODUCT_GET));
|
||||
request.setFileDelete(getNotSuperModelUrl(FILE_DELETE));
|
||||
request.setFileDownload(getNotSuperModelUrl(FILE_DOWNLOAD));
|
||||
requestUrl = request;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ public class ZentaoPathInfoClient extends ZentaoClient {
|
|||
private static final String USER_GET = "/api-getModel-user-getList?zentaosid=";
|
||||
private static final String BUILDS_GET = "/api-getModel-build-getProductBuildPairs-productID={0}?zentaosid={1}";
|
||||
private static final String CREATE_META_DATA="/bug-create-{0}.json?zentaosid={1}";
|
||||
private static final String FILE_UPLOAD = "/api-getModel-file-saveUpload.json?zentaosid=";
|
||||
private static final String FILE_UPLOAD = "/api-getModel-file-saveUpload-{1}-{2}.json?zentaosid={3}";
|
||||
private static final String FILE_DELETE = "/file-delete-{1}-.yes.json?zentaosid={2}";
|
||||
private static final String FILE_DOWNLOAD="/file-download-{1}-.click.json?zentaosid={2}";
|
||||
private static final String REPLACE_IMG_URL = "<img src=\"%s/file-read-$1\"/>";
|
||||
private static final Pattern IMG_PATTERN = Pattern.compile("file-read-(.*?)\"/>");
|
||||
private static final String PRODUCT_GET = "/api-getModel-product-getById-productID={0}?zentaosid={1}";
|
||||
|
@ -45,6 +47,8 @@ public class ZentaoPathInfoClient extends ZentaoClient {
|
|||
request.setBugList(getUrl(BUG_LIST_URL));
|
||||
request.setCreateMetaData(getUrl(CREATE_META_DATA));
|
||||
request.setProductGet(getUrl(PRODUCT_GET));
|
||||
request.setFileDelete(getUrl(FILE_DELETE));
|
||||
request.setFileDelete(getUrl(FILE_DOWNLOAD));
|
||||
requestUrl = request;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ public class RequestUrl {
|
|||
private String userGet;
|
||||
private String buildsGet;
|
||||
private String fileUpload;
|
||||
private String fileDelete;
|
||||
private String fileDownload;
|
||||
private String replaceImgUrl;
|
||||
private String productGet;
|
||||
private Pattern imgPattern;
|
||||
|
|
Loading…
Reference in New Issue