fix(测试跟踪): 非xpack同步jira缺陷报错
This commit is contained in:
parent
133f474d39
commit
6142f28f76
|
@ -153,9 +153,9 @@ public class IssuesController {
|
||||||
return issuesService.getZentaoBuilds(request);
|
return issuesService.getZentaoBuilds(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/sync")
|
@GetMapping("/sync/{projectId}")
|
||||||
public boolean getPlatformIssue(@RequestBody IssueSyncRequest request) {
|
public boolean getPlatformIssue(@PathVariable String projectId) {
|
||||||
return issuesService.syncThirdPartyIssues(request);
|
return issuesService.syncThirdPartyIssues(projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/sync/check/{projectId}")
|
@GetMapping("/sync/check/{projectId}")
|
||||||
|
|
|
@ -886,9 +886,7 @@ public class IssuesService {
|
||||||
List<String> projectIds = trackProjectService.getThirdPartProjectIds();
|
List<String> projectIds = trackProjectService.getThirdPartProjectIds();
|
||||||
projectIds.forEach(id -> {
|
projectIds.forEach(id -> {
|
||||||
try {
|
try {
|
||||||
IssueSyncRequest request = new IssueSyncRequest();
|
syncThirdPartyIssues(id);
|
||||||
request.setProjectId(id);
|
|
||||||
syncThirdPartyIssues(request);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e.getMessage(), e);
|
LogUtil.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
@ -931,38 +929,35 @@ public class IssuesService {
|
||||||
stringRedisTemplate.delete(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
|
stringRedisTemplate.delete(SYNC_THIRD_PARTY_ISSUES_KEY + ":" + projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean syncThirdPartyIssues(IssueSyncRequest syncRequest) {
|
public boolean syncThirdPartyIssues(String projectId) {
|
||||||
if (StringUtils.isNotBlank(syncRequest.getProjectId())) {
|
if (StringUtils.isNotBlank(projectId)) {
|
||||||
String syncValue = getSyncKey(syncRequest.getProjectId());
|
String syncValue = getSyncKey(projectId);
|
||||||
if (StringUtils.isNotEmpty(syncValue)) {
|
if (StringUtils.isNotEmpty(syncValue)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSyncKey(syncRequest.getProjectId());
|
setSyncKey(projectId);
|
||||||
|
|
||||||
Project project = baseProjectService.getProjectById(syncRequest.getProjectId());
|
Project project = baseProjectService.getProjectById(projectId);
|
||||||
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(syncRequest.getProjectId(), project.getPlatform());
|
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(projectId, project.getPlatform());
|
||||||
if (syncRequest.getCreateTime() != null) {
|
|
||||||
issues = filterSyncIssuesByCreated(issues, syncRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(issues)) {
|
if (CollectionUtils.isEmpty(issues)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IssuesRequest issuesRequest = new IssuesRequest();
|
IssuesRequest issuesRequest = new IssuesRequest();
|
||||||
issuesRequest.setProjectId(syncRequest.getProjectId());
|
issuesRequest.setProjectId(projectId);
|
||||||
issuesRequest.setWorkspaceId(project.getWorkspaceId());
|
issuesRequest.setWorkspaceId(project.getWorkspaceId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!trackProjectService.isThirdPartTemplate(project)) {
|
if (!trackProjectService.isThirdPartTemplate(project)) {
|
||||||
String defaultCustomFields = getDefaultCustomFields(syncRequest.getProjectId());
|
String defaultCustomFields = getDefaultCustomFields(projectId);
|
||||||
issuesRequest.setDefaultCustomFields(defaultCustomFields);
|
issuesRequest.setDefaultCustomFields(defaultCustomFields);
|
||||||
}
|
}
|
||||||
if (PlatformPluginService.isPluginPlatform(project.getPlatform())) {
|
if (PlatformPluginService.isPluginPlatform(project.getPlatform())) {
|
||||||
// 分批处理
|
// 分批处理
|
||||||
SubListUtil.dealForSubList(issues, 500, (subIssue) ->
|
SubListUtil.dealForSubList(issues, 500, (subIssue) ->
|
||||||
syncPluginThirdPartyIssues(subIssue, project));
|
syncPluginThirdPartyIssues(subIssue, project, issuesRequest.getDefaultCustomFields()));
|
||||||
} else {
|
} else {
|
||||||
IssuesPlatform platform = IssueFactory.createPlatform(project.getPlatform(), issuesRequest);
|
IssuesPlatform platform = IssueFactory.createPlatform(project.getPlatform(), issuesRequest);
|
||||||
syncThirdPartyIssues(platform::syncIssues, project, issues);
|
syncThirdPartyIssues(platform::syncIssues, project, issues);
|
||||||
|
@ -970,13 +965,13 @@ public class IssuesService {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
deleteSyncKey(syncRequest.getProjectId());
|
deleteSyncKey(projectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
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);
|
List<PlatformIssuesDTO> platformIssues = JSON.parseArray(JSON.toJSONString(issues), PlatformIssuesDTO.class);
|
||||||
platformIssues.stream().forEach(item -> {
|
platformIssues.stream().forEach(item -> {
|
||||||
// 给缺陷添加自定义字段
|
// 给缺陷添加自定义字段
|
||||||
|
@ -991,6 +986,7 @@ public class IssuesService {
|
||||||
});
|
});
|
||||||
SyncIssuesRequest request = new SyncIssuesRequest();
|
SyncIssuesRequest request = new SyncIssuesRequest();
|
||||||
request.setIssues(platformIssues);
|
request.setIssues(platformIssues);
|
||||||
|
request.setDefaultCustomFields(defaultCustomFields);
|
||||||
request.setProjectConfig(PlatformPluginService.getCompatibleProjectConfig(project));
|
request.setProjectConfig(PlatformPluginService.getCompatibleProjectConfig(project));
|
||||||
Platform platform = platformPluginService.getPlatform(project.getPlatform());
|
Platform platform = platformPluginService.getPlatform(project.getPlatform());
|
||||||
|
|
||||||
|
@ -999,17 +995,12 @@ public class IssuesService {
|
||||||
List<IssuesWithBLOBs> updateIssues = syncIssuesResult.getUpdateIssues();
|
List<IssuesWithBLOBs> updateIssues = syncIssuesResult.getUpdateIssues();
|
||||||
|
|
||||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||||
|
try {
|
||||||
IssuesMapper issueBatchMapper = sqlSession.getMapper(IssuesMapper.class);
|
IssuesMapper issueBatchMapper = sqlSession.getMapper(IssuesMapper.class);
|
||||||
AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper = sqlSession.getMapper(AttachmentModuleRelationMapper.class);
|
AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper = sqlSession.getMapper(AttachmentModuleRelationMapper.class);
|
||||||
|
|
||||||
// 批量更新
|
// 批量更新
|
||||||
updateIssues.stream()
|
updateIssues.forEach(issueBatchMapper::updateByPrimaryKeySelective);
|
||||||
.map(item -> {
|
|
||||||
IssuesWithBLOBs issuesWithBLOBs = new IssuesWithBLOBs();
|
|
||||||
BeanUtils.copyBean(issuesWithBLOBs, item);
|
|
||||||
return issuesWithBLOBs;
|
|
||||||
})
|
|
||||||
.forEach(issueBatchMapper::updateByPrimaryKeySelective);
|
|
||||||
|
|
||||||
// 批量删除
|
// 批量删除
|
||||||
syncIssuesResult.getDeleteIssuesIds()
|
syncIssuesResult.getDeleteIssuesIds()
|
||||||
|
@ -1031,6 +1022,12 @@ public class IssuesService {
|
||||||
|
|
||||||
// 修改自定义字段
|
// 修改自定义字段
|
||||||
customFieldIssuesService.batchEditFields(customFieldMap);
|
customFieldIssuesService.batchEditFields(customFieldMap);
|
||||||
|
|
||||||
|
sqlSession.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
sqlSession.close();
|
||||||
|
MSException.throwException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncPluginIssueAttachment(Platform platform, SyncIssuesResult syncIssuesResult, AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper) {
|
private void syncPluginIssueAttachment(Platform platform, SyncIssuesResult syncIssuesResult, AttachmentModuleRelationMapper batchAttachmentModuleRelationMapper) {
|
||||||
|
@ -1049,8 +1046,8 @@ public class IssuesService {
|
||||||
|
|
||||||
List<PlatformAttachment> syncAttachments = attachmentMap.get(issueId);
|
List<PlatformAttachment> syncAttachments = attachmentMap.get(issueId);
|
||||||
for (PlatformAttachment syncAttachment : syncAttachments) {
|
for (PlatformAttachment syncAttachment : syncAttachments) {
|
||||||
jiraAttachmentSet.add(syncAttachment.getFileName());
|
|
||||||
if (!attachmentsNameSet.contains(syncAttachment.getFileName())) {
|
if (!attachmentsNameSet.contains(syncAttachment.getFileName())) {
|
||||||
|
jiraAttachmentSet.add(syncAttachment.getFileName());
|
||||||
try {
|
try {
|
||||||
byte[] content = platform.getAttachmentContent(syncAttachment.getFileKey());
|
byte[] content = platform.getAttachmentContent(syncAttachment.getFileKey());
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
|
|
|
@ -3,7 +3,6 @@ package io.metersphere.service.wapper;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.service.PlatformPluginService;
|
import io.metersphere.service.PlatformPluginService;
|
||||||
import io.metersphere.xpack.track.dto.request.IssuesRequest;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
@ -35,10 +34,7 @@ public class IssueProxyResourceService {
|
||||||
MSException.throwException(Translator.get("invalid_parameter"));
|
MSException.throwException(Translator.get("invalid_parameter"));
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(platform)) {
|
if (StringUtils.isNotBlank(platform)) {
|
||||||
IssuesRequest issuesRequest = new IssuesRequest();
|
return platformPluginService.getPlatform(platform, workspaceId)
|
||||||
issuesRequest.setProjectId(projectId);
|
|
||||||
issuesRequest.setWorkspaceId(workspaceId);
|
|
||||||
return platformPluginService.getPlatform(platform)
|
|
||||||
.proxyForGet(url, byte[].class);
|
.proxyForGet(url, byte[].class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,16 +146,18 @@ export function getRelateIssues(page) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function syncIssues(param) {
|
export function syncAllIssues(param) {
|
||||||
let url = 'issues/sync';
|
|
||||||
if (hasLicense()) {
|
|
||||||
url = 'xpack/issue/sync';
|
|
||||||
}
|
|
||||||
// 浏览器默认策略,请求同一个url,可能导致 stalled 时间过长,加个uuid防止请求阻塞
|
// 浏览器默认策略,请求同一个url,可能导致 stalled 时间过长,加个uuid防止请求阻塞
|
||||||
url = url + "?stamp=" + getUUID();
|
let url = 'xpack/issue/sync' + "?stamp=" + getUUID();
|
||||||
return post(url, param);
|
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) {
|
export function checkSyncIssues(loading, isNotFirst) {
|
||||||
let url = 'issues/sync/check/' + getCurrentProjectID() + "?stamp=" + getUUID();
|
let url = 'issues/sync/check/' + getCurrentProjectID() + "?stamp=" + getUUID();
|
||||||
|
|
|
@ -7,7 +7,21 @@
|
||||||
:create-tip="$t('test_track.issue.create_issue')"
|
:create-tip="$t('test_track.issue.create_issue')"
|
||||||
:tip="$t('commons.search_by_name_or_id')">
|
:tip="$t('commons.search_by_name_or_id')">
|
||||||
<template v-slot:button>
|
<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-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"/>
|
<ms-table-button icon="el-icon-download" :content="$t('commons.export')" v-if="hasPermission('PROJECT_TRACK_ISSUE:READ')" @click="handleExport"/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -195,7 +209,7 @@ import {
|
||||||
getIssues,
|
getIssues,
|
||||||
syncIssues,
|
syncIssues,
|
||||||
deleteIssue,
|
deleteIssue,
|
||||||
getIssuesById, batchDeleteIssue, getPlatformOption
|
getIssuesById, batchDeleteIssue, getPlatformOption, syncAllIssues
|
||||||
} from "@/api/issue";
|
} from "@/api/issue";
|
||||||
import {
|
import {
|
||||||
getCustomFieldValue,
|
getCustomFieldValue,
|
||||||
|
@ -214,6 +228,7 @@ import {
|
||||||
getAdvSearchCustomField
|
getAdvSearchCustomField
|
||||||
} from "metersphere-frontend/src/components/search/custom-component";
|
} from "metersphere-frontend/src/components/search/custom-component";
|
||||||
import MsMarkDownText from "metersphere-frontend/src/components/MsMarkDownText";
|
import MsMarkDownText from "metersphere-frontend/src/components/MsMarkDownText";
|
||||||
|
import {hasLicense} from "metersphere-frontend/src/utils/permission";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "IssueList",
|
name: "IssueList",
|
||||||
|
@ -269,7 +284,8 @@ export default {
|
||||||
creatorFilters: [],
|
creatorFilters: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
dataSelectRange: "",
|
dataSelectRange: "",
|
||||||
platformOptions: []
|
platformOptions: [],
|
||||||
|
hasLicense: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -303,6 +319,8 @@ export default {
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
this.platformOptions = r.data;
|
this.platformOptions = r.data;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.hasLicense = hasLicense();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
platformFilters() {
|
platformFilters() {
|
||||||
|
@ -467,7 +485,7 @@ export default {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
syncIssues() {
|
syncAllIssues() {
|
||||||
this.$refs.issueSyncSelect.open();
|
this.$refs.issueSyncSelect.open();
|
||||||
},
|
},
|
||||||
handleImport() {
|
handleImport() {
|
||||||
|
@ -500,7 +518,20 @@ export default {
|
||||||
"createTime": data.createTime.getTime(),
|
"createTime": data.createTime.getTime(),
|
||||||
"pre": data.preValue
|
"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) => {
|
.then((response) => {
|
||||||
if (response.data === false) {
|
if (response.data === false) {
|
||||||
checkSyncIssues(this.loading);
|
checkSyncIssues(this.loading);
|
||||||
|
|
Loading…
Reference in New Issue