增加生成后端服务代码。
This commit is contained in:
parent
1a6deb77d4
commit
9a01ae8d30
@ -26,6 +26,7 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
@ -206,7 +207,7 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
|
||||
}
|
||||
|
||||
public JenkinsCrumbIssuerResponse convertResponse(ResponseEntity<String> response) {
|
||||
// 1. 从<EFBFBD><EFBFBD><EFBFBD>应体中解析JSON
|
||||
// 1. 从响应体中解析JSON
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode jsonNode;
|
||||
try {
|
||||
@ -232,7 +233,8 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
|
||||
* @param externalSystem Jenkins系统配置
|
||||
* @param path API路径
|
||||
* @param treeQuery tree查询参数
|
||||
* @param responseClass 响应类型
|
||||
* @param jsonArrayKey JSON数组的key
|
||||
* @param responseType 响应类型的Class对象,用于类型安全
|
||||
* @param <T> 响应类型泛型
|
||||
* @return API响应结果
|
||||
*/
|
||||
@ -240,7 +242,7 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
|
||||
String path,
|
||||
String treeQuery,
|
||||
String jsonArrayKey,
|
||||
Class<T> responseClass) {
|
||||
Class<T> responseType) {
|
||||
try {
|
||||
String url = UriComponentsBuilder.fromHttpUrl(externalSystem.getUrl())
|
||||
.path(path)
|
||||
@ -259,14 +261,15 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
|
||||
if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode root = mapper.readTree(response.getBody());
|
||||
// 使用responseType进行类型安全的转换
|
||||
return mapper.convertValue(root.get(jsonArrayKey),
|
||||
new TypeReference<List<T>>() {
|
||||
});
|
||||
mapper.getTypeFactory().constructCollectionType(List.class, responseType));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to call Jenkins API: path={}, error={}", path, e.getMessage(), e);
|
||||
throw new RuntimeException("调用Jenkins API失败: " + path, e);
|
||||
log.error("Failed to call Jenkins API: path={}, error={}, responseType={}",
|
||||
path, e.getMessage(), responseType.getSimpleName(), e);
|
||||
throw new RuntimeException("调用Jenkins API<50><49>败: " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,16 +280,30 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
|
||||
* @return 视图列表
|
||||
*/
|
||||
public List<JenkinsViewResponse> listViews(ExternalSystem externalSystem) {
|
||||
String treeQuery = "views[name,url,description,_class,primaryView," +
|
||||
"properties[owner,configurationStatus,filter]," +
|
||||
"jobs[*,lastBuild[*],lastCompletedBuild[*]]]";
|
||||
return callJenkinsApi(
|
||||
String treeQuery = "views[name,url,description,_class]";
|
||||
List<JenkinsViewResponse> views = callJenkinsApi(
|
||||
externalSystem,
|
||||
"/api/json",
|
||||
treeQuery,
|
||||
"views",
|
||||
JenkinsViewResponse.class
|
||||
);
|
||||
|
||||
// 过滤和清洗数据
|
||||
return views.stream()
|
||||
.filter(view -> !"all".equalsIgnoreCase(view.getName()))
|
||||
.peek(view -> {
|
||||
// 清理描述中的多余空格
|
||||
if (view.getDescription() != null) {
|
||||
view.setDescription(view.getDescription().trim());
|
||||
}
|
||||
// 转换URL为相对路径
|
||||
if (view.getUrl() != null) {
|
||||
String baseUrl = StringUtils.removeEnd(externalSystem.getUrl(), "/");
|
||||
view.setUrl(view.getUrl().replace(baseUrl, ""));
|
||||
}
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,18 +314,39 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
|
||||
* @return 任务列表
|
||||
*/
|
||||
public List<JenkinsJobResponse> listJobs(ExternalSystem externalSystem, String viewName) {
|
||||
String treeQuery = "jobs[name,url,description,_class,buildable,inQueue," +
|
||||
"keepDependencies,nextBuildNumber,concurrentBuild,disabled," +
|
||||
"displayName,fullName,color,lastBuild[*],lastCompletedBuild[*]," +
|
||||
"lastFailedBuild[*],lastSuccessfulBuild[*],lastUnstableBuild[*]," +
|
||||
"lastUnsuccessfulBuild[*],property[parameterDefinitions[*]]]";
|
||||
return callJenkinsApi(
|
||||
// 只查询必要的字段
|
||||
String treeQuery = "jobs[name,url,description,buildable,nextBuildNumber," +
|
||||
"lastBuild[number],color]";
|
||||
|
||||
List<JenkinsJobResponse> jobs = callJenkinsApi(
|
||||
externalSystem,
|
||||
"/view/" + viewName + "/api/json",
|
||||
treeQuery,
|
||||
"jobs",
|
||||
JenkinsJobResponse.class
|
||||
);
|
||||
|
||||
// 过滤和清洗数据
|
||||
String baseUrl = StringUtils.removeEnd(externalSystem.getUrl(), "/");
|
||||
return jobs.stream()
|
||||
.peek(job -> {
|
||||
// 清理描述中的多余空格
|
||||
if (job.getDescription() != null) {
|
||||
job.setDescription(job.getDescription().trim());
|
||||
}
|
||||
// 转换URL为相对路径
|
||||
if (job.getUrl() != null) {
|
||||
job.setUrl(job.getUrl().replace(baseUrl, ""));
|
||||
}
|
||||
// 设置默认值
|
||||
if (job.getBuildable() == null) {
|
||||
job.setBuildable(false);
|
||||
}
|
||||
if (job.getNextBuildNumber() == null) {
|
||||
job.setNextBuildNumber(1);
|
||||
}
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
package com.qqchen.deploy.backend.deploy.integration.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Jenkins任务响应对象
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class JenkinsJobResponse {
|
||||
/**
|
||||
* 任务名称
|
||||
@ -25,12 +26,6 @@ public class JenkinsJobResponse {
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 任务类型
|
||||
*/
|
||||
@JsonProperty("_class")
|
||||
private String jobClass;
|
||||
|
||||
/**
|
||||
* 是否可构建
|
||||
*/
|
||||
@ -41,26 +36,11 @@ public class JenkinsJobResponse {
|
||||
*/
|
||||
private Boolean inQueue;
|
||||
|
||||
/**
|
||||
* 是否保持构建
|
||||
*/
|
||||
private Boolean keepDependencies;
|
||||
|
||||
/**
|
||||
* 下一个构建号
|
||||
*/
|
||||
private Integer nextBuildNumber;
|
||||
|
||||
/**
|
||||
* 并发构建
|
||||
*/
|
||||
private Boolean concurrentBuild;
|
||||
|
||||
/**
|
||||
* 禁用原因
|
||||
*/
|
||||
private String disabledReason;
|
||||
|
||||
/**
|
||||
* 显示名称
|
||||
*/
|
||||
@ -76,71 +56,44 @@ public class JenkinsJobResponse {
|
||||
*/
|
||||
private String color;
|
||||
|
||||
/**
|
||||
* Jenkins类型
|
||||
*/
|
||||
private String _class;
|
||||
|
||||
/**
|
||||
* 最后一次构建
|
||||
*/
|
||||
@JsonProperty("lastBuild")
|
||||
private BuildInfo lastBuild;
|
||||
|
||||
/**
|
||||
* 最后一次完成的构建
|
||||
*/
|
||||
@JsonProperty("lastCompletedBuild")
|
||||
private BuildInfo lastCompletedBuild;
|
||||
|
||||
/**
|
||||
* 最后一次失败的构建
|
||||
*/
|
||||
@JsonProperty("lastFailedBuild")
|
||||
private BuildInfo lastFailedBuild;
|
||||
|
||||
/**
|
||||
* 最后一次成功的构建
|
||||
*/
|
||||
@JsonProperty("lastSuccessfulBuild")
|
||||
private BuildInfo lastSuccessfulBuild;
|
||||
|
||||
/**
|
||||
* 最后一次不稳定的构建
|
||||
*/
|
||||
@JsonProperty("lastUnstableBuild")
|
||||
private BuildInfo lastUnstableBuild;
|
||||
|
||||
/**
|
||||
* 最后一次不成功的构建
|
||||
*/
|
||||
@JsonProperty("lastUnsuccessfulBuild")
|
||||
private BuildInfo lastUnsuccessfulBuild;
|
||||
|
||||
/**
|
||||
* 构建参数定义
|
||||
*/
|
||||
private List<ParameterDefinition> parameterDefinitions;
|
||||
|
||||
/**
|
||||
* 健康报告列表
|
||||
*/
|
||||
private List<JenkinsHealthReportResponse> healthReports;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class BuildInfo {
|
||||
private Integer number;
|
||||
private String url;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ParameterDefinition {
|
||||
@JsonProperty("_class")
|
||||
private String type;
|
||||
private String name;
|
||||
private String description;
|
||||
private String defaultValue;
|
||||
private List<Choice> choices;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Choice {
|
||||
private String value;
|
||||
private String name;
|
||||
private String _class;
|
||||
private Long timestamp;
|
||||
private Long duration;
|
||||
private String result;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package com.qqchen.deploy.backend.deploy.service;
|
||||
|
||||
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
|
||||
import com.qqchen.deploy.backend.deploy.dto.JenkinsJobDTO;
|
||||
@ -13,11 +15,11 @@ public interface IJenkinsJobService extends IBaseService<JenkinsJob, JenkinsJobD
|
||||
/**
|
||||
* 同步指定视图下的Jenkins任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewId 视图ID
|
||||
* @param externalSystem 外部系统
|
||||
* @param view 视图
|
||||
* @return 同步的任务数量
|
||||
*/
|
||||
Integer syncJobsByView(Long externalSystemId, Long viewId);
|
||||
Integer syncJobsByView(ExternalSystem externalSystem, JenkinsView view);
|
||||
|
||||
/**
|
||||
* 同步外部系统下所有视图的Jenkins任务
|
||||
|
||||
@ -69,7 +69,7 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
int totalSyncedJobs = 0;
|
||||
for (JenkinsView view : views) {
|
||||
try {
|
||||
Integer syncedJobs = syncJobsByView(externalSystemId, view.getId());
|
||||
Integer syncedJobs = syncJobsByView(externalSystem, view);
|
||||
totalSyncedJobs += syncedJobs;
|
||||
log.info("Successfully synchronized {} jobs for view: {}", syncedJobs, view.getViewName());
|
||||
} catch (Exception e) {
|
||||
@ -78,32 +78,24 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Successfully synchronized total {} jobs for external system: {}",
|
||||
totalSyncedJobs, externalSystemId);
|
||||
log.info("Successfully synchronized total {} jobs for external system: {}", totalSyncedJobs, externalSystemId);
|
||||
return totalSyncedJobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步指定视图下的Jenkins任务
|
||||
*
|
||||
* @param externalSystemId 外部系统ID
|
||||
* @param viewId 视图ID
|
||||
* @param externalSystem 外部系统
|
||||
* @param view 视图
|
||||
* @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));
|
||||
public Integer syncJobsByView(ExternalSystem externalSystem, JenkinsView view) {
|
||||
|
||||
JenkinsView jenkinsView = jenkinsViewRepository.findById(viewId)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
|
||||
|
||||
// 2. 调用Jenkins API获取任务列表
|
||||
List<JenkinsJobResponse> jobResponses = jenkinsServiceIntegration.listJobs(externalSystem, jenkinsView.getViewName());
|
||||
List<JenkinsJobResponse> jobResponses = jenkinsServiceIntegration.listJobs(externalSystem, view.getViewName());
|
||||
if (jobResponses.isEmpty()) {
|
||||
log.info("No jobs found in Jenkins view: {}", jenkinsView.getViewName());
|
||||
log.info("No jobs found in Jenkins view: {}", view.getViewName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -111,8 +103,7 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
List<JenkinsJob> jenkinsJobs = new ArrayList<>();
|
||||
for (JenkinsJobResponse jobResponse : jobResponses) {
|
||||
// 查找是否存在相同的任务
|
||||
Optional<JenkinsJob> existingJob = jenkinsJobRepository
|
||||
.findByExternalSystemIdAndViewIdAndJobName(externalSystemId, viewId, jobResponse.getName());
|
||||
Optional<JenkinsJob> existingJob = jenkinsJobRepository.findByExternalSystemIdAndViewIdAndJobName(externalSystem.getId(), view.getId(), jobResponse.getName());
|
||||
|
||||
JenkinsJob jenkinsJob;
|
||||
if (existingJob.isPresent()) {
|
||||
@ -123,8 +114,8 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
} else {
|
||||
// 创建新的任务
|
||||
jenkinsJob = new JenkinsJob();
|
||||
jenkinsJob.setExternalSystemId(externalSystemId);
|
||||
jenkinsJob.setViewId(viewId);
|
||||
jenkinsJob.setExternalSystemId(externalSystem.getId());
|
||||
jenkinsJob.setViewId(view.getId());
|
||||
jenkinsJob.setJobName(jobResponse.getName());
|
||||
updateJobFromResponse(jenkinsJob, jobResponse);
|
||||
log.debug("Creating new Jenkins job: {}", jenkinsJob.getJobName());
|
||||
@ -135,7 +126,7 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
// 4. 批量保存或更新
|
||||
jenkinsJobRepository.saveAll(jenkinsJobs);
|
||||
|
||||
log.info("Successfully synchronized {} Jenkins jobs for view: {}", jenkinsJobs.size(), jenkinsView.getViewName());
|
||||
log.info("Successfully synchronized {} Jenkins jobs for view: {}", jenkinsJobs.size(), view.getViewName());
|
||||
|
||||
return jenkinsJobs.size();
|
||||
}
|
||||
|
||||
@ -69,16 +69,14 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
|
||||
if (existingView.isPresent()) {
|
||||
// 更新已存在的视图
|
||||
jenkinsView = existingView.get();
|
||||
jenkinsView.setViewUrl(viewResponse.getUrl());
|
||||
jenkinsView.setDescription(viewResponse.getDescription());
|
||||
updateViewFromResponse(jenkinsView, viewResponse);
|
||||
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);
|
||||
jenkinsView.setViewName(viewResponse.getName());
|
||||
updateViewFromResponse(jenkinsView, viewResponse);
|
||||
log.debug("Creating new Jenkins view: {}", jenkinsView.getViewName());
|
||||
}
|
||||
jenkinsViews.add(jenkinsView);
|
||||
@ -92,4 +90,12 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
|
||||
|
||||
return jenkinsViews.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从API响应更新视图信息
|
||||
*/
|
||||
private void updateViewFromResponse(JenkinsView jenkinsView, JenkinsViewResponse response) {
|
||||
jenkinsView.setDescription(response.getDescription());
|
||||
jenkinsView.setViewUrl(response.getUrl());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user