refactor(项目设置): 优化缺陷同步定时任务配置逻辑

This commit is contained in:
song-cc-rock 2024-01-29 16:11:56 +08:00 committed by 刘瑞斌
parent e15e0611f7
commit 97ece4ad80
19 changed files with 200 additions and 224 deletions

View File

@ -94,4 +94,10 @@ public class MsSyncBugDTO {
* 缺陷描述 * 缺陷描述
*/ */
private String description; private String description;
/**
* 缺陷位置
*/
private Long pos;
} }

View File

@ -10,7 +10,7 @@ public class SyncAllBugRequest extends SyncBugRequest {
/** /**
* 创建时间前后 * 创建时间前后
*/ */
private boolean pre; private Boolean pre;
/** /**
* 条件: 缺陷创建时间 * 条件: 缺陷创建时间

View File

@ -12,7 +12,7 @@ public class BugSyncRequest implements Serializable {
private String projectId; private String projectId;
@Schema(description = "创建时间前或后", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间前或后", requiredMode = Schema.RequiredMode.REQUIRED)
private boolean pre; private Boolean pre;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private Long createTime; private Long createTime;

View File

@ -2,13 +2,18 @@ package io.metersphere.bug.job;
import io.metersphere.bug.service.BugSyncService; import io.metersphere.bug.service.BugSyncService;
import io.metersphere.bug.service.XpackBugService; import io.metersphere.bug.service.XpackBugService;
import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.sdk.util.CommonBeanFactory; import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.domain.ServiceIntegration;
import io.metersphere.system.dto.sdk.LicenseDTO; import io.metersphere.system.dto.sdk.LicenseDTO;
import io.metersphere.system.schedule.BaseScheduleJob; import io.metersphere.system.schedule.BaseScheduleJob;
import io.metersphere.system.service.LicenseService; import io.metersphere.system.service.LicenseService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
/** /**
* 缺陷同步定时任务 * 缺陷同步定时任务
@ -18,30 +23,55 @@ public class BugSyncJob extends BaseScheduleJob {
private final LicenseService licenseService; private final LicenseService licenseService;
private final BugSyncService bugSyncService; private final BugSyncService bugSyncService;
private final XpackBugService xpackBugService; private final XpackBugService xpackBugService;
private final ProjectApplicationService projectApplicationService;
public BugSyncJob() { public BugSyncJob() {
licenseService = CommonBeanFactory.getBean(LicenseService.class); licenseService = CommonBeanFactory.getBean(LicenseService.class);
xpackBugService = CommonBeanFactory.getBean(XpackBugService.class); xpackBugService = CommonBeanFactory.getBean(XpackBugService.class);
bugSyncService = CommonBeanFactory.getBean(BugSyncService.class); bugSyncService = CommonBeanFactory.getBean(BugSyncService.class);
projectApplicationService = CommonBeanFactory.getBean(ProjectApplicationService.class);
}
public static JobKey getJobKey(String resourceId) {
return new JobKey(resourceId, BugSyncJob.class.getName());
}
public static TriggerKey getTriggerKey(String resourceId) {
return new TriggerKey(resourceId, BugSyncJob.class.getName());
} }
@Override @Override
protected void businessExecute(JobExecutionContext context) { protected void businessExecute(JobExecutionContext context) {
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
String resourceId = jobDataMap.getString("resourceId");
String userId = jobDataMap.getString("userId");
if (!checkBeforeSync(resourceId)) {
return;
}
LogUtils.info("bug sync job start......"); LogUtils.info("bug sync job start......");
if (licenseService == null) { if (licenseService == null) {
LogUtils.info("license is null, sync remain bug"); LogUtils.info("license is null, sync remain bug");
bugSyncService.syncPlatformBugBySchedule(); bugSyncService.syncPlatformBugBySchedule(resourceId, userId);
} else { } else {
LicenseDTO licenseDTO = licenseService.validate(); LicenseDTO licenseDTO = licenseService.validate();
if (licenseDTO != null && licenseDTO.getLicense() != null if (licenseDTO != null && licenseDTO.getLicense() != null
&& StringUtils.equals(licenseDTO.getStatus(), "valid")) { && StringUtils.equals(licenseDTO.getStatus(), "valid")) {
LogUtils.info("license is valid, sync all bug"); LogUtils.info("license is valid, sync all bug");
xpackBugService.syncPlatformBugsBySchedule(); xpackBugService.syncPlatformBugsBySchedule(resourceId, userId);
} else { } else {
LogUtils.info("license is invalid, sync remain bug"); LogUtils.info("license is invalid, sync remain bug");
bugSyncService.syncPlatformBugBySchedule(); bugSyncService.syncPlatformBugBySchedule(resourceId, userId);
} }
} }
LogUtils.info("bug sync job end......"); LogUtils.info("bug sync job end......");
} }
/**
* 同步前检验, 同步配置的平台是否开启插件集成
* @return 是否放行
*/
private boolean checkBeforeSync(String projectId) {
ServiceIntegration serviceIntegration = projectApplicationService.getPlatformServiceIntegrationWithSyncOrDemand(projectId, true);
return serviceIntegration != null && serviceIntegration.getEnable();
}
} }

