增加生成后端服务代码。
This commit is contained in:
parent
7bc5f66967
commit
1a6deb77d4
@ -30,7 +30,7 @@
|
||||
@Slf4j
|
||||
@Service
|
||||
@ServiceType(DATABASE)
|
||||
public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, ExternalSystemDTO, Long>
|
||||
public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, ExternalSystemDTO, ExternalSystemQuery, Long>
|
||||
implements IExternalSystemService {
|
||||
|
||||
@Override
|
||||
|
||||
@ -2,31 +2,58 @@ package com.qqchen.deploy.backend.deploy.api;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsManagerService;
|
||||
import com.qqchen.deploy.backend.framework.api.Response;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* Jenkins构建信息 Controller
|
||||
* Jenkins管理API控制器
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/jenkins-manager")
|
||||
@Tag(name = "Jenkins三方系统管理", description = "Jenkins三方系统管理")
|
||||
@Tag(name = "Jenkins管理", description = "Jenkins管理相关接口")
|
||||
public class JenkinsManagerApiController {
|
||||
|
||||
|
||||
@Resource
|
||||
private IJenkinsManagerService jenkinsManagerService;
|
||||
|
||||
@GetMapping("/views/page")
|
||||
public Response<Void> page() {
|
||||
return Response.success(jenkinsManagerService.viewsPage());
|
||||
@Operation(summary = "同步所有Jenkins数据")
|
||||
@PostMapping("/{externalSystemId}/sync-all")
|
||||
public Response<Void> syncAll(
|
||||
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
|
||||
) {
|
||||
jenkinsManagerService.syncAll(externalSystemId);
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "同步Jenkins视图")
|
||||
@PostMapping("/{externalSystemId}/sync-views")
|
||||
public Response<Void> syncViews(
|
||||
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
|
||||
) {
|
||||
jenkinsManagerService.syncViews(externalSystemId);
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "同步Jenkins任务")
|
||||
@PostMapping("/{externalSystemId}/sync-jobs")
|
||||
public Response<Void> syncJobs(
|
||||
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
|
||||
) {
|
||||
jenkinsManagerService.syncJobs(externalSystemId);
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "同步Jenkins构建信息")
|
||||
@PostMapping("/{externalSystemId}/sync-builds")
|
||||
public Response<Void> syncBuilds(
|
||||
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
|
||||
) {
|
||||
jenkinsManagerService.syncBuilds(externalSystemId);
|
||||
return Response.success();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.qqchen.deploy.backend.deploy.integration.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Jenkins健康报告响应对象
|
||||
* 用于表示Jenkins任务的健康状态,包括构建稳定性、测试结果、代码覆盖率等
|
||||
*/
|
||||
@Data
|
||||
public class JenkinsHealthReportResponse {
|
||||
|
||||
/**
|
||||
* 健康检查描述
|
||||
* 例如: "Build stability: No recent builds failed"
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 健康分数(0-100)
|
||||
*/
|
||||
private Integer score;
|
||||
|
||||
/**
|
||||
* 健康检查类型
|
||||
* 例如: "Build stability", "Test result", "Code coverage"
|
||||
*/
|
||||
@JsonProperty("_class")
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 图标名称
|
||||
* 例如: "health-80plus" 表示健康度大于80%
|
||||
*/
|
||||
private String iconName;
|
||||
|
||||
/**
|
||||
* 图标URL
|
||||
*/
|
||||
private String iconUrl;
|
||||
}
|
||||
@ -117,6 +117,11 @@ public class JenkinsJobResponse {
|
||||
*/
|
||||
private List<ParameterDefinition> parameterDefinitions;
|
||||
|
||||
/**
|
||||
* 健康报告列表
|
||||
*/
|
||||
private List<JenkinsHealthReportResponse> healthReports;
|
||||
|
||||
@Data
|
||||
public static class BuildInfo {
|
||||
private Integer number;
|
||||
|
||||
@ -1,12 +1,35 @@
|
||||
package com.qqchen.deploy.backend.deploy.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsBuild;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Jenkins构建信息 Repository
|
||||
* Jenkins构建信息仓库接口
|
||||
*/
|
||||
@Repository
|
||||
public interface IJenkinsBuildRepository extends IBaseRepository<JenkinsBuild, Long> {
|
||||
|
||||
/**
|
||||
* 根据外部系统ID、任务ID和构建号查询构建信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param jobId 任务ID
|
||||
* @param buildNumber 构建号
|
||||
* @return 构建信息
|
||||
*/
|
||||
Optional<JenkinsBuild> findByExternalSystemIdAndJobIdAndBuildNumber(
|
||||
Long externalSystemId, Long jobId, Integer buildNumber);
|
||||
|
||||
/**
|
||||
* 根据外部系统ID和任务ID查询所有构建信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param jobId 任务ID
|
||||
* @return 构建信息列表
|
||||
*/
|
||||
List<JenkinsBuild> findByExternalSystemIdAndJobId(Long externalSystemId, Long jobId);
|
||||
}
|
||||
@ -1,12 +1,34 @@
|
||||
package com.qqchen.deploy.backend.deploy.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Jenkins工作 Repository
|
||||
* Jenkins任务仓库接口
|
||||
*/
|
||||
@Repository
|
||||
public interface IJenkinsJobRepository extends IBaseRepository<JenkinsJob, Long> {
|
||||
|
||||
/**
|
||||
* 根据外部系统ID、视图ID和任务名称查询任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewId 视图ID
|
||||
* @param jobName 任务名称
|
||||
* @return 任务对象
|
||||
*/
|
||||
Optional<JenkinsJob> findByExternalSystemIdAndViewIdAndJobName(Long externalSystemId, Long viewId, String jobName);
|
||||
|
||||
/**
|
||||
* 根据外部系统ID和视图ID查询所有任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewId 视图ID
|
||||
* @return 任务列表
|
||||
*/
|
||||
List<JenkinsJob> findByExternalSystemIdAndViewId(Long externalSystemId, Long viewId);
|
||||
}
|
||||
@ -1,12 +1,32 @@
|
||||
package com.qqchen.deploy.backend.deploy.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Jenkins视图 Repository
|
||||
* Jenkins视图仓库接口
|
||||
*/
|
||||
@Repository
|
||||
public interface IJenkinsViewRepository extends IBaseRepository<JenkinsView, Long> {
|
||||
|
||||
/**
|
||||
* 根据外部系统ID和视图名称查询视图
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewName 视图名称
|
||||
* @return 视图对象
|
||||
*/
|
||||
Optional<JenkinsView> findByExternalSystemIdAndViewName(Long externalSystemId, String viewName);
|
||||
|
||||
/**
|
||||
* 根据外部系统ID查询所有视图
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 视图列表
|
||||
*/
|
||||
List<JenkinsView> findByExternalSystemId(Long externalSystemId);
|
||||
}
|
||||
@ -9,4 +9,30 @@ import com.qqchen.deploy.backend.deploy.query.JenkinsBuildQuery;
|
||||
* Jenkins构建信息 Service接口
|
||||
*/
|
||||
public interface IJenkinsBuildService extends IBaseService<JenkinsBuild, JenkinsBuildDTO, JenkinsBuildQuery, Long> {
|
||||
|
||||
/**
|
||||
* 同步指定任务的构建信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param jobId 任务ID
|
||||
* @return 同步的构建数量
|
||||
*/
|
||||
Integer syncBuilds(Long externalSystemId, Long jobId);
|
||||
|
||||
/**
|
||||
* 同步指定视图下所有任务的构建信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewId 视图ID
|
||||
* @return 同步的构建总数
|
||||
*/
|
||||
Integer syncBuildsByView(Long externalSystemId, Long viewId);
|
||||
|
||||
/**
|
||||
* 同步外部系统下所有构建信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 同步的构建总数
|
||||
*/
|
||||
Integer syncAllBuilds(Long externalSystemId);
|
||||
}
|
||||
@ -6,7 +6,24 @@ import com.qqchen.deploy.backend.deploy.dto.JenkinsJobDTO;
|
||||
import com.qqchen.deploy.backend.deploy.query.JenkinsJobQuery;
|
||||
|
||||
/**
|
||||
* Jenkins工作 Service接口
|
||||
* Jenkins任务 Service接口
|
||||
*/
|
||||
public interface IJenkinsJobService extends IBaseService<JenkinsJob, JenkinsJobDTO, JenkinsJobQuery, Long> {
|
||||
|
||||
/**
|
||||
* 同步指定视图下的Jenkins任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewId 视图ID
|
||||
* @return 同步的任务数量
|
||||
*/
|
||||
Integer syncJobsByView(Long externalSystemId, Long viewId);
|
||||
|
||||
/**
|
||||
* 同步外部系统下所有视图的Jenkins任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 同步的任务总数
|
||||
*/
|
||||
Integer syncJobs(Long externalSystemId);
|
||||
}
|
||||
@ -1,7 +1,35 @@
|
||||
package com.qqchen.deploy.backend.deploy.service;
|
||||
|
||||
|
||||
/**
|
||||
* Jenkins管理服务接口
|
||||
*/
|
||||
public interface IJenkinsManagerService {
|
||||
|
||||
Void viewsPage();
|
||||
/**
|
||||
* 同步Jenkins所有数据(视图、任务、构建信息)
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
*/
|
||||
void syncAll(Long externalSystemId);
|
||||
|
||||
/**
|
||||
* 同步Jenkins视图
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
*/
|
||||
void syncViews(Long externalSystemId);
|
||||
|
||||
/**
|
||||
* 同步Jenkins任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
*/
|
||||
void syncJobs(Long externalSystemId);
|
||||
|
||||
/**
|
||||
* 同步Jenkins构建信息
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
*/
|
||||
void syncBuilds(Long externalSystemId);
|
||||
}
|
||||
@ -1,12 +1,20 @@
|
||||
package com.qqchen.deploy.backend.deploy.service;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
|
||||
import com.qqchen.deploy.backend.deploy.dto.JenkinsViewDTO;
|
||||
import com.qqchen.deploy.backend.deploy.query.JenkinsViewQuery;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
|
||||
/**
|
||||
* Jenkins视图 Service接口
|
||||
*/
|
||||
public interface IJenkinsViewService extends IBaseService<JenkinsView, JenkinsViewDTO, JenkinsViewQuery, Long> {
|
||||
|
||||
/**
|
||||
* 同步Jenkins视图
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 同步的视图数量
|
||||
*/
|
||||
Integer syncViews(Long externalSystemId);
|
||||
}
|
||||
@ -1,12 +1,34 @@
|
||||
package com.qqchen.deploy.backend.deploy.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsBuild;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
|
||||
import com.qqchen.deploy.backend.deploy.dto.JenkinsBuildDTO;
|
||||
import com.qqchen.deploy.backend.deploy.query.JenkinsBuildQuery;
|
||||
import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration;
|
||||
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsBuildResponse;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IJenkinsBuildRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IJenkinsJobRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IJenkinsViewRepository;
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsBuildService;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Jenkins构建信息 Service实现
|
||||
@ -15,4 +37,158 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, JenkinsBuildDTO, JenkinsBuildQuery, Long>
|
||||
implements IJenkinsBuildService {
|
||||
|
||||
@Resource
|
||||
private IExternalSystemRepository externalSystemRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsViewRepository jenkinsViewRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsJobRepository jenkinsJobRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsBuildRepository jenkinsBuildRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsServiceIntegration jenkinsServiceIntegration;
|
||||
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer syncAllBuilds(Long externalSystemId) {
|
||||
// 1. 查询外部系统
|
||||
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
|
||||
|
||||
// 2. 查询所有视图
|
||||
List<JenkinsView> views = jenkinsViewRepository.findByExternalSystemId(externalSystemId);
|
||||
if (views.isEmpty()) {
|
||||
log.info("No views found for external system: {}", externalSystemId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 同步每个视图下的构建信息
|
||||
int totalSyncedBuilds = 0;
|
||||
for (JenkinsView view : views) {
|
||||
try {
|
||||
Integer syncedBuilds = syncBuildsByView(externalSystemId, view.getId());
|
||||
totalSyncedBuilds += syncedBuilds;
|
||||
log.info("Successfully synchronized {} builds for view: {}", syncedBuilds, view.getViewName());
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to sync builds for view: {}", view.getViewName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Successfully synchronized total {} builds for external system: {}",
|
||||
totalSyncedBuilds, externalSystemId);
|
||||
return totalSyncedBuilds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer syncBuildsByView(Long externalSystemId, Long viewId) {
|
||||
// 1. 查询视图下的所有任务
|
||||
List<JenkinsJob> jobs = jenkinsJobRepository.findByExternalSystemIdAndViewId(externalSystemId, viewId);
|
||||
if (jobs.isEmpty()) {
|
||||
log.info("No jobs found for view: {}", viewId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. 同步每个任务的构建信息
|
||||
int totalSyncedBuilds = 0;
|
||||
for (JenkinsJob job : jobs) {
|
||||
try {
|
||||
Integer syncedBuilds = syncBuilds(externalSystemId, job.getId());
|
||||
totalSyncedBuilds += syncedBuilds;
|
||||
log.info("Successfully synchronized {} builds for job: {}", syncedBuilds, job.getJobName());
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to sync builds for job: {}", job.getJobName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return totalSyncedBuilds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer syncBuilds(Long externalSystemId, Long jobId) {
|
||||
// 1. 查询外部系统和任务
|
||||
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
|
||||
|
||||
JenkinsJob jenkinsJob = jenkinsJobRepository.findById(jobId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
|
||||
|
||||
// 2. 调用Jenkins API获取构建列表
|
||||
List<JenkinsBuildResponse> buildResponses = jenkinsServiceIntegration.listBuilds(externalSystem, jenkinsJob.getJobName());
|
||||
if (buildResponses.isEmpty()) {
|
||||
log.info("No builds found for job: {}", jenkinsJob.getJobName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 转换并保存/更新构建数据
|
||||
List<JenkinsBuild> jenkinsBuilds = new ArrayList<>();
|
||||
for (JenkinsBuildResponse buildResponse : buildResponses) {
|
||||
// 查找是否存在相同的构建
|
||||
Optional<JenkinsBuild> existingBuild = jenkinsBuildRepository
|
||||
.findByExternalSystemIdAndJobIdAndBuildNumber(externalSystemId, jobId, buildResponse.getNumber());
|
||||
|
||||
JenkinsBuild jenkinsBuild;
|
||||
if (existingBuild.isPresent()) {
|
||||
// 更新已存在的构建
|
||||
jenkinsBuild = existingBuild.get();
|
||||
updateBuildFromResponse(jenkinsBuild, buildResponse);
|
||||
log.debug("Updating existing Jenkins build: {} for job: {}",
|
||||
jenkinsBuild.getBuildNumber(), jenkinsJob.getJobName());
|
||||
} else {
|
||||
// 创建新的构建
|
||||
jenkinsBuild = new JenkinsBuild();
|
||||
jenkinsBuild.setExternalSystemId(externalSystemId);
|
||||
jenkinsBuild.setJobId(jobId);
|
||||
jenkinsBuild.setBuildNumber(buildResponse.getNumber());
|
||||
updateBuildFromResponse(jenkinsBuild, buildResponse);
|
||||
log.debug("Creating new Jenkins build: {} for job: {}",
|
||||
jenkinsBuild.getBuildNumber(), jenkinsJob.getJobName());
|
||||
}
|
||||
jenkinsBuilds.add(jenkinsBuild);
|
||||
}
|
||||
|
||||
// 4. 批量保存或更新
|
||||
jenkinsBuildRepository.saveAll(jenkinsBuilds);
|
||||
|
||||
log.info("Successfully synchronized {} Jenkins builds for job: {}",
|
||||
jenkinsBuilds.size(), jenkinsJob.getJobName());
|
||||
|
||||
return jenkinsBuilds.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从API响应更新构建信息
|
||||
*/
|
||||
private void updateBuildFromResponse(JenkinsBuild jenkinsBuild, JenkinsBuildResponse response) {
|
||||
jenkinsBuild.setBuildUrl(response.getUrl());
|
||||
jenkinsBuild.setBuildStatus(response.getResult());
|
||||
jenkinsBuild.setDuration(response.getDuration());
|
||||
|
||||
// 转换时间戳为LocalDateTime
|
||||
if (response.getTimestamp() != null) {
|
||||
LocalDateTime startTime = LocalDateTime.ofInstant(
|
||||
Instant.ofEpochMilli(response.getTimestamp()),
|
||||
ZoneId.systemDefault()
|
||||
);
|
||||
jenkinsBuild.setStarttime(startTime);
|
||||
}
|
||||
|
||||
// 将构建参数转换为JSON字符串
|
||||
try {
|
||||
String actionsJson = objectMapper.writeValueAsString(response.getActions());
|
||||
jenkinsBuild.setActions(actionsJson);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("Failed to serialize build actions", e);
|
||||
jenkinsBuild.setActions("{}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,231 @@
|
||||
package com.qqchen.deploy.backend.deploy.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
|
||||
import com.qqchen.deploy.backend.deploy.dto.JenkinsJobDTO;
|
||||
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsHealthReportResponse;
|
||||
import com.qqchen.deploy.backend.deploy.query.JenkinsJobQuery;
|
||||
import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration;
|
||||
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsJobResponse;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IJenkinsJobRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IJenkinsViewRepository;
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsJobService;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalDouble;
|
||||
|
||||
/**
|
||||
* Jenkins工作 Service实现
|
||||
* Jenkins任务 Service实现
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJobDTO, JenkinsJobQuery, Long>
|
||||
implements IJenkinsJobService {
|
||||
|
||||
@Resource
|
||||
private IExternalSystemRepository externalSystemRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsViewRepository jenkinsViewRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsJobRepository jenkinsJobRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsServiceIntegration jenkinsServiceIntegration;
|
||||
|
||||
/**
|
||||
* 同步外部系统下所有视图的Jenkins任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 同步的任务总数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer syncJobs(Long externalSystemId) {
|
||||
// 1. 查询外部系统
|
||||
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
|
||||
|
||||
// 2. 查询该外部系统下的所有视图
|
||||
List<JenkinsView> views = jenkinsViewRepository.findByExternalSystemId(externalSystemId);
|
||||
if (views.isEmpty()) {
|
||||
log.info("No views found for external system: {}", externalSystemId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 遍历所有视图,同步每个视图下的任务
|
||||
int totalSyncedJobs = 0;
|
||||
for (JenkinsView view : views) {
|
||||
try {
|
||||
Integer syncedJobs = syncJobsByView(externalSystemId, view.getId());
|
||||
totalSyncedJobs += syncedJobs;
|
||||
log.info("Successfully synchronized {} jobs for view: {}", syncedJobs, view.getViewName());
|
||||
} catch (Exception e) {
|
||||
// 记录错误但继续同步其他视图
|
||||
log.error("Failed to sync jobs for view: {}", view.getViewName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Successfully synchronized total {} jobs for external system: {}",
|
||||
totalSyncedJobs, externalSystemId);
|
||||
return totalSyncedJobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步指定视图下的Jenkins任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewId 视图ID
|
||||
* @return 同步的任务数量
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer syncJobsByView(Long externalSystemId, Long viewId) {
|
||||
// 1. 查询外部系统和视图
|
||||
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
|
||||
|
||||
JenkinsView jenkinsView = jenkinsViewRepository.findById(viewId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
|
||||
|
||||
// 2. 调用Jenkins API获取任务列表
|
||||
List<JenkinsJobResponse> jobResponses = jenkinsServiceIntegration.listJobs(externalSystem, jenkinsView.getViewName());
|
||||
if (jobResponses.isEmpty()) {
|
||||
log.info("No jobs found in Jenkins view: {}", jenkinsView.getViewName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 转换并保存/更新任务数据
|
||||
List<JenkinsJob> jenkinsJobs = new ArrayList<>();
|
||||
for (JenkinsJobResponse jobResponse : jobResponses) {
|
||||
// 查找是否存在相同的任务
|
||||
Optional<JenkinsJob> existingJob = jenkinsJobRepository
|
||||
.findByExternalSystemIdAndViewIdAndJobName(externalSystemId, viewId, jobResponse.getName());
|
||||
|
||||
JenkinsJob jenkinsJob;
|
||||
if (existingJob.isPresent()) {
|
||||
// 更新已存在的任务
|
||||
jenkinsJob = existingJob.get();
|
||||
updateJobFromResponse(jenkinsJob, jobResponse);
|
||||
log.debug("Updating existing Jenkins job: {}", jenkinsJob.getJobName());
|
||||
} else {
|
||||
// 创建新的任务
|
||||
jenkinsJob = new JenkinsJob();
|
||||
jenkinsJob.setExternalSystemId(externalSystemId);
|
||||
jenkinsJob.setViewId(viewId);
|
||||
jenkinsJob.setJobName(jobResponse.getName());
|
||||
updateJobFromResponse(jenkinsJob, jobResponse);
|
||||
log.debug("Creating new Jenkins job: {}", jenkinsJob.getJobName());
|
||||
}
|
||||
jenkinsJobs.add(jenkinsJob);
|
||||
}
|
||||
|
||||
// 4. 批量保存或更新
|
||||
jenkinsJobRepository.saveAll(jenkinsJobs);
|
||||
|
||||
log.info("Successfully synchronized {} Jenkins jobs for view: {}", jenkinsJobs.size(), jenkinsView.getViewName());
|
||||
|
||||
return jenkinsJobs.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从API响应更新任务信息
|
||||
*/
|
||||
private void updateJobFromResponse(JenkinsJob jenkinsJob, JenkinsJobResponse response) {
|
||||
jenkinsJob.setBuildable(response.getBuildable());
|
||||
jenkinsJob.setDescription(response.getDescription());
|
||||
jenkinsJob.setJobUrl(response.getUrl());
|
||||
jenkinsJob.setNextBuildNumber(response.getNextBuildNumber());
|
||||
|
||||
// 设置最后构建信息
|
||||
if (response.getLastBuild() != null) {
|
||||
jenkinsJob.setLastBuildNumber(response.getLastBuild().getNumber());
|
||||
// 根据颜色判断构建状态
|
||||
jenkinsJob.setLastBuildStatus(convertColorToStatus(response.getColor()));
|
||||
}
|
||||
|
||||
// 设置健康分数
|
||||
jenkinsJob.setHealthReportScore(calculateHealthScore(response));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Jenkins颜色转换为构建状态
|
||||
*/
|
||||
private String convertColorToStatus(String color) {
|
||||
if (color == null) return "UNKNOWN";
|
||||
return switch (color) {
|
||||
case "blue" -> "SUCCESS";
|
||||
case "red" -> "FAILURE";
|
||||
case "yellow" -> "UNSTABLE";
|
||||
case "grey", "disabled" -> "DISABLED";
|
||||
case "notbuilt" -> "NOT_BUILT";
|
||||
case "aborted" -> "ABORTED";
|
||||
default -> "UNKNOWN";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算任务健康分数
|
||||
* Jenkins健康分数基于以下几个方面:
|
||||
* 1. 构建稳定性(最近构建的成功率)
|
||||
* 2. 测试结果
|
||||
* 3. 代码覆盖率
|
||||
* 4. 静态代码分析结果等
|
||||
*
|
||||
* @param response Jenkins任务响应
|
||||
* @return 健康分数(0-100)
|
||||
*/
|
||||
private Integer calculateHealthScore(JenkinsJobResponse response) {
|
||||
// 如果任务被禁用,返回0分
|
||||
if (!response.getBuildable()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取任务的健康报告
|
||||
List<JenkinsHealthReportResponse> healthReports = response.getHealthReports();
|
||||
if (healthReports == null || healthReports.isEmpty()) {
|
||||
// 如果没有健康报告,根据最近构建状态判断
|
||||
return calculateScoreByBuildStatus(response);
|
||||
}
|
||||
|
||||
// 如果有多个健康报告,取平均分
|
||||
OptionalDouble avgScore = healthReports.stream()
|
||||
.mapToInt(JenkinsHealthReportResponse::getScore)
|
||||
.average();
|
||||
|
||||
return avgScore.isPresent() ? (int) avgScore.getAsDouble() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据构建状态计算分数
|
||||
*/
|
||||
private Integer calculateScoreByBuildStatus(JenkinsJobResponse response) {
|
||||
String color = response.getColor();
|
||||
if (color == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return switch (color) {
|
||||
case "blue" -> 100; // 成功
|
||||
case "yellow" -> 70; // 不稳定
|
||||
case "red" -> 40; // 失败
|
||||
case "grey" -> 0; // 禁用
|
||||
case "disabled" -> 0; // 禁用
|
||||
case "notbuilt" -> 50; // 未构建
|
||||
case "aborted" -> 60; // 中断
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,16 +1,70 @@
|
||||
package com.qqchen.deploy.backend.deploy.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsManagerService;
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsViewService;
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsJobService;
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsBuildService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Jenkins管理服务实现
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class JenkinsManagerServiceImpl implements IJenkinsManagerService {
|
||||
|
||||
@Resource
|
||||
private IJenkinsViewService jenkinsViewService;
|
||||
|
||||
@Resource
|
||||
private IJenkinsJobService jenkinsJobService;
|
||||
|
||||
@Resource
|
||||
private IJenkinsBuildService jenkinsBuildService;
|
||||
|
||||
@Override
|
||||
public Void viewsPage() {
|
||||
return null;
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncAll(Long externalSystemId) {
|
||||
// 1. 同步视图
|
||||
Integer viewCount = jenkinsViewService.syncViews(externalSystemId);
|
||||
log.info("Synchronized {} views", viewCount);
|
||||
|
||||
// 2. 同步任务
|
||||
Integer jobCount = jenkinsJobService.syncJobs(externalSystemId);
|
||||
log.info("Synchronized {} jobs", jobCount);
|
||||
|
||||
// 3. 同步构建信息
|
||||
Integer buildCount = jenkinsBuildService.syncAllBuilds(externalSystemId);
|
||||
log.info("Synchronized {} builds", buildCount);
|
||||
|
||||
log.info("Successfully synchronized {} views, {} jobs, and {} builds",
|
||||
viewCount, jobCount, buildCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncViews(Long externalSystemId) {
|
||||
// 同步视图
|
||||
Integer viewCount = jenkinsViewService.syncViews(externalSystemId);
|
||||
log.info("Successfully synchronized {} views", viewCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncJobs(Long externalSystemId) {
|
||||
// 同步任务
|
||||
Integer jobCount = jenkinsJobService.syncJobs(externalSystemId);
|
||||
log.info("Successfully synchronized {} jobs", jobCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncBuilds(Long externalSystemId) {
|
||||
// 同步构建信息
|
||||
Integer buildCount = jenkinsBuildService.syncAllBuilds(externalSystemId);
|
||||
log.info("Successfully synchronized {} builds", buildCount);
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,25 @@
|
||||
package com.qqchen.deploy.backend.deploy.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
|
||||
import com.qqchen.deploy.backend.deploy.dto.JenkinsViewDTO;
|
||||
import com.qqchen.deploy.backend.deploy.query.JenkinsViewQuery;
|
||||
import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration;
|
||||
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsViewResponse;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
|
||||
import com.qqchen.deploy.backend.deploy.repository.IJenkinsViewRepository;
|
||||
import com.qqchen.deploy.backend.deploy.service.IJenkinsViewService;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Jenkins视图 Service实现
|
||||
@ -15,4 +28,68 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, JenkinsViewDTO, JenkinsViewQuery, Long>
|
||||
implements IJenkinsViewService {
|
||||
|
||||
@Resource
|
||||
private IExternalSystemRepository externalSystemRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsViewRepository jenkinsViewRepository;
|
||||
|
||||
@Resource
|
||||
private IJenkinsServiceIntegration jenkinsServiceIntegration;
|
||||
|
||||
/**
|
||||
* 同步Jenkins视图
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @return 同步的视图数量
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer syncViews(Long externalSystemId) {
|
||||
// 1. 查询外部系统
|
||||
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
|
||||
|
||||
// 2. 调用Jenkins API获取视图列表
|
||||
List<JenkinsViewResponse> viewResponses = jenkinsServiceIntegration.listViews(externalSystem);
|
||||
if (viewResponses.isEmpty()) {
|
||||
log.info("No views found in Jenkins system: {}", externalSystemId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. 转换并保存/更新视图数据
|
||||
List<JenkinsView> jenkinsViews = new ArrayList<>();
|
||||
for (JenkinsViewResponse viewResponse : viewResponses) {
|
||||
// 查找是否存在相同的视图
|
||||
Optional<JenkinsView> existingView = jenkinsViewRepository
|
||||
.findByExternalSystemIdAndViewName(externalSystemId, viewResponse.getName());
|
||||
|
||||
JenkinsView jenkinsView;
|
||||
if (existingView.isPresent()) {
|
||||
// 更新已存在的视图
|
||||
jenkinsView = existingView.get();
|
||||
jenkinsView.setViewUrl(viewResponse.getUrl());
|
||||
jenkinsView.setDescription(viewResponse.getDescription());
|
||||
log.debug("Updating existing Jenkins view: {}", jenkinsView.getViewName());
|
||||
} else {
|
||||
// 创建新的视图
|
||||
jenkinsView = new JenkinsView();
|
||||
jenkinsView.setViewName(viewResponse.getName());
|
||||
jenkinsView.setViewUrl(viewResponse.getUrl());
|
||||
jenkinsView.setDescription(viewResponse.getDescription());
|
||||
jenkinsView.setExternalSystemId(externalSystemId);
|
||||
log.debug("Creating new Jenkins view: {}", jenkinsView.getViewName());
|
||||
}
|
||||
jenkinsViews.add(jenkinsView);
|
||||
}
|
||||
|
||||
// 4. 批量保存或更新
|
||||
jenkinsViewRepository.saveAll(jenkinsViews);
|
||||
|
||||
log.info("Successfully synchronized {} Jenkins views for external system: {}",
|
||||
jenkinsViews.size(), externalSystemId);
|
||||
|
||||
return jenkinsViews.size();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user