fix(测试跟踪): 非xpack同步jira缺陷报错

This commit is contained in:
chenjianxing 2022-11-21 22:15:58 +08:00 committed by jianxing
parent 133f474d39
commit 6142f28f76
5 changed files with 92 additions and 66 deletions

View File

@ -153,9 +153,9 @@ public class IssuesController {
return issuesService.getZentaoBuilds(request);
}
@PostMapping("/sync")
public boolean getPlatformIssue(@RequestBody IssueSyncRequest request) {
return issuesService.syncThirdPartyIssues(request);
@GetMapping("/sync/{projectId}")
public boolean getPlatformIssue(@PathVariable String projectId) {
return issuesService.syncThirdPartyIssues(projectId);
}
@GetMapping("/sync/check/{projectId}")

View File

@ -886,9 +886,7 @@ public class IssuesService {
List<String> projectIds = trackProjectService.getThirdPartProjectIds();
projectIds.forEach(id -> {
try {
IssueSyncRequest request = new IssueSyncRequest();
request.setProjectId(id);
syncThirdPartyIssues(request);
syncThirdPartyIssues(id);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
}
@ -931,38 +929,35 @@ public class IssuesService {
stringRedisTemplate.delete(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
}
public boolean syncThirdPartyIssues(IssueSyncRequest syncRequest) {
if (StringUtils.isNotBlank(syncRequest.getProjectId())) {
String syncValue = getSyncKey(syncRequest.getProjectId());
public boolean syncThirdPartyIssues(String projectId) {
if (StringUtils.isNotBlank(projectId)) {
String syncValue = getSyncKey(projectId);
if (StringUtils.isNotEmpty(syncValue)) {
return false;
}
setSyncKey(syncRequest.getProjectId());
setSyncKey(projectId);
Project project = baseProjectService.getProjectById(syncRequest.getProjectId());
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(syncRequest.getProjectId(), project.getPlatform());
if (syncRequest.getCreateTime() != null) {
issues = filterSyncIssuesByCreated(issues, syncRequest);
}
Project project = baseProjectService.getProjectById(projectId);
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(projectId, project.getPlatform());
if (CollectionUtils.isEmpty(issues)) {
return true;
}
IssuesRequest issuesRequest = new IssuesRequest();
issuesRequest.setProjectId(syncRequest.getProjectId());
issuesRequest.setProjectId(projectId);
issuesRequest.setWorkspaceId(project.getWorkspaceId());
try {
if (!trackProjectService.isThirdPartTemplate(project)) {
String defaultCustomFields = getDefaultCustomFields(syncRequest.getProjectId());
String defaultCustomFields = getDefaultCustomFields(projectId);
issuesRequest.setDefaultCustomFields(defaultCustomFields);
}
if (PlatformPluginService.isPluginPlatform(project.getPlatform())) {
// 分批处理
SubListUtil.dealForSubList(issues, 500, (subIssue) ->
syncPluginThirdPartyIssues(subIssue, project));
syncPluginThirdPartyIssues(subIssue, project, issuesRequest.getDefaultCustomFields()));
} else {
IssuesPlatform platform = IssueFactory.createPlatform(project.getPlatform(), issuesRequest);
syncThirdPartyIssues(platform::syncIssues, project, issues);
@ -970,13 +965,13 @@ public class IssuesService {
} catch (Exception e) {
throw e;
} finally {
deleteSyncKey(syncRequest.getProjectId());
deleteSyncKey(projectId);
}
}
return true;
}
public void syncPluginThirdPartyIssues(List<IssuesDao> issues, Project project) {
public void syncPluginThirdPartyIssues(List<IssuesDao> issues, Project project, String defaultCustomFields) {
List<PlatformIssuesDTO> platformIssues = JSON.parseArray(JSON.toJSONString(issues), PlatformIssuesDTO.class);
platformIssues.stream().forEach(item -> {
// 给缺陷添加自定义字段
@ -991,6 +986,7 @@ public class IssuesService {
});
SyncIssuesRequest request = new SyncIssuesRequest();
request.setIssues(platformIssues);
request.setDefaultCustomFields(defaultCustomFields);
request.setProjectConfig(PlatformPluginService.getCompatibleProjectConfig(project));
Platform platform = platformPluginService.getPlatform(project.getPlatform());
@ -999,38 +995,39 @@ public class IssuesService {
List<IssuesWithBLOBs> updateIssues = syncIssuesResult.getUpdateIssues();
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
IssuesMapper issueBatchMapper = sqlSession.getMapper(IssuesMapper.class);
AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper = sqlSession.getMapper(AttachmentModuleRelationMapper.class);
// 批量更新
updateIssues.stream()
.map(item -> {
IssuesWithBLOBs issuesWithBLOBs = new IssuesWithBLOBs();
BeanUtils.copyBean(issuesWithBLOBs, item);
return issuesWithBLOBs;
})
.forEach(issueBatchMapper::updateByPrimaryKeySelective);
// 批量删除
syncIssuesResult.getDeleteIssuesIds()
.stream()
.forEach(issueBatchMapper::deleteByPrimaryKey);
try {
// 同步附件
syncPluginIssueAttachment(platform, syncIssuesResult, batchAttachmentModuleRelationMapper);
IssuesMapper issueBatchMapper = sqlSession.getMapper(IssuesMapper.class);
AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper = sqlSession.getMapper(AttachmentModuleRelationMapper.class);
// 批量更新
updateIssues.forEach(issueBatchMapper::updateByPrimaryKeySelective);
// 批量删除
syncIssuesResult.getDeleteIssuesIds()
.stream()
.forEach(issueBatchMapper::deleteByPrimaryKey);
try {
// 同步附件
syncPluginIssueAttachment(platform, syncIssuesResult, batchAttachmentModuleRelationMapper);
} catch (Exception e) {
LogUtil.error(e);
}
HashMap<String, List<CustomFieldResourceDTO>> customFieldMap = new HashMap<>();
updateIssues.forEach(item -> {
List<CustomFieldResourceDTO> customFieldResource = baseCustomFieldService.getCustomFieldResourceDTO(item.getCustomFields());
customFieldMap.put(item.getId(), customFieldResource);
});
// 修改自定义字段
customFieldIssuesService.batchEditFields(customFieldMap);
sqlSession.commit();
} catch (Exception e) {
LogUtil.error(e);
sqlSession.close();
MSException.throwException(e);
}
HashMap<String, List<CustomFieldResourceDTO>> customFieldMap = new HashMap<>();
updateIssues.forEach(item -> {
List<CustomFieldResourceDTO> customFieldResource = baseCustomFieldService.getCustomFieldResourceDTO(item.getCustomFields());
customFieldMap.put(item.getId(), customFieldResource);
});
// 修改自定义字段
customFieldIssuesService.batchEditFields(customFieldMap);
}
private void syncPluginIssueAttachment(Platform platform, SyncIssuesResult syncIssuesResult, AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper) {
@ -1049,8 +1046,8 @@ public class IssuesService {
List<PlatformAttachment> syncAttachments = attachmentMap.get(issueId);
for (PlatformAttachment syncAttachment : syncAttachments) {
jiraAttachmentSet.add(syncAttachment.getFileName());
if (!attachmentsNameSet.contains(syncAttachment.getFileName())) {
jiraAttachmentSet.add(syncAttachment.getFileName());
try {
byte[] content = platform.getAttachmentContent(syncAttachment.getFileKey());
if (content == null) {

View File

@ -3,7 +3,6 @@ package io.metersphere.service.wapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.i18n.Translator;
import io.metersphere.service.PlatformPluginService;
import io.metersphere.xpack.track.dto.request.IssuesRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
@ -35,10 +34,7 @@ public class IssueProxyResourceService {
MSException.throwException(Translator.get("invalid_parameter"));
}
if (StringUtils.isNotBlank(platform)) {
IssuesRequest issuesRequest = new IssuesRequest();
issuesRequest.setProjectId(projectId);
issuesRequest.setWorkspaceId(workspaceId);
return platformPluginService.getPlatform(platform)
return platformPluginService.getPlatform(platform, workspaceId)
.proxyForGet(url, byte[].class);
}

View File

@ -146,16 +146,18 @@ export function getRelateIssues(page) {
});
}
export function syncIssues(param) {
let url = 'issues/sync';
if (hasLicense()) {
url = 'xpack/issue/sync';
}
export function syncAllIssues(param) {
// 浏览器默认策略请求同一个url可能导致 stalled 时间过长加个uuid防止请求阻塞
url = url + "?stamp=" + getUUID();
let url = 'xpack/issue/sync' + "?stamp=" + getUUID();
return post(url, param);
}
export function syncIssues() {
// 浏览器默认策略请求同一个url可能导致 stalled 时间过长加个uuid防止请求阻塞
let url = 'issues/sync/' + getCurrentProjectID() + "?stamp=" + getUUID();
return get(url);
}
// 轮询同步状态
export function checkSyncIssues(loading, isNotFirst) {
let url = 'issues/sync/check/' + getCurrentProjectID() + "?stamp=" + getUUID();

View File

@ -7,7 +7,21 @@
:create-tip="$t('test_track.issue.create_issue')"
:tip="$t('commons.search_by_name_or_id')">
<template v-slot:button>
<ms-table-button icon="el-icon-refresh" :content="$t('test_track.issue.sync_bugs')" v-if="isThirdPart && hasPermission('PROJECT_TRACK_ISSUE:READ+CREATE')" @click="syncIssues"/>
<span v-if="isThirdPart && hasPermission('PROJECT_TRACK_ISSUE:READ+CREATE')">
<ms-table-button
v-if="hasLicense"
icon="el-icon-refresh"
:content="$t('test_track.issue.sync_bugs')"
@click="syncAllIssues"/>
<ms-table-button
v-if="!hasLicense"
icon="el-icon-refresh"
:content="$t('test_track.issue.sync_bugs')"
@click="syncIssues"/>
</span>
<ms-table-button icon="el-icon-upload2" :content="$t('commons.import')" v-if="hasPermission('PROJECT_TRACK_ISSUE:READ+CREATE')" @click="handleImport"/>
<ms-table-button icon="el-icon-download" :content="$t('commons.export')" v-if="hasPermission('PROJECT_TRACK_ISSUE:READ')" @click="handleExport"/>
</template>
@ -195,7 +209,7 @@ import {
getIssues,
syncIssues,
deleteIssue,
getIssuesById, batchDeleteIssue, getPlatformOption
getIssuesById, batchDeleteIssue, getPlatformOption, syncAllIssues
} from "@/api/issue";
import {
getCustomFieldValue,
@ -214,6 +228,7 @@ import {
getAdvSearchCustomField
} from "metersphere-frontend/src/components/search/custom-component";
import MsMarkDownText from "metersphere-frontend/src/components/MsMarkDownText";
import {hasLicense} from "metersphere-frontend/src/utils/permission";
export default {
name: "IssueList",
@ -269,7 +284,8 @@ export default {
creatorFilters: [],
loading: false,
dataSelectRange: "",
platformOptions: []
platformOptions: [],
hasLicense: false
};
},
watch: {
@ -303,6 +319,8 @@ export default {
.then((r) => {
this.platformOptions = r.data;
});
this.hasLicense = hasLicense();
},
computed: {
platformFilters() {
@ -467,7 +485,7 @@ export default {
}
return false;
},
syncIssues() {
syncAllIssues() {
this.$refs.issueSyncSelect.open();
},
handleImport() {
@ -500,7 +518,20 @@ export default {
"createTime": data.createTime.getTime(),
"pre": data.preValue
}
syncIssues(param)
syncAllIssues(param)
.then((response) => {
if (response.data === false) {
checkSyncIssues(this.loading);
} else {
this.$success(this.$t('test_track.issue.sync_complete'));
this.loading = false;
this.getIssues();
}
});
},
syncIssues() {
this.loading = true;
syncIssues()
.then((response) => {
if (response.data === false) {
checkSyncIssues(this.loading);