View File

@ -0,0 +1,67 @@
package io.metersphere.bug.service;
import io.metersphere.bug.job.BugSyncJob;
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.constants.ScheduleResourceType;
import io.metersphere.sdk.constants.ScheduleType;
import io.metersphere.system.domain.Schedule;
import io.metersphere.system.schedule.ScheduleService;
import io.metersphere.system.service.BaseBugScheduleService;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
@Transactional(rollbackFor = Exception.class)
public class BugScheduleServiceImpl implements BaseBugScheduleService {
@Resource
private ScheduleService scheduleService;
@Override
public void updateBugSyncScheduleConfig(List<ProjectApplication> bugSyncConfigs, String projectId, String currentUser) {
List<ProjectApplication> syncCron = bugSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.BUG.BUG_SYNC.name() + "_" + ProjectApplicationType.BUG_SYNC_CONFIG.CRON_EXPRESSION.name())).toList();
List<ProjectApplication> syncEnable = bugSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.BUG.BUG_SYNC.name() + "_" + ProjectApplicationType.BUG_SYNC_CONFIG.SYNC_ENABLE.name())).toList();
if (CollectionUtils.isNotEmpty(syncCron)) {
Boolean enable = Boolean.valueOf(syncEnable.get(0).getTypeValue());
String typeValue = syncCron.get(0).getTypeValue();
Schedule schedule = scheduleService.getScheduleByResource(projectId, BugSyncJob.class.getName());
Optional<Schedule> optional = Optional.ofNullable(schedule);
optional.ifPresentOrElse(s -> {
s.setEnable(enable);
s.setValue(typeValue);
scheduleService.editSchedule(s);
scheduleService.addOrUpdateCronJob(s, BugSyncJob.getJobKey(projectId), BugSyncJob.getTriggerKey(projectId), BugSyncJob.class);
}, () -> {
Schedule request = new Schedule();
request.setName("Bug Sync Job");
request.setResourceId(projectId);
request.setKey(IDGenerator.nextStr());
request.setProjectId(projectId);
request.setEnable(enable);
request.setCreateUser(currentUser);
request.setType(ScheduleType.CRON.name());
request.setValue(typeValue);
request.setJob(BugSyncJob.class.getName());
request.setResourceType(ScheduleResourceType.BUG_SYNC.name());
scheduleService.addSchedule(request);
scheduleService.addOrUpdateCronJob(request, BugSyncJob.getJobKey(projectId), BugSyncJob.getTriggerKey(projectId), BugSyncJob.class);
});
}
}
@Override
public void enableOrNotBugSyncSchedule(String projectId, String currentUser, Boolean enable) {
Schedule schedule = scheduleService.getScheduleByResource(projectId, BugSyncJob.class.getName());
if (schedule != null) {
schedule.setEnable(enable);
scheduleService.editSchedule(schedule);
}
}
}

View File

