大声道撒旦

This commit is contained in:
dengqichen 2024-12-31 18:33:41 +08:00
parent f1f9ef0aab
commit ef0f92e447
23 changed files with 360 additions and 47 deletions

View File

@ -68,7 +68,6 @@
<dependency> <dependency>
<groupId>com.mysql</groupId> <groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId> <artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency> </dependency>
<!-- Hibernate Types --> <!-- Hibernate Types -->
@ -220,11 +219,11 @@
<artifactId>flowable-bpmn-layout</artifactId> <artifactId>flowable-bpmn-layout</artifactId>
<version>${flowable.version}</version> <version>${flowable.version}</version>
</dependency> </dependency>
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>org.flowable</groupId>--> <!-- <groupId>org.flowable</groupId>-->
<!-- <artifactId>flowable-bpmn-model</artifactId>--> <!-- <artifactId>flowable-bpmn-model</artifactId>-->
<!-- <version>${flowable.version}</version> &lt;!&ndash; 使用您项目中的版本 &ndash;&gt;--> <!-- <version>${flowable.version}</version> &lt;!&ndash; 使用您项目中的版本 &ndash;&gt;-->
<!-- </dependency>--> <!-- </dependency>-->
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>org.flowable</groupId>--> <!-- <groupId>org.flowable</groupId>-->
<!-- <artifactId>flowable-spring-boot-starter-rest</artifactId>--> <!-- <artifactId>flowable-spring-boot-starter-rest</artifactId>-->
@ -241,6 +240,11 @@
<artifactId>freemarker</artifactId> <artifactId>freemarker</artifactId>
<version>2.3.32</version> <version>2.3.32</version>
</dependency> </dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,29 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.deploy.entity.DeployLog;
import com.qqchen.deploy.backend.deploy.dto.DeployLogDTO;
import com.qqchen.deploy.backend.deploy.query.DeployLogQuery;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 部署日志 Controller
*/
@Slf4j
@RestController
@RequestMapping("/api/v1/deploy-log")
@Tag(name = "部署日志管理", description = "部署日志管理相关接口")
public class DeployLogApiController extends BaseController<DeployLog, DeployLogDTO, Long, DeployLogQuery> {
@Override
protected void exportData(HttpServletResponse response, List<DeployLogDTO> data) {
// TODO: 实现导出逻辑
log.info("导出部署日志数据,数据量:{}", data.size());
}
}

View File

@ -0,0 +1,13 @@
package com.qqchen.deploy.backend.deploy.converter;
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import com.qqchen.deploy.backend.deploy.entity.DeployLog;
import com.qqchen.deploy.backend.deploy.dto.DeployLogDTO;
import org.mapstruct.Mapper;
/**
* 部署日志 Converter
*/
@Mapper(config = BaseConverter.class)
public interface DeployLogConverter extends BaseConverter<DeployLog, DeployLogDTO> {
}

View File

@ -5,13 +5,14 @@ import com.qqchen.deploy.backend.deploy.enums.BuildTypeEnum;
import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum; import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum;
import com.qqchen.deploy.backend.framework.dto.BaseDTO; import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO; import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnums;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/** /**
* 应用配置DTO * 应用配置DTO
*/ */
@ -33,6 +34,15 @@ public class DeployAppConfigDTO extends BaseDTO {
@Schema(description = "已发布的流程定义") @Schema(description = "已发布的流程定义")
private WorkflowDefinitionDTO publishedWorkflowDefinition; private WorkflowDefinitionDTO publishedWorkflowDefinition;
@Schema(description = "最后一次部署状态")
private WorkflowInstanceStatusEnums lastBuildStatus;
@Schema(description = "最后一次部署开始时间")
private LocalDateTime lastBuildStartTime;
@Schema(description = "最后一次部署结束时间")
private LocalDateTime LastBuildEndTime;
@Schema(description = "表单配置") @Schema(description = "表单配置")
private JsonNode formVariablesSchema; private JsonNode formVariablesSchema;

View File

@ -0,0 +1,49 @@
package com.qqchen.deploy.backend.deploy.dto;
import com.fasterxml.jackson.databind.JsonNode;
import com.qqchen.deploy.backend.deploy.enums.DeployStatusEnum;
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import com.vladmihalcea.hibernate.type.json.JsonType;
import jakarta.persistence.Column;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import java.time.LocalDateTime;
/**
* 部署日志 DTO
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DeployLogDTO extends BaseDTO {
/**
* 环境ID
*/
private Long workflowInstanceId;
/**
* 环境ID
*/
private Long environmentId;
/**
* 应用ID
*/
private Long applicationId;
/**
* 部署版本号
*/
private String deployVersion;
private JsonNode variables;
private JsonNode formVariables;
/**
* 部署参数(JSON)
*/
private JsonNode deployVariables;
}