@ -7,13 +7,11 @@ import io.metersphere.bug.dto.request.BugSyncRequest;
import io.metersphere.bug.enums.BugPlatform; import io.metersphere.bug.enums.BugPlatform;
import io.metersphere.bug.mapper.BugMapper; import io.metersphere.bug.mapper.BugMapper;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.domain.ProjectExample;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.service.ProjectApplicationService; import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.project.service.ProjectTemplateService; import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.sdk.constants.TemplateScene; import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.domain.Template; import io.metersphere.system.domain.Template;
import io.metersphere.system.domain.TemplateExample; import io.metersphere.system.domain.TemplateExample;
import io.metersphere.system.mapper.TemplateMapper; import io.metersphere.system.mapper.TemplateMapper;
@ -134,18 +132,8 @@ public class BugSyncService {
/** /**
* 定时任务同步缺陷(存量) * 定时任务同步缺陷(存量)
*/ */
public void syncPlatformBugBySchedule() { public void syncPlatformBugBySchedule(String projectId, String scheduleUser) {
ProjectExample example = new ProjectExample(); syncBugs(projectId, scheduleUser);
List<Project> projects = projectMapper.selectByExample(example);
List<String> allProjectIds = projects.stream().map(Project::getId).collect(Collectors.toList());
List<String> syncProjectIds = projectApplicationService.filterNeedSyncProject(allProjectIds);
syncProjectIds.forEach(id -> {
try {
syncBugs(id, "admin");
} catch (Exception e) {
LogUtils.error(e.getMessage(), e);
}
});
} }
/** /**

View File

@ -14,8 +14,10 @@ public interface XpackBugService {
/** /**
* 同步系统下所有第三方平台项目缺陷(定时任务) * 同步系统下所有第三方平台项目缺陷(定时任务)
* @param projectId 项目ID
* @param scheduleUser 定时任务执行用户
*/ */
void syncPlatformBugsBySchedule(); void syncPlatformBugsBySchedule(String projectId, String scheduleUser);
/** /**
* 同步当前项目第三方平台缺陷(前台调用, 全量同步) * 同步当前项目第三方平台缺陷(前台调用, 全量同步)

View File

@ -554,8 +554,7 @@ public class BugControllerTests extends BaseTest {
this.requestGetWithOk(BUG_HEADER_STATUS_OPTION + "/default-project-for-bug"); this.requestGetWithOk(BUG_HEADER_STATUS_OPTION + "/default-project-for-bug");
this.requestGetWithOk(BUG_HEADER_HANDLER_OPTION + "/default-project-for-bug"); this.requestGetWithOk(BUG_HEADER_HANDLER_OPTION + "/default-project-for-bug");
// 同步删除缺陷(default-bug-id-jira-sync) // 同步并删除的两条缺陷
// 一条模板不存在的缺陷(手动删除default-bug-id-jira-sync-1, 影响后续测试)
this.requestGetWithOk(BUG_SYNC + "/default-project-for-bug"); this.requestGetWithOk(BUG_SYNC + "/default-project-for-bug");
bugMapper.deleteByPrimaryKey("default-bug-id-jira-sync-1"); bugMapper.deleteByPrimaryKey("default-bug-id-jira-sync-1");
@ -618,6 +617,12 @@ public class BugControllerTests extends BaseTest {
deleteLocalFile(updateRequest2.getId()); // 手动删除关联的文件, 重新同步时会下载平台附件 deleteLocalFile(updateRequest2.getId()); // 手动删除关联的文件, 重新同步时会下载平台附件
bugService.syncPlatformBugs(remainBugs, defaultProject, "admin"); bugService.syncPlatformBugs(remainBugs, defaultProject, "admin");
// 全选删除所有Jira缺陷
BugBatchRequest request = new BugBatchRequest();
request.setProjectId("default-project-for-bug");
request.setSelectAll(true);
this.requestPost(BUG_BATCH_DELETE, request);
// 集成配置为空 // 集成配置为空
addRequest.setProjectId("default-project-for-not-integration"); addRequest.setProjectId("default-project-for-not-integration");
MultiValueMap<String, Object> notIntegrationParam = getDefaultMultiPartParam(addRequest, file); MultiValueMap<String, Object> notIntegrationParam = getDefaultMultiPartParam(addRequest, file);
@ -638,7 +643,7 @@ public class BugControllerTests extends BaseTest {
@Order(97) @Order(97)
void coverSyncScheduleTests() { void coverSyncScheduleTests() {
// 定时同步存量缺陷 // 定时同步存量缺陷
bugSyncService.syncPlatformBugBySchedule(); bugSyncService.syncPlatformBugBySchedule("default-project-for-bug", "admin");
// 异常信息 // 异常信息
bugSyncExtraService.setSyncErrorMsg("default-project-for-bug", "sync error!"); bugSyncExtraService.setSyncErrorMsg("default-project-for-bug", "sync error!");
String syncErrorMsg = bugSyncExtraService.getSyncErrorMsg("default-project-for-bug"); String syncErrorMsg = bugSyncExtraService.getSyncErrorMsg("default-project-for-bug");
@ -823,7 +828,7 @@ public class BugControllerTests extends BaseTest {
summaryField.setId("summary"); summaryField.setId("summary");
summaryField.setName("摘要"); summaryField.setName("摘要");
summaryField.setType("input"); summaryField.setType("input");
summaryField.setValue("这是一段summary内容!!!!"); summaryField.setValue("这是一段summary内容1!!!!");
BugCustomFieldDTO descriptionField = new BugCustomFieldDTO(); BugCustomFieldDTO descriptionField = new BugCustomFieldDTO();
descriptionField.setId("description"); descriptionField.setId("description");
descriptionField.setName("描述"); descriptionField.setName("描述");

View File

@ -1,50 +0,0 @@
package io.metersphere.bug.job;
import io.metersphere.system.dto.sdk.LicenseDTO;
import io.metersphere.system.dto.sdk.LicenseInfoDTO;
import io.metersphere.system.service.LicenseService;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.mockito.Mockito;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.util.ReflectionTestUtils;
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BugSyncJobTests {
@Resource
private LicenseService licenseService;
@Test
void test() {
// set licenseService field to null by reflection
BugSyncJob noLicenseMockObj = new BugSyncJob();
ReflectionTestUtils.setField(noLicenseMockObj, "licenseService", null);
noLicenseMockObj.businessExecute(null);
// set mocLicenseService field
BugSyncJob syncJob = new BugSyncJob();
// mock license validate return null
Mockito.when(licenseService.validate()).thenReturn(null);
syncJob.businessExecute(null);
// mock license validate return empty info
Mockito.when(licenseService.validate()).thenReturn(new LicenseDTO());
syncJob.businessExecute(null);
// mock license validate return invalid && license info
LicenseDTO invalid = new LicenseDTO();
invalid.setStatus("invalid");
invalid.setLicense(new LicenseInfoDTO());
Mockito.when(licenseService.validate()).thenReturn(invalid);
syncJob.businessExecute(null);
// mock license validate return valid && license info
LicenseDTO valid = new LicenseDTO();
valid.setStatus("valid");
valid.setLicense(new LicenseInfoDTO());
Mockito.when(licenseService.validate()).thenReturn(valid);
syncJob.businessExecute(null);
}
}

View File

@ -13,7 +13,7 @@ import java.util.List;
public class XpackBugMockServiceImpl implements XpackBugService { public class XpackBugMockServiceImpl implements XpackBugService {
@Override @Override
public void syncPlatformBugsBySchedule() { public void syncPlatformBugsBySchedule(String projectId, String scheduleUser) {
} }

View File

@ -286,7 +286,7 @@ public class ProjectApplicationController {
@Operation(summary = "缺陷管理-同步缺陷配置") @Operation(summary = "缺陷管理-同步缺陷配置")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_BUG_UPDATE) @RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_BUG_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateBugSyncLog(#projectId, #configs)", msClass = ProjectApplicationService.class) @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateBugSyncLog(#projectId, #configs)", msClass = ProjectApplicationService.class)
public void syncBugConfig(@PathVariable("projectId") String projectId, @RequestBody Map<String, String> configs) { public void syncBugConfig(@PathVariable("projectId") String projectId, @RequestBody Map<String, Object> configs) {
projectApplicationService.syncBugConfig(projectId, configs, SessionUtils.getUserId()); projectApplicationService.syncBugConfig(projectId, configs, SessionUtils.getUserId());
} }

View File

@ -19,4 +19,7 @@ public class ProjectTemplateDTO extends Template implements Serializable {
@Schema(description = "是否是默认模板") @Schema(description = "是否是默认模板")
private Boolean enableDefault = false; private Boolean enableDefault = false;
@Schema(description = "是否是平台自动获取模板")
private Boolean enablePlatformDefault = false;
} }

View File

@ -1,21 +0,0 @@
package io.metersphere.project.job;
import io.metersphere.system.schedule.BaseScheduleJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
public class BugSyncJob extends BaseScheduleJob {
@Override
protected void businessExecute(JobExecutionContext context) {
//TODO 定时任务执行 同步issue
}
public static JobKey getJobKey(String projectId) {
return new JobKey(projectId, BugSyncJob.class.getName());
}
public static TriggerKey getTriggerKey(String projectId) {
return new TriggerKey(projectId, BugSyncJob.class.getName());
}
}

View File

@ -8,25 +8,26 @@ import io.metersphere.project.domain.Project;
import io.metersphere.project.domain.ProjectApplication; import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.domain.ProjectApplicationExample; import io.metersphere.project.domain.ProjectApplicationExample;
import io.metersphere.project.dto.ModuleDTO; import io.metersphere.project.dto.ModuleDTO;
import io.metersphere.project.job.BugSyncJob;
import io.metersphere.project.mapper.*; import io.metersphere.project.mapper.*;
import io.metersphere.project.request.ProjectApplicationRequest; import io.metersphere.project.request.ProjectApplicationRequest;
import io.metersphere.project.utils.ModuleSortUtils; import io.metersphere.project.utils.ModuleSortUtils;
import io.metersphere.sdk.constants.OperationLogConstants; import io.metersphere.sdk.constants.OperationLogConstants;
import io.metersphere.sdk.constants.ProjectApplicationType; import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.constants.ScheduleResourceType;
import io.metersphere.sdk.constants.ScheduleType;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.*; import io.metersphere.system.domain.Plugin;
import io.metersphere.system.domain.ServiceIntegration;
import io.metersphere.system.domain.ServiceIntegrationExample;
import io.metersphere.system.domain.User;
import io.metersphere.system.dto.sdk.OptionDTO; import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO; import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.mapper.PluginMapper; import io.metersphere.system.mapper.PluginMapper;
import io.metersphere.system.mapper.ServiceIntegrationMapper; import io.metersphere.system.mapper.ServiceIntegrationMapper;
import io.metersphere.system.schedule.ScheduleService; import io.metersphere.system.service.BaseBugScheduleService;
import io.metersphere.system.service.PlatformPluginService; import io.metersphere.system.service.PlatformPluginService;
import io.metersphere.system.service.PluginLoadService; import io.metersphere.system.service.PluginLoadService;
import io.metersphere.system.service.ServiceIntegrationService; import io.metersphere.system.service.ServiceIntegrationService;
@ -49,9 +50,6 @@ public class ProjectApplicationService {
@Resource @Resource
private ProjectApplicationMapper projectApplicationMapper; private ProjectApplicationMapper projectApplicationMapper;
@Resource
private ScheduleService scheduleService;
@Resource @Resource
private ExtProjectUserRoleMapper extProjectUserRoleMapper; private ExtProjectUserRoleMapper extProjectUserRoleMapper;
@ -105,54 +103,14 @@ public class ProjectApplicationService {
} }
private void doBeforeUpdate(ProjectApplication application, String currentUser) { private void doBeforeUpdate(ProjectApplication application, String currentUser) {
//TODO 后续清理合并完没问题再清理===== 清理报告只有一个定时任务项目配置时不需要在添加定时任务了 BaseBugScheduleService baseBugScheduleService = CommonBeanFactory.getBean(BaseBugScheduleService.class);
/*String type = application.getType(); if (StringUtils.equals(ProjectApplicationType.BUG.BUG_SYNC.name() + "_" + ProjectApplicationType.BUG_SYNC_CONFIG.SYNC_ENABLE.name(),
if (StringUtils.equals(type, ProjectApplicationType.TEST_PLAN.TEST_PLAN_CLEAN_REPORT.name()) application.getType()) && baseBugScheduleService != null) {
|| StringUtils.equals(type, ProjectApplicationType.UI.UI_CLEAN_REPORT.name()) // 缺陷同步配置开启或关闭
|| StringUtils.equals(type, ProjectApplicationType.LOAD_TEST.LOAD_TEST_CLEAN_REPORT.name()) baseBugScheduleService.enableOrNotBugSyncSchedule(application.getProjectId(), currentUser, Boolean.valueOf(application.getTypeValue()));
|| StringUtils.equals(type, ProjectApplicationType.API.API_CLEAN_REPORT.name())) { }
//清除 测试计划/UI测试/性能测试/接口测试 报告 定时任务
this.doHandleSchedule(application, currentUser);
}*/
} }
/*private void doHandleSchedule(ProjectApplication application, String currentUser) {
String typeValue = application.getTypeValue();
String projectId = application.getProjectId();
Boolean enable = BooleanUtils.isTrue(Boolean.valueOf(typeValue));
Schedule schedule = scheduleService.getScheduleByResource(application.getProjectId(), CleanUpReportJob.class.getName());
Optional<Schedule> optional = Optional.ofNullable(schedule);
optional.ifPresentOrElse(s -> {
s.setEnable(enable);
s.setCreateUser(currentUser);
scheduleService.editSchedule(s);
scheduleService.addOrUpdateCronJob(s,
CleanUpReportJob.getJobKey(projectId),
CleanUpReportJob.getTriggerKey(projectId),
CleanUpReportJob.class);
}, () -> {
Schedule request = new Schedule();
request.setName("Clean Report Job");
request.setResourceId(projectId);
request.setKey(projectId);
request.setProjectId(projectId);
request.setEnable(enable);
request.setCreateUser(currentUser);
request.setType(ScheduleType.CRON.name());
// 每天凌晨2点执行清理任务
request.setValue("0 0 2 * * ?");
request.setJob(CleanUpReportJob.class.getName());
request.setResourceType(ScheduleResourceType.CLEAN_REPORT.name());
scheduleService.addSchedule(request);
scheduleService.addOrUpdateCronJob(request,
CleanUpReportJob.getJobKey(projectId),
CleanUpReportJob.getTriggerKey(projectId),
CleanUpReportJob.class);
});
}*/
/** /**
* 获取配置信息 * 获取配置信息
* *
@ -237,10 +195,9 @@ public class ProjectApplicationService {
* @param projectId * @param projectId
* @param configs * @param configs
*/ */
public void syncBugConfig(String projectId, Map<String, String> configs, String currentUser) { public void syncBugConfig(String projectId, Map<String, Object> configs, String currentUser) {
List<ProjectApplication> bugSyncConfigs = configs.entrySet().stream().map(config -> new ProjectApplication(projectId, ProjectApplicationType.BUG.BUG_SYNC.name() + "_" + config.getKey().toUpperCase(), config.getValue())).collect(Collectors.toList()); List<ProjectApplication> bugSyncConfigs = configs.entrySet().stream().map(config -> new ProjectApplication(projectId, ProjectApplicationType.BUG.BUG_SYNC.name() + "_" + config.getKey().toUpperCase(),
//处理同步缺陷定时任务配置 (config.getValue() instanceof String) ? config.getValue().toString() : JSON.toJSONString(config.getValue()))).toList();
doSaveOrUpdateSchedule(bugSyncConfigs, projectId, currentUser);
ProjectApplicationExample example = new ProjectApplicationExample(); ProjectApplicationExample example = new ProjectApplicationExample();
example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.BUG.BUG_SYNC.name() + "%"); example.createCriteria().andProjectIdEqualTo(projectId).andTypeLike(ProjectApplicationType.BUG.BUG_SYNC.name() + "%");
if (projectApplicationMapper.countByExample(example) > 0) { if (projectApplicationMapper.countByExample(example) > 0) {
@ -251,47 +208,13 @@ public class ProjectApplicationService {
} else { } else {
projectApplicationMapper.batchInsert(bugSyncConfigs); projectApplicationMapper.batchInsert(bugSyncConfigs);
} }
} // 更新缺陷定时任务配置
BaseBugScheduleService baseBugScheduleService = CommonBeanFactory.getBean(BaseBugScheduleService.class);
private void doSaveOrUpdateSchedule(List<ProjectApplication> bugSyncConfigs, String projectId, String currentUser) { if (baseBugScheduleService != null) {
List<ProjectApplication> syncCron = bugSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.BUG.BUG_SYNC.name() + "_" + ProjectApplicationType.BUG_SYNC_CONFIG.CRON_EXPRESSION.name())).collect(Collectors.toList()); baseBugScheduleService.updateBugSyncScheduleConfig(bugSyncConfigs, projectId, currentUser);
List<ProjectApplication> syncEnable = bugSyncConfigs.stream().filter(config -> config.getType().equals(ProjectApplicationType.BUG.BUG_SYNC.name() + "_" + ProjectApplicationType.BUG_SYNC_CONFIG.SYNC_ENABLE.name())).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(syncCron)) {
Boolean enable = Boolean.valueOf(syncEnable.get(0).getTypeValue());
String typeValue = syncCron.get(0).getTypeValue();
Schedule schedule = scheduleService.getScheduleByResource(projectId, BugSyncJob.class.getName());
Optional<Schedule> optional = Optional.ofNullable(schedule);
optional.ifPresentOrElse(s -> {
s.setEnable(enable);
s.setValue(typeValue);
scheduleService.editSchedule(s);
scheduleService.addOrUpdateCronJob(s,
BugSyncJob.getJobKey(projectId),
BugSyncJob.getTriggerKey(projectId),
BugSyncJob.class);
}, () -> {
Schedule request = new Schedule();
request.setName("Bug Sync Job");
request.setResourceId(projectId);
request.setKey(projectId);
request.setProjectId(projectId);
request.setEnable(enable);
request.setCreateUser(currentUser);
request.setType(ScheduleType.CRON.name());
// 每天凌晨2点执行清理任务
request.setValue(typeValue);
request.setJob(BugSyncJob.class.getName());
request.setResourceType(ScheduleResourceType.BUG_SYNC.name());
scheduleService.addSchedule(request);
scheduleService.addOrUpdateCronJob(request,
BugSyncJob.getJobKey(projectId),
BugSyncJob.getTriggerKey(projectId),
BugSyncJob.class);
});
} }
} }
/** /**
* 获取同步缺陷配置 * 获取同步缺陷配置
* *
@ -604,26 +527,6 @@ public class ProjectApplicationService {
return getPluginName(platformKeyConfig.getTypeValue()); return getPluginName(platformKeyConfig.getTypeValue());
} }
/**
* 过滤出能够同步的项目
*
* @param projectIds 项目ID集合
* @return 同步的项目ID集合
*/
public List<String> filterNeedSyncProject(List<String> projectIds) {
Iterator<String> iterator = projectIds.iterator();
while (iterator.hasNext()) {
String projectId = iterator.next();
ServiceIntegration serviceIntegration = getPlatformServiceIntegrationWithSyncOrDemand(projectId, true);
String platformName = getPlatformName(projectId);
if (serviceIntegration == null || StringUtils.equals("Local", platformName)) {
// 项目未配置第三方平台 或者 项目同步配置为Local
iterator.remove();
}
}
return projectIds;
}
/** /**
* 获取项目同步机制 * 获取项目同步机制
* *

View File

@ -62,10 +62,37 @@ public class ProjectTemplateService extends BaseTemplateService {
public List list(String projectId, String scene) { public List list(String projectId, String scene) {
projectService.checkResourceExist(projectId); projectService.checkResourceExist(projectId);
List<Template> templates = super.list(projectId, scene); List<Template> templates = super.list(projectId, scene);
List<ProjectTemplateDTO> templateDTOS = templates.stream().map(item -> BeanUtils.copyBean(new ProjectTemplateDTO(), item)).collect(Collectors.toList());
// 缺陷模板需要获取第三方平台模板 // 缺陷模板需要获取第三方平台模板
templates = addPluginBugTemplate(projectId, scene, templates); if (StringUtils.equals(scene, TemplateScene.BUG.name())) {
Template pluginBugTemplate = getPluginBugTemplate(projectId);
if (pluginBugTemplate != null) {
ProjectTemplateDTO pluginTemplate = BeanUtils.copyBean(new ProjectTemplateDTO(), pluginBugTemplate);
pluginTemplate.setEnablePlatformDefault(true);
templateDTOS.add(pluginTemplate);
}
}
// 标记默认模板 // 标记默认模板
return tagDefaultTemplate(projectId, scene, templates); // 查询项目下设置中配置的默认模板
String defaultProjectId = getDefaultTemplateId(projectId, scene);
ProjectTemplateDTO defaultTemplate = templateDTOS.stream()
.filter(t -> StringUtils.equals(defaultProjectId, t.getId()))
.findFirst()
.orElse(null);
// 如果查询不到默认模板设置内置模板为默认模板
if (defaultTemplate == null) {
Optional<ProjectTemplateDTO> internalTemplate = templateDTOS.stream()
.filter(ProjectTemplateDTO::getInternal).findFirst();
if (internalTemplate.isPresent()) {
defaultTemplate = internalTemplate.get();
}
}
if (defaultTemplate != null) {
defaultTemplate.setEnableDefault(true);
}
return templateDTOS;
} }
/** /**

View File

@ -31,9 +31,7 @@ import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND; import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND;
@ -768,12 +766,5 @@ public class ProjectApplicationControllerTests extends BaseTest {
// 获取同步机制 // 获取同步机制
Assertions.assertTrue(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application")); Assertions.assertTrue(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application"));
Assertions.assertFalse(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application-not-exist")); Assertions.assertFalse(projectApplicationService.isPlatformSyncMethodByIncrement("default-project-for-application-not-exist"));
// 过滤Local平台项目
projectApplicationService.filterNeedSyncProject(new ArrayList<>(new ArrayList<>(List.of("default-project-for-application"))));
projectApplicationService.filterNeedSyncProject(new ArrayList<>(new ArrayList<>(List.of("default-project-for-application-not-exist"))));
// 移除插件测试
basePluginTestService.deleteJiraPlugin();
projectApplicationService.filterNeedSyncProject(new ArrayList<>(new ArrayList<>(List.of("default-project-for-application"))));
} }
} }

View File

@ -0,0 +1,24 @@
package io.metersphere.system.service;
import io.metersphere.project.domain.ProjectApplication;
import java.util.List;
public interface BaseBugScheduleService {
/**
* 更新项目的缺陷同步定时任务
* @param bugSyncConfigs 配置
* @param projectId 项目ID
* @param currentUser 当前用户
*/
void updateBugSyncScheduleConfig(List<ProjectApplication> bugSyncConfigs, String projectId, String currentUser);
/**
* 启用或禁用缺陷同步定时任务
* @param projectId 项目ID
* @param currentUser 当前用户
* @param enable 开启或禁用
*/
void enableOrNotBugSyncSchedule(String projectId, String currentUser, Boolean enable);
}

View File

@ -162,6 +162,7 @@
<exclude>io/metersphere/sdk/**</exclude> <exclude>io/metersphere/sdk/**</exclude>
<exclude>io/metersphere/provider/**</exclude> <exclude>io/metersphere/provider/**</exclude>
<exclude>io/metersphere/plugin/**</exclude> <exclude>io/metersphere/plugin/**</exclude>
<exclude>io/metersphere/*/job/**</exclude>
</excludes> </excludes>
</configuration> </configuration>
<executions> <executions>