View File

@ -0,0 +1,59 @@
package com.qqchen.deploy.backend.deploy.entity;
import com.fasterxml.jackson.databind.JsonNode;
import com.qqchen.deploy.backend.deploy.enums.DeployStatusEnum;
import com.qqchen.deploy.backend.framework.domain.Entity;
import com.vladmihalcea.hibernate.type.json.JsonType;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import java.time.LocalDateTime;
/**
* 部署日志实体
*/
@Data
@EqualsAndHashCode(callSuper = true)
@jakarta.persistence.Entity
@Table(name = "deploy_log")
public class DeployLog extends Entity<Long> {
/**
* 环境ID
*/
@Column(name = "workflow_instance_id", nullable = false)
private Long workflowInstanceId;
/**
* 环境ID
*/
@Column(name = "environment_id", nullable = false)
private Long environmentId;
/**
* 应用ID
*/
@Column(name = "application_id", nullable = false)
private Long applicationId;
/**
* 部署版本号
*/
@Column(name = "deploy_version", nullable = false)
private String deployVersion;
@Type(JsonType.class)
@Column(name = "form_variables", columnDefinition = "text", nullable = false)
private JsonNode formVariables;
/**
* 部署参数(JSON)
*/
@Type(JsonType.class)
@Column(name = "deploy_variables", columnDefinition = "text", nullable = false)
private JsonNode deployVariables;
}

View File

@ -0,0 +1,11 @@
package com.qqchen.deploy.backend.deploy.enums;
public enum DeployStatusEnum {
PENDING,
DEPLOYING,
FAILURE,
SUCCESS
}

View File

@ -32,7 +32,7 @@ public interface IJenkinsServiceIntegration extends IExternalSystemIntegration {
* *
* @return 构建队列ID * @return 构建队列ID
*/ */
String buildWithParameters(); String buildWithParameters(ExternalSystem externalSystem, String jobName);
/** /**
* 获取队列中的构建信息 * 获取队列中的构建信息
@ -45,11 +45,11 @@ public interface IJenkinsServiceIntegration extends IExternalSystemIntegration {
/** /**
* 获取构建状态 * 获取构建状态
* *
* @param jobName 任务名称 * @param jobName 任务名称
* @param buildNumber 构建编号 * @param buildNumber 构建编号
* @return 构建状态 * @return 构建状态
*/ */
JenkinsBuildStatus getBuildStatus(String jobName, Integer buildNumber); JenkinsBuildStatus getBuildStatus(ExternalSystem externalSystem, String jobName, Integer buildNumber);
/** /**
* 查询所有视图 * 查询所有视图
@ -63,7 +63,7 @@ public interface IJenkinsServiceIntegration extends IExternalSystemIntegration {
* 查询视图下的所有任务 * 查询视图下的所有任务
* *
* @param externalSystem Jenkins系统配置 * @param externalSystem Jenkins系统配置
* @param viewName 视图名称 * @param viewName 视图名称
* @return 任务列表 * @return 任务列表
*/ */
List<JenkinsJobResponse> listJobs(ExternalSystem externalSystem, String viewName); List<JenkinsJobResponse> listJobs(ExternalSystem externalSystem, String viewName);
@ -74,7 +74,7 @@ public interface IJenkinsServiceIntegration extends IExternalSystemIntegration {
* 查询任务的构建信息 * 查询任务的构建信息
* *
* @param externalSystem Jenkins系统配置 * @param externalSystem Jenkins系统配置
* @param jobName 任务名称 * @param jobName 任务名称
* @return 构建信息列表 * @return 构建信息列表
*/ */
List<JenkinsBuildResponse> listBuilds(ExternalSystem externalSystem, String jobName); List<JenkinsBuildResponse> listBuilds(ExternalSystem externalSystem, String jobName);

View File

@ -115,14 +115,13 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
} }
@Override @Override
public String buildWithParameters() { public String buildWithParameters(ExternalSystem externalSystem, String jobName) {
JenkinsCrumbIssuerResponse jenkinsCrumbIssue = getJenkinsCrumbIssue(); JenkinsCrumbIssuerResponse jenkinsCrumbIssue = getJenkinsCrumbIssue();
ExternalSystem externalSystem = systemRepository.findById(1L).orElseThrow(() -> new RuntimeException("没有找到三方系统"));
HttpHeaders headers = createHeaders(externalSystem); HttpHeaders headers = createHeaders(externalSystem);
headers.set("Jenkins-Crumb", jenkinsCrumbIssue.getCrumb()); headers.set("Jenkins-Crumb", jenkinsCrumbIssue.getCrumb());
headers.set("Cookie", jenkinsCrumbIssue.getCookie()); headers.set("Cookie", jenkinsCrumbIssue.getCookie());
HttpEntity<String> entity = new HttpEntity<>(headers); HttpEntity<String> entity = new HttpEntity<>(headers);
String url = externalSystem.getUrl() + String.format("/job/%s/buildWithParameters", "scp-meta"); String url = externalSystem.getUrl() + String.format("/job/%s/buildWithParameters", jobName);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
// 2. 从Location头获取队列ID // 2. 从Location头获取队列ID
String location = response.getHeaders().getFirst("Location"); String location = response.getHeaders().getFirst("Location");
@ -164,12 +163,9 @@ public class JenkinsServiceIntegration implements IJenkinsServiceIntegration {
@Override @Override
public JenkinsBuildStatus getBuildStatus(String jobName, Integer buildNumber) { public JenkinsBuildStatus getBuildStatus(ExternalSystem externalSystem, String jobName, Integer buildNumber) {
try { try {
ExternalSystem externalSystem = systemRepository.findById(1L).orElseThrow(() -> new RuntimeException("没有找到三方系统"));
String url = String.format("%s/job/%s/%d/api/json", externalSystem.getUrl().trim(), jobName, buildNumber); String url = String.format("%s/job/%s/%d/api/json", externalSystem.getUrl().trim(), jobName, buildNumber);
ResponseEntity<Map<String, Object>> response = restTemplate.exchange( ResponseEntity<Map<String, Object>> response = restTemplate.exchange(
url, url,
HttpMethod.GET, HttpMethod.GET,

View File

@ -0,0 +1,18 @@
package com.qqchen.deploy.backend.deploy.query;
import com.qqchen.deploy.backend.framework.annotation.QueryField;
import com.qqchen.deploy.backend.framework.enums.QueryType;
import com.qqchen.deploy.backend.framework.query.BaseQuery;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 部署日志查询对象
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DeployLogQuery extends BaseQuery {
}

View File

@ -0,0 +1,14 @@
package com.qqchen.deploy.backend.deploy.repository;
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
import com.qqchen.deploy.backend.deploy.entity.DeployLog;
import org.springframework.stereotype.Repository;
/**
* 部署日志 Repository
*/
@Repository
public interface IDeployLogRepository extends IBaseRepository<DeployLog, Long> {
DeployLog findTop1ByApplicationIdOrderByCreateTimeDesc(Long id);
}

View File

@ -0,0 +1,12 @@
package com.qqchen.deploy.backend.deploy.service;
import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.deploy.entity.DeployLog;
import com.qqchen.deploy.backend.deploy.dto.DeployLogDTO;
import com.qqchen.deploy.backend.deploy.query.DeployLogQuery;
/**
* 部署日志 Service接口
*/
public interface IDeployLogService extends IBaseService<DeployLog, DeployLogDTO, DeployLogQuery, Long> {
}

View File

@ -1,23 +1,33 @@
package com.qqchen.deploy.backend.deploy.service.impl; package com.qqchen.deploy.backend.deploy.service.impl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.deploy.converter.ApplicationConverter; import com.qqchen.deploy.backend.deploy.converter.ApplicationConverter;
import com.qqchen.deploy.backend.deploy.converter.DeployLogConverter;
import com.qqchen.deploy.backend.deploy.dto.BuildConfigDefinedDTO; import com.qqchen.deploy.backend.deploy.dto.BuildConfigDefinedDTO;
import com.qqchen.deploy.backend.deploy.dto.DeployAppBuildDTO; import com.qqchen.deploy.backend.deploy.dto.DeployAppBuildDTO;
import com.qqchen.deploy.backend.deploy.dto.DeployAppConfigDTO; import com.qqchen.deploy.backend.deploy.dto.DeployAppConfigDTO;
import com.qqchen.deploy.backend.deploy.dto.DeployLogDTO;
import com.qqchen.deploy.backend.deploy.entity.Application; import com.qqchen.deploy.backend.deploy.entity.Application;
import com.qqchen.deploy.backend.deploy.entity.DeployAppConfig; import com.qqchen.deploy.backend.deploy.entity.DeployAppConfig;
import com.qqchen.deploy.backend.deploy.entity.DeployLog;
import com.qqchen.deploy.backend.deploy.entity.Environment; import com.qqchen.deploy.backend.deploy.entity.Environment;
import com.qqchen.deploy.backend.deploy.enums.BuildTypeEnum; import com.qqchen.deploy.backend.deploy.enums.BuildTypeEnum;
import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum; import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum;
import com.qqchen.deploy.backend.deploy.query.DeployAppConfigQuery; import com.qqchen.deploy.backend.deploy.query.DeployAppConfigQuery;
import com.qqchen.deploy.backend.deploy.repository.IApplicationRepository; import com.qqchen.deploy.backend.deploy.repository.IApplicationRepository;
import com.qqchen.deploy.backend.deploy.repository.IDeployLogRepository;
import com.qqchen.deploy.backend.deploy.repository.IEnvironmentRepository; import com.qqchen.deploy.backend.deploy.repository.IEnvironmentRepository;
import com.qqchen.deploy.backend.deploy.service.IDeployAppConfigService; import com.qqchen.deploy.backend.deploy.service.IDeployAppConfigService;
import com.qqchen.deploy.backend.deploy.service.IDeployLogService;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.workflow.converter.WorkflowDefinitionConverter; import com.qqchen.deploy.backend.workflow.converter.WorkflowDefinitionConverter;
import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceDTO;
import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceStartRequest; import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceStartRequest;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository;
import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService; import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -58,15 +68,42 @@ public class DeployAppConfigServiceImpl extends BaseServiceImpl<DeployAppConfig,
@Resource @Resource
private IEnvironmentRepository environmentRepository; private IEnvironmentRepository environmentRepository;
@Resource
private IDeployLogService deployLogService;
@Resource
private IDeployLogRepository deployLogRepository;
@Resource
private DeployLogConverter deployLogConverter;
@Resource
private IWorkflowInstanceRepository workflowInstanceRepository;
@Resource
private ObjectMapper objectMapper;
@Override @Override
public Page<DeployAppConfigDTO> page(DeployAppConfigQuery query) { public Page<DeployAppConfigDTO> page(DeployAppConfigQuery query) {
Page<DeployAppConfigDTO> page = super.page(query); Page<DeployAppConfigDTO> page = super.page(query);
List<DeployAppConfigDTO> result = page.getContent().stream().peek(deployAppConfig -> { List<DeployAppConfigDTO> result = page.getContent().stream().peek(deployAppConfig -> {
Optional<Application> optionalApplication = applicationRepository.findById(deployAppConfig.getApplicationId()); Optional<Application> optionalApplication = applicationRepository.findById(deployAppConfig.getApplicationId());
optionalApplication.ifPresent(application -> deployAppConfig.setApplication(applicationConverter.toDto(application))); if (optionalApplication.isPresent()) {
Application application = optionalApplication.get();
deployAppConfig.setApplication(applicationConverter.toDto(application));
DeployLog lastDeployLog = deployLogRepository.findTop1ByApplicationIdOrderByCreateTimeDesc(application.getId());
Optional<WorkflowInstance> optionalWorkflowInstance = workflowInstanceRepository.findById(lastDeployLog.getWorkflowInstanceId());
if (optionalWorkflowInstance.isPresent()) {
WorkflowInstance workflowInstance = optionalWorkflowInstance.get();
deployAppConfig.setLastBuildStatus(workflowInstance.getStatus());
deployAppConfig.setLastBuildStartTime(workflowInstance.getStartTime());
deployAppConfig.setLastBuildEndTime(workflowInstance.getEndTime());
}
}
Optional<WorkflowDefinition> optionalWorkflowDefinition = workflowDefinitionRepository.findById(deployAppConfig.getWorkflowDefinitionId()); Optional<WorkflowDefinition> optionalWorkflowDefinition = workflowDefinitionRepository.findById(deployAppConfig.getWorkflowDefinitionId());
optionalWorkflowDefinition.ifPresent(workflowDefinition -> deployAppConfig.setPublishedWorkflowDefinition(workflowDefinitionConverter.toDto(workflowDefinition))); optionalWorkflowDefinition.ifPresent(workflowDefinition -> deployAppConfig.setPublishedWorkflowDefinition(workflowDefinitionConverter.toDto(workflowDefinition)));
}).collect(toList()); }).collect(toList());
return new PageImpl<>(result, page.getPageable(), page.getTotalElements()); return new PageImpl<>(result, page.getPageable(), page.getTotalElements());
} }
@ -107,11 +144,26 @@ public class DeployAppConfigServiceImpl extends BaseServiceImpl<DeployAppConfig,
WorkflowDefinition workflowDefinition = workflowDefinitionRepository.findById(dto.getWorkflowDefinitionId()).orElseThrow(() -> new RuntimeException("Workflow definition not found: " + dto.getWorkflowDefinitionId())); WorkflowDefinition workflowDefinition = workflowDefinitionRepository.findById(dto.getWorkflowDefinitionId()).orElseThrow(() -> new RuntimeException("Workflow definition not found: " + dto.getWorkflowDefinitionId()));
Environment environment = environmentRepository.findById(dto.getEnvironmentId()).orElseThrow(() -> new RuntimeException("Environment not found: " + dto.getEnvironmentId())); Environment environment = environmentRepository.findById(dto.getEnvironmentId()).orElseThrow(() -> new RuntimeException("Environment not found: " + dto.getEnvironmentId()));
Application application = applicationRepository.findById(dto.getApplicationId()).orElseThrow(() -> new RuntimeException("Application not found: " + dto.getApplicationId())); Application application = applicationRepository.findById(dto.getApplicationId()).orElseThrow(() -> new RuntimeException("Application not found: " + dto.getApplicationId()));
WorkflowInstanceStartRequest request = new WorkflowInstanceStartRequest(); WorkflowInstanceStartRequest request = new WorkflowInstanceStartRequest();
request.setProcessKey(workflowDefinition.getKey()); request.setProcessKey(workflowDefinition.getKey());
request.setBusinessKey(environment.getEnvCode() + "_" + application.getAppCode() + "_" + System.currentTimeMillis() / 1000); request.setBusinessKey(environment.getEnvCode() + "_" + application.getAppCode() + "_" + System.currentTimeMillis() / 1000);
workflowInstanceService.startWorkflow(request); request.setVariables(objectMapper.convertValue(dto.getBuildVariables(), new TypeReference<>() {
}));
WorkflowInstanceDTO workflowInstanceDTO = workflowInstanceService.startWorkflow(request);
buildAndSaveDeployLog(dto, environment, application, workflowInstanceDTO);
}
private void buildAndSaveDeployLog(DeployAppBuildDTO deployAppBuild, Environment environment, Application application, WorkflowInstanceDTO workflowInstance) {
DeployLogDTO deployLog = new DeployLogDTO();
deployLog.setEnvironmentId(environment.getId());
deployLog.setApplicationId(application.getId());
deployLog.setWorkflowInstanceId(workflowInstance.getId());
deployLog.setVariables(deployAppBuild.getBuildVariables());
deployLog.setDeployVersion(application.getAppCode() + "_" + System.currentTimeMillis() / 1000);
deployLog.setDeployVariables(deployAppBuild.getBuildVariables());
deployLog.setFormVariables(deployAppBuild.getFormVariables());
deployLogService.create(deployLog);
} }
@Override @Override

View File

@ -0,0 +1,17 @@
package com.qqchen.deploy.backend.deploy.service.impl;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.deploy.entity.DeployLog;
import com.qqchen.deploy.backend.deploy.dto.DeployLogDTO;
import com.qqchen.deploy.backend.deploy.query.DeployLogQuery;
import com.qqchen.deploy.backend.deploy.service.IDeployLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 部署日志 Service实现
*/
@Slf4j
@Service
public class DeployLogServiceImpl extends BaseServiceImpl<DeployLog, DeployLogDTO, DeployLogQuery, Long> implements IDeployLogService {
}

View File

@ -176,7 +176,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
} }
@Override @Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) @Transactional
public Integer syncBuilds(ExternalSystem externalSystem, JenkinsJob job) { public Integer syncBuilds(ExternalSystem externalSystem, JenkinsJob job) {
JenkinsJobResponse queryJob = jenkinsServiceIntegration.job(externalSystem, job.getJobName()); JenkinsJobResponse queryJob = jenkinsServiceIntegration.job(externalSystem, job.getJobName());
if (queryJob == null || queryJob.getLastBuild() == null) { if (queryJob == null || queryJob.getLastBuild() == null) {

View File

@ -1,7 +1,6 @@
package com.qqchen.deploy.backend.framework.generator; package com.qqchen.deploy.backend.framework.generator;
import com.qqchen.deploy.backend.framework.utils.CodeGeneratorUtils; import com.qqchen.deploy.backend.framework.generator.CodeGeneratorUtils.GeneratorConfig;
import com.qqchen.deploy.backend.framework.utils.CodeGeneratorUtils.GeneratorConfig;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -1,6 +1,5 @@
package com.qqchen.deploy.backend.framework.utils; package com.qqchen.deploy.backend.framework.generator;
import com.qqchen.deploy.backend.framework.generator.CodeGenerator;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
@ -16,8 +15,6 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* 代码生成器工具类 * 代码生成器工具类

View File

@ -15,6 +15,7 @@ import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WOR
import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_NODE_EXECUTION_STATUS_SUCCESS; import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_NODE_EXECUTION_STATUS_SUCCESS;
import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_PREVIOUS_NODE_EXECUTION_STATUS_VARIABLE_NAME; import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_PREVIOUS_NODE_EXECUTION_STATUS_VARIABLE_NAME;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
/** /**
@ -27,7 +28,6 @@ import java.util.Optional;
* <p> * <p>
* panelVariables: 节点配置一次配置长期有效 * panelVariables: 节点配置一次配置长期有效
* localVariables: 运行时变量每次执行都会变化 * localVariables: 运行时变量每次执行都会变化
* fromVariables: 表单输入每次执行需要用户填写
*/ */
@Slf4j @Slf4j
public abstract class BaseNodeDelegate<P, L> implements JavaDelegate { public abstract class BaseNodeDelegate<P, L> implements JavaDelegate {
@ -39,8 +39,6 @@ public abstract class BaseNodeDelegate<P, L> implements JavaDelegate {
// 字段注入由Flowable自动设置 // 字段注入由Flowable自动设置
protected Expression panelVariables; protected Expression panelVariables;
protected Expression localVariables;
@Override @Override
public void execute(DelegateExecution execution) { public void execute(DelegateExecution execution) {
try { try {
@ -55,13 +53,7 @@ public abstract class BaseNodeDelegate<P, L> implements JavaDelegate {
} }
// 获取并转换Local变量 // 获取并转换Local变量
L localVars = null; L localVars = objectMapper.convertValue(execution.getVariables(), getLocalVariablesClass());
if (localVariables != null) {
String localVarsJson = localVariables.getValue(execution).toString();
JsonNode localVarsNode = objectMapper.readTree(localVarsJson);
localVars = objectMapper.treeToValue(localVarsNode, getLocalVariablesClass());
}
// 执行具体的任务逻辑 // 执行具体的任务逻辑
executeInternal(execution, panelVars, localVars); executeInternal(execution, panelVars, localVars);

View File

@ -1,8 +1,13 @@
package com.qqchen.deploy.backend.workflow.delegate; package com.qqchen.deploy.backend.workflow.delegate;
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
import com.qqchen.deploy.backend.deploy.enums.JenkinsBuildStatus; import com.qqchen.deploy.backend.deploy.enums.JenkinsBuildStatus;
import com.qqchen.deploy.backend.deploy.integration.IExternalSystemIntegration;
import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration; import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration;
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsQueueBuildInfoResponse; import com.qqchen.deploy.backend.deploy.integration.response.JenkinsQueueBuildInfoResponse;
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
import com.qqchen.deploy.backend.deploy.repository.IJenkinsJobRepository;
import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants; import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
import com.qqchen.deploy.backend.workflow.dto.definition.node.localVariables.DeployNodeLocalVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.localVariables.DeployNodeLocalVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.DeployNodePanelVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.DeployNodePanelVariables;
@ -36,6 +41,12 @@ public class DeployNodeDelegate extends BaseNodeDelegate<DeployNodePanelVariable
// 最大轮询次数 // 最大轮询次数
private static final int MAX_BUILD_POLLS = 180; // 30分钟超时 private static final int MAX_BUILD_POLLS = 180; // 30分钟超时
@Resource
private IExternalSystemRepository externalSystemRepository;
@Resource
private IJenkinsJobRepository jenkinsJobRepository;
@Override @Override
protected Class<DeployNodePanelVariables> getPanelVariablesClass() { protected Class<DeployNodePanelVariables> getPanelVariablesClass() {
return DeployNodePanelVariables.class; return DeployNodePanelVariables.class;
@ -48,10 +59,12 @@ public class DeployNodeDelegate extends BaseNodeDelegate<DeployNodePanelVariable
@Override @Override
protected void executeInternal(DelegateExecution execution, DeployNodePanelVariables panelVariables, DeployNodeLocalVariables localVariables) { protected void executeInternal(DelegateExecution execution, DeployNodePanelVariables panelVariables, DeployNodeLocalVariables localVariables) {
String queueId = jenkinsServiceIntegration.buildWithParameters(); ExternalSystem externalSystem = externalSystemRepository.findById(localVariables.getExternalSystemId()).orElseThrow(() -> new RuntimeException("ExternalSystem not found!!!"));
JenkinsJob jenkinsJob = jenkinsJobRepository.findById(localVariables.getJobId()).orElseThrow(() -> new RuntimeException("Jenkins job not found!!!"));
String queueId = jenkinsServiceIntegration.buildWithParameters(externalSystem, jenkinsJob.getJobName());
JenkinsQueueBuildInfoResponse buildInfo = waitForBuildToStart(queueId); JenkinsQueueBuildInfoResponse buildInfo = waitForBuildToStart(queueId);
// 3. 轮询构建状态 // 3. 轮询构建状态
pollBuildStatus("scp-meta", buildInfo.getBuildNumber()); pollBuildStatus(externalSystem, jenkinsJob.getJobName(), buildInfo.getBuildNumber());
} }
private JenkinsQueueBuildInfoResponse waitForBuildToStart(String queueId) { private JenkinsQueueBuildInfoResponse waitForBuildToStart(String queueId) {
@ -77,7 +90,7 @@ public class DeployNodeDelegate extends BaseNodeDelegate<DeployNodePanelVariable
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, String.format("Build did not start within %d seconds", MAX_QUEUE_POLLS * QUEUE_POLL_INTERVAL)); throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, String.format("Build did not start within %d seconds", MAX_QUEUE_POLLS * QUEUE_POLL_INTERVAL));
} }
private void pollBuildStatus(String jobName, Integer buildNumber) { private void pollBuildStatus(ExternalSystem externalSystem, String jobName, Integer buildNumber) {
int attempts = 0; int attempts = 0;
while (attempts < MAX_BUILD_POLLS) { while (attempts < MAX_BUILD_POLLS) {
try { try {
@ -85,7 +98,7 @@ public class DeployNodeDelegate extends BaseNodeDelegate<DeployNodePanelVariable
Thread.sleep(BUILD_POLL_INTERVAL * 1000L); Thread.sleep(BUILD_POLL_INTERVAL * 1000L);
// 获取构建状态 // 获取构建状态
JenkinsBuildStatus status = jenkinsServiceIntegration.getBuildStatus(jobName, buildNumber); JenkinsBuildStatus status = jenkinsServiceIntegration.getBuildStatus(externalSystem, jobName, buildNumber);
log.info("Jenkins build status: job={}, buildNumber={}, status={}", jobName, buildNumber, status); log.info("Jenkins build status: job={}, buildNumber={}, status={}", jobName, buildNumber, status);
switch (status) { switch (status) {

View File

@ -3,6 +3,8 @@ package com.qqchen.deploy.backend.workflow.dto;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.util.Map;
@Data @Data
@Schema(description = "工作流实例启动入参") @Schema(description = "工作流实例启动入参")
public class WorkflowInstanceStartRequest { public class WorkflowInstanceStartRequest {
@ -11,5 +13,6 @@ public class WorkflowInstanceStartRequest {
private String businessKey; private String businessKey;
private Map<String, Object> variables;
} }

View File

@ -14,7 +14,7 @@ public class DeployNodeLocalVariables extends BaseNodeLocalVariables {
description = "三方Jenkins系统", description = "三方Jenkins系统",
required = true required = true
) )
private String externalSystemId; private Long externalSystemId;
@SchemaProperty( @SchemaProperty(
@ -23,7 +23,7 @@ public class DeployNodeLocalVariables extends BaseNodeLocalVariables {
required = true, required = true,
order = 3 order = 3
) )
private String viewId; private Long viewId;
@SchemaProperty( @SchemaProperty(
@ -32,6 +32,6 @@ public class DeployNodeLocalVariables extends BaseNodeLocalVariables {
required = true, required = true,
order = 4 order = 4
) )
private String jobId; private Long jobId;
} }

View File

@ -178,7 +178,9 @@ public class WorkflowInstanceServiceImpl extends BaseServiceImpl<WorkflowInstanc
WorkflowDefinition workflowDefinition = workflowDefinitionRepository.findByKey(request.getProcessKey()).orElseThrow(() -> new RuntimeException("Workflow definition process key not found: " + request.getProcessKey())); WorkflowDefinition workflowDefinition = workflowDefinitionRepository.findByKey(request.getProcessKey()).orElseThrow(() -> new RuntimeException("Workflow definition process key not found: " + request.getProcessKey()));
ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder() ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
.processDefinitionKey(request.getProcessKey()) .processDefinitionKey(request.getProcessKey())
.variables(request.getVariables())
.businessKey(request.getBusinessKey()) .businessKey(request.getBusinessKey())
.variables(request.getVariables())
.startAsync(); // 异步启动会自动执行 shell 任务 .startAsync(); // 异步启动会自动执行 shell 任务
// .start(); // .start();
return createWorkflowInstance(workflowDefinition.getId(), request.getBusinessKey(), processInstance); return createWorkflowInstance(workflowDefinition.getId(), request.getBusinessKey(), processInstance);

View File

@ -647,3 +647,26 @@ CREATE TABLE deploy_project_group_environment
REFERENCES deploy_environment (id) REFERENCES deploy_environment (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目组环境关联表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目组环境关联表';
CREATE TABLE deploy_log
(
-- 基础字段
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
-- 业务字段
workflow_instance_id BIGINT NULL COMMENT '工作流实例ID',
environment_id BIGINT NOT NULL COMMENT '环境ID',
application_id BIGINT NOT NULL COMMENT '应用ID',
deploy_version VARCHAR(100) NOT NULL COMMENT '部署版本号',
form_variables TEXT NULL COMMENT '部署参数(JSON)',
deploy_variables TEXT NULL COMMENT '部署参数(JSON)',
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除0-未删除1-已删除'
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci COMMENT ='部署日志表';