biz-process 部分类的逻辑转写成java
This commit is contained in:
parent
cd9329d438
commit
a4c12a7f78
@ -1,12 +1,19 @@
|
||||
package cd.casic.ci.common.pipeline;
|
||||
|
||||
import cd.casic.ci.common.pipeline.container.Container;
|
||||
import cd.casic.ci.common.pipeline.container.Stage;
|
||||
import cd.casic.ci.common.pipeline.container.TriggerContainer;
|
||||
import cd.casic.ci.common.pipeline.enums.CallBackEvent;
|
||||
import cd.casic.ci.common.pipeline.pojo.event.PipelineCallbackEvent;
|
||||
import cd.casic.ci.common.pipeline.pojo.event.ProjectPipelineCallBack;
|
||||
import cd.casic.ci.common.pipeline.pojo.time.BuildRecordTimeCost;
|
||||
import cd.casic.ci.common.pipeline.pojo.transfer.Resources;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -74,4 +81,41 @@ public class Model implements IModelTemplate {
|
||||
|
||||
@Schema(title = "提交时流水线最新版本号", required = false)
|
||||
private int latestVersion;
|
||||
/**
|
||||
* 获取流水线回调配置
|
||||
* @param projectId 项目ID
|
||||
* @param callbackEvent 回调事件类型
|
||||
* @return 流水线回调配置列表
|
||||
*/
|
||||
public List<ProjectPipelineCallBack> getPipelineCallBack(
|
||||
String projectId,
|
||||
CallBackEvent callbackEvent
|
||||
) {
|
||||
List<ProjectPipelineCallBack> pipelineCallBack = new ArrayList<>();
|
||||
if (events != null) {
|
||||
events.forEach((eventName, event) -> {
|
||||
// TODO 可能要重写equals
|
||||
if (callbackEvent==event.getCallbackEvent()) {
|
||||
pipelineCallBack.add(
|
||||
new ProjectPipelineCallBack(
|
||||
null,
|
||||
projectId,
|
||||
event.getCallbackEvent().name(),
|
||||
event.getCallbackUrl(),
|
||||
event.getSecretToken(),
|
||||
true,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
return pipelineCallBack;
|
||||
}
|
||||
public TriggerContainer getTriggerContainer(){
|
||||
Container container = stages.get(0).getContainers().get(0);
|
||||
return JSON.parseObject(JSON.toJSONString(container),TriggerContainer.class);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
package cd.casic.ci.common.pipeline;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class UUIDUtil {
|
||||
private UUIDUtil() {
|
||||
// 私有构造方法防止实例化
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成32位字符随机UUID
|
||||
* @return UUID字符串
|
||||
*/
|
||||
public static String generate() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
String str = uuid.toString();
|
||||
// 通过substring拼接去掉UUID中的连字符
|
||||
return str.substring(0, 8) + str.substring(9, 13) + str.substring(14, 18) + str.substring(19, 23) + str.substring(24);
|
||||
}
|
||||
|
||||
// 可选方案:使用replace方法更简洁
|
||||
// public static String generate() {
|
||||
// return UUID.randomUUID().toString().replace("-", "");
|
||||
// }
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
package cd.casic.ci.common.pipeline.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SQLLimit {
|
||||
private Integer offset;
|
||||
private Integer limit;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package cd.casic.ci.common.pipeline.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class SQLPage<T> {
|
||||
private Long count;
|
||||
private List<T> records;
|
||||
}
|
@ -173,7 +173,9 @@ public abstract class Element implements IModelTemplate {
|
||||
String elementId = postFlag ? elementPostInfo.getParentElementId() : id;
|
||||
if (variables.get(ElementUtils.getSkipElementVariableName(elementId)) != null && "true".equals(variables.get(ElementUtils.getSkipElementVariableName(elementId)))) {
|
||||
if (additionalOptions == null) {
|
||||
additionalOptions = new ElementAdditionalOptions();
|
||||
ElementAdditionalOptions elementAdditionalOptions = new ElementAdditionalOptions();
|
||||
elementAdditionalOptions.setRunCondition(ElementAdditionalOptions.RunCondition.PRE_TASK_SUCCESS);
|
||||
additionalOptions = elementAdditionalOptions;
|
||||
}
|
||||
additionalOptions.setEnable(false);
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package cd.casic.ci.common.pipeline.pojo.element;
|
||||
import cd.casic.ci.common.pipeline.NameAndValue;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -18,6 +20,8 @@ import java.util.List;
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "插件级别流程控制模型")
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ElementAdditionalOptions {
|
||||
@Schema(title = "是否启用", required = false)
|
||||
private boolean enable = true;
|
||||
@ -58,6 +62,13 @@ public class ElementAdditionalOptions {
|
||||
@Deprecated
|
||||
private List<NameAndValue> customEnv;
|
||||
|
||||
public ElementAdditionalOptions(boolean continueWhenFailed, Long timeout, RunCondition runCondition, ElementPostInfo elementPostInfo) {
|
||||
this.continueWhenFailed = continueWhenFailed;
|
||||
this.timeout = timeout;
|
||||
this.runCondition = runCondition;
|
||||
this.elementPostInfo = elementPostInfo;
|
||||
}
|
||||
|
||||
public enum RunCondition {
|
||||
PRE_TASK_SUCCESS,
|
||||
PRE_TASK_FAILED_BUT_CANCEL,
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cd.casic.ci.common.pipeline.pojo.element;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -14,6 +15,7 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "元素post信息")
|
||||
@AllArgsConstructor
|
||||
public class ElementPostInfo {
|
||||
@Schema(title = "入口参数")
|
||||
private String postEntryParam;
|
||||
|
@ -0,0 +1,9 @@
|
||||
package cd.casic.ci.common.pipeline.pojo.event;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class IEvent {
|
||||
private Integer delayMills;
|
||||
private Integer retryTime;
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package cd.casic.ci.common.pipeline.service.utils;
|
||||
|
||||
|
||||
|
||||
import cd.casic.framework.commons.util.watcher.Watcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 日志工具类
|
||||
*/
|
||||
public final class LogUtils {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LogUtils.class);
|
||||
private static final int DEFAULT_MAX_LENGTH = 16384;
|
||||
|
||||
private LogUtils() {
|
||||
// 私有构造函数,防止实例化
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录耗时信息
|
||||
* @param message 日志消息
|
||||
* @param startTime 开始时间
|
||||
* @param warnThreshold 警告阈值,默认1000ms
|
||||
* @param errorThreshold 错误阈值,默认5000ms
|
||||
*/
|
||||
public static void costTime(String message, long startTime, long warnThreshold, long errorThreshold) {
|
||||
long cost = System.currentTimeMillis() - startTime;
|
||||
if (cost < warnThreshold) {
|
||||
LOG.info("{} cost {} ms", message, cost);
|
||||
} else if (cost < errorThreshold) {
|
||||
LOG.warn("{} cost {} ms", message, cost);
|
||||
} else {
|
||||
LOG.error("{} cost {} ms", message, cost);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录耗时信息(使用默认阈值)
|
||||
* @param message 日志消息
|
||||
* @param startTime 开始时间
|
||||
*/
|
||||
public static void costTime(String message, long startTime) {
|
||||
costTime(message, startTime, 1000L, 5000L);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算watcher的耗时并打印日志
|
||||
* @param watcher 监控器
|
||||
* @param warnThreshold 警告阈值
|
||||
* @param errorThreshold 错误阈值
|
||||
*/
|
||||
public static void printCostTimeWE(Watcher watcher, long warnThreshold, long errorThreshold) {
|
||||
watcher.stop();
|
||||
long cost = System.currentTimeMillis() - watcher.getCreateTime();
|
||||
if (cost >= warnThreshold) {
|
||||
if (cost > errorThreshold) {
|
||||
LOG.error("{} cost {} ms", watcher, cost);
|
||||
} else {
|
||||
LOG.warn("{} cost {} ms", watcher, cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算watcher的耗时并打印日志(使用默认阈值)
|
||||
* @param watcher 监控器
|
||||
*/
|
||||
public static void printCostTimeWE(Watcher watcher) {
|
||||
printCostTimeWE(watcher, 1000L, 5000L);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有限长度的日志内容(使用默认最大长度16K)
|
||||
* @param logStr 原始日志内容
|
||||
* @return 截取后的日志
|
||||
*/
|
||||
public static String getLogWithLengthLimit(String logStr) {
|
||||
return getLogWithLengthLimit(logStr, DEFAULT_MAX_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有限长度的日志内容
|
||||
* @param logStr 原始日志内容
|
||||
* @param maxLength 最大长度,若小于0则不生效,返回原始日志
|
||||
* @return 截取后的日志
|
||||
*/
|
||||
public static String getLogWithLengthLimit(String logStr, int maxLength) {
|
||||
if (logStr == null) {
|
||||
return null;
|
||||
}
|
||||
if (maxLength < 0) {
|
||||
return logStr;
|
||||
}
|
||||
return logStr.length() > maxLength ? logStr.substring(0, maxLength) : logStr;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package cd.casic.ci.event.pojo;
|
||||
|
||||
import com.mysql.cj.MessageBuilder;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -17,6 +18,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@Data
|
||||
@Slf4j
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IEvent {
|
||||
|
||||
private int delayMills = 0;
|
||||
|
@ -2,7 +2,9 @@ package cd.casic.ci.event.pojo.pipeline;
|
||||
|
||||
import cd.casic.ci.event.enums.ActionType;
|
||||
import cd.casic.ci.event.pojo.IEvent;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
@ -15,8 +17,10 @@ import org.slf4j.MDC;
|
||||
* @Filename:IPipelineEvent
|
||||
* @description:Todo
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public abstract class IPipelineEvent extends IEvent {
|
||||
private ActionType actionType;
|
||||
private String source;
|
||||
@ -25,4 +29,13 @@ public abstract class IPipelineEvent extends IEvent {
|
||||
private String userId;
|
||||
private String traceId = MDC.get("bizid");
|
||||
private String routeKeySuffix;
|
||||
|
||||
public IPipelineEvent( ActionType actionType, String source, String projectId, String pipelineId, String userId,int delayMills) {
|
||||
super(delayMills, 1);
|
||||
this.actionType = actionType;
|
||||
this.source = source;
|
||||
this.projectId = projectId;
|
||||
this.pipelineId = pipelineId;
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package cd.casic.ci.process.api.engine.pojo.event;
|
||||
|
||||
import cd.casic.ci.event.enums.ActionType;
|
||||
import cd.casic.ci.event.pojo.pipeline.IPipelineEvent;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* @author by mianbin
|
||||
@ -9,6 +11,8 @@ import cd.casic.ci.event.pojo.pipeline.IPipelineEvent;
|
||||
* @Description TODO
|
||||
* @Date 2025/3/31 16:33
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class PipelineStreamEnabledEvent extends IPipelineEvent {
|
||||
private final String source;
|
||||
private final String projectId;
|
||||
|
@ -2,6 +2,7 @@ package cd.casic.ci.process.api.process.pojo;
|
||||
|
||||
import cd.casic.ci.common.pipeline.pojo.time.BuildRecordTimeCost;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@ -17,6 +18,7 @@ import java.util.List;
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "历史构建阶段状态")
|
||||
@AllArgsConstructor
|
||||
public class BuildStageStatus {
|
||||
@Schema(title = "阶段ID", required = true)
|
||||
private String stageId;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cd.casic.ci.process.api.process.pojo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -14,6 +15,7 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "流水线-阶段标签信息")
|
||||
@AllArgsConstructor
|
||||
public class PipelineStageTag {
|
||||
@Schema(title = "阶段标签ID", required = true)
|
||||
private String id;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cd.casic.ci.process.api.process.pojo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@ -16,6 +17,7 @@ import java.util.List;
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "项目的流水线回调历史")
|
||||
@AllArgsConstructor
|
||||
public class ProjectPipelineCallBackHistory {
|
||||
@Schema(title = "流水线id", required = false)
|
||||
private Long id;
|
||||
@ -46,7 +48,8 @@ public class ProjectPipelineCallBackHistory {
|
||||
|
||||
@Data
|
||||
@Schema(title = "回调header 模型")
|
||||
public class CallBackHeader {
|
||||
@AllArgsConstructor
|
||||
public static class CallBackHeader {
|
||||
@Schema(title = "名字", required = false)
|
||||
private String name;
|
||||
@Schema(title = "值", required = false)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cd.casic.ci.process.api.process.pojo.audit;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -14,6 +15,7 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "审计模型-Audit")
|
||||
@AllArgsConstructor
|
||||
public class AuditInfo {
|
||||
@Schema(title = "状态", required = true)
|
||||
private String status;
|
||||
|
@ -1,7 +1,9 @@
|
||||
package cd.casic.ci.process.api.process.pojo.pipeline;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.Model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -11,6 +13,7 @@ import lombok.Data;
|
||||
* @Date 2025/3/31 17:31
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Schema(title = "构建详情-构建信息")
|
||||
public class ModelDetail {
|
||||
@Schema(title = "构建ID", required = true)
|
||||
|
@ -277,7 +277,7 @@ public class PipelineVarUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public String oldVarToNewVar(String oldVarName) {
|
||||
public static String oldVarToNewVar(String oldVarName) {
|
||||
return oldVarMappingNewVar.get(oldVarName);
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,15 @@
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>module-ci-process-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mq</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.resilience4j</groupId>
|
||||
<artifactId>resilience4j-circuitbreaker</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,6 @@
|
||||
package cd.casic.ci.process.process.constant;
|
||||
|
||||
public class AllocIdGenerateConstant {
|
||||
public static final String AUDIT_RESOURCE="AUDIT_RESOURCE";
|
||||
public static final String PROJECT_PIPELINE_CALLBACK_HISTORY="PROJECT_PIPELINE_CALLBACK_HISTORY";
|
||||
}
|
@ -33,6 +33,8 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 审计记录 Mapper 接口
|
||||
*/
|
||||
@ -48,9 +50,9 @@ public interface AuditDao {
|
||||
@Param("action") String action,
|
||||
@Param("actionContent") String actionContent,
|
||||
@Param("projectId") String projectId,
|
||||
@Param("id") String id
|
||||
@Param("id") Long id
|
||||
);
|
||||
TAuditResourceRecord listByResourceTye(
|
||||
List<TAuditResourceRecord> listByResourceTye(
|
||||
@Param("queryAudit") QueryAudit queryAudit,
|
||||
@Param("offset") Integer offset,
|
||||
@Param("limit") Integer limit
|
||||
|
@ -0,0 +1,26 @@
|
||||
package cd.casic.ci.process.process.dal.engin;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PipelineTriggerReviewDao {
|
||||
Integer createReviewRecord(
|
||||
@Param("buildId") String buildId,
|
||||
@Param("pipelineId") String pipelineId,
|
||||
@Param("projectId") String projectId,
|
||||
@Param("reviewers") List<String> reviewers
|
||||
);
|
||||
Integer updateOperator(
|
||||
@Param("projectId") String projectId,
|
||||
@Param("pipelineId") String pipelineId,
|
||||
@Param("buildId") String buildId,
|
||||
@Param("userId") String userId
|
||||
);
|
||||
List<String> getTriggerReviewers(
|
||||
@Param("projectId") String projectId,
|
||||
@Param("pipelineId") String pipelineId,
|
||||
@Param("buildId") String buildId
|
||||
);
|
||||
|
||||
}
|
@ -27,10 +27,13 @@
|
||||
|
||||
package cd.casic.ci.process.process.dal.pipeline;
|
||||
|
||||
import cd.casic.ci.process.api.process.pojo.PipelineStageTag;
|
||||
import cd.casic.ci.process.process.dataObject.TPipelineStageTagRecord;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流水线阶段标签Mapper接口
|
||||
*/
|
||||
@ -96,7 +99,7 @@ public interface PipelineStageTagDao {
|
||||
*
|
||||
* @return 所有阶段标签记录
|
||||
*/
|
||||
TPipelineStageTagRecord getAllStageTag();
|
||||
List<TPipelineStageTagRecord> getAllStageTag();
|
||||
|
||||
/**
|
||||
* 获取默认阶段标签
|
||||
@ -117,4 +120,14 @@ public interface PipelineStageTagDao {
|
||||
@Param("stageTagName") String stageTagName,
|
||||
@Param("weight") Integer weight
|
||||
);
|
||||
static PipelineStageTag convert(TPipelineStageTagRecord record, Boolean defaultFlag){
|
||||
return new PipelineStageTag(
|
||||
record.getId(),
|
||||
record.getStageTagName(),
|
||||
record.getWeight(),
|
||||
defaultFlag,
|
||||
record.getCreateTime().getTime(),
|
||||
record.getUpdateTime().getTime()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cd.casic.ci.process.process.event.callback.listener;
|
||||
|
||||
|
||||
import cd.casic.ci.project.pojo.mq.ProjectBroadCastEvent;
|
||||
import cd.casic.ci.project.pojo.mq.ProjectCreateBroadCastEvent;
|
||||
import cd.casic.ci.project.pojo.mq.ProjectEnableStatusBroadCastEvent;
|
||||
import cd.casic.ci.project.pojo.mq.ProjectUpdateBroadCastEvent;
|
||||
import cd.casic.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ProjectCallbackEventListener extends AbstractRedisStreamMessageListener<ProjectBroadCastEvent> {
|
||||
@Override
|
||||
public void onMessage(ProjectBroadCastEvent message) {
|
||||
log.info("Receive ProjectEvent from MQ [$event]");
|
||||
try {
|
||||
if (message instanceof ProjectUpdateBroadCastEvent) {
|
||||
|
||||
} else if (message instanceof ProjectEnableStatusBroadCastEvent) {
|
||||
|
||||
} else if (message instanceof ProjectCreateBroadCastEvent) {
|
||||
|
||||
}
|
||||
// when (event) {
|
||||
// is ProjectUpdateBroadCastEvent -> {
|
||||
// onReceiveProjectUpdate(event)
|
||||
// }
|
||||
//
|
||||
// is ProjectEnableStatusBroadCastEvent -> {
|
||||
// onReceiveProjectEnable(event)
|
||||
// }
|
||||
//
|
||||
// is ProjectCreateBroadCastEvent -> {
|
||||
// onReceiveProjectCreate(event)
|
||||
// }
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("BKSystemMonitor| project callback listener execute error", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,594 @@
|
||||
package cd.casic.ci.process.process.event.engine.control;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.Model;
|
||||
import cd.casic.ci.common.pipeline.container.Container;
|
||||
import cd.casic.ci.common.pipeline.container.Stage;
|
||||
import cd.casic.ci.common.pipeline.enums.BuildStatus;
|
||||
import cd.casic.ci.common.pipeline.enums.CallBackEvent;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.enums.ProjectPipelineCallbackStatus;
|
||||
import cd.casic.ci.common.pipeline.pojo.element.Element;
|
||||
import cd.casic.ci.common.pipeline.pojo.event.ProjectPipelineCallBack;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.service.utils.LogUtils;
|
||||
import cd.casic.ci.process.api.engine.pojo.PipelineInfo;
|
||||
import cd.casic.ci.process.api.engine.pojo.event.PipelineStreamEnabledEvent;
|
||||
import cd.casic.ci.process.api.process.pojo.ProjectPipelineCallBackHistory;
|
||||
import cd.casic.ci.process.api.process.pojo.pipeline.ModelDetail;
|
||||
import cd.casic.ci.process.process.constant.AllocIdGenerateConstant;
|
||||
import cd.casic.ci.process.process.service.base.PipelineBuildDetailServiceImpl;
|
||||
import cd.casic.ci.process.process.service.base.engin.service.PipelineRepositoryService;
|
||||
import cd.casic.ci.process.process.service.base.engin.service.ProjectPipelineCallBackService;
|
||||
import cd.casic.ci.process.process.service.base.engin.service.ProjectPipelineCallBackUrlGenerator;
|
||||
import cd.casic.ci.process.process.service.base.pojo.*;
|
||||
import cd.casic.ci.process.process.service.base.pojo.constant.CallbackConstants;
|
||||
import cd.casic.ci.project.service.ServiceAllocIdResource;
|
||||
import cd.casic.framework.commons.util.watcher.Watcher;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CallNotPermittedException;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import okhttp3.*;
|
||||
import org.apache.commons.lang3.tuple.ImmutableTriple;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
@Service
|
||||
public class CallBackControl {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CallBackControl.class);
|
||||
private static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
|
||||
private static final int MAX_RETRY_COUNT = 3;
|
||||
private static final long DEFAULT_FAILURE_DISABLE_TIME_PERIOD = 12 * 60 * 60 * 1000L;
|
||||
private static final String PIPELINE_CALLBACK_COUNT = "pipeline_callback_count";
|
||||
private static final long connectTimeout = 3L;
|
||||
private static final long readTimeout = 3L;
|
||||
private static final long writeTimeout = 3L;
|
||||
|
||||
private final PipelineBuildDetailServiceImpl pipelineBuildDetailService;
|
||||
private final PipelineRepositoryService pipelineRepositoryService;
|
||||
private final ProjectPipelineCallBackService projectPipelineCallBackService;
|
||||
private final CircuitBreakerRegistry callbackCircuitBreakerRegistry;
|
||||
private final MeterRegistry meterRegistry;
|
||||
private final ProjectPipelineCallBackUrlGenerator projectPipelineCallBackUrlGenerator;
|
||||
private ServiceAllocIdResource serviceAllocIdResource;
|
||||
|
||||
@Value("${callback.failureDisableTimePeriod:#{43200000}}")
|
||||
private long failureDisableTimePeriod = DEFAULT_FAILURE_DISABLE_TIME_PERIOD;
|
||||
|
||||
@Autowired
|
||||
public CallBackControl(
|
||||
PipelineBuildDetailServiceImpl pipelineBuildDetailService,
|
||||
PipelineRepositoryService pipelineRepositoryService,
|
||||
ProjectPipelineCallBackService projectPipelineCallBackService,
|
||||
CircuitBreakerRegistry callbackCircuitBreakerRegistry,
|
||||
MeterRegistry meterRegistry,
|
||||
ProjectPipelineCallBackUrlGenerator projectPipelineCallBackUrlGenerator,
|
||||
ServiceAllocIdResource serviceAllocIdResource
|
||||
) {
|
||||
this.pipelineBuildDetailService = pipelineBuildDetailService;
|
||||
this.pipelineRepositoryService = pipelineRepositoryService;
|
||||
this.projectPipelineCallBackService = projectPipelineCallBackService;
|
||||
this.callbackCircuitBreakerRegistry = callbackCircuitBreakerRegistry;
|
||||
this.meterRegistry = meterRegistry;
|
||||
this.projectPipelineCallBackUrlGenerator = projectPipelineCallBackUrlGenerator;
|
||||
this.serviceAllocIdResource = serviceAllocIdResource;
|
||||
}
|
||||
|
||||
// 静态初始化块
|
||||
private static final SSLSocketFactory anySslSocketFactory;
|
||||
private static final TrustManager[] trustAnyCerts;
|
||||
private static final OkHttpClient callbackClient;
|
||||
|
||||
static {
|
||||
trustAnyCerts = new TrustManager[]{
|
||||
new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||
sslContext.init(null, trustAnyCerts, new java.security.SecureRandom());
|
||||
anySslSocketFactory = sslContext.getSocketFactory();
|
||||
} catch (Exception e) {
|
||||
// throw new RemoteServiceException(e.getMessage()); TODO 添加项目报错
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
|
||||
callbackClient = new OkHttpClient.Builder()
|
||||
.connectTimeout(connectTimeout, TimeUnit.SECONDS)
|
||||
.readTimeout(readTimeout, TimeUnit.SECONDS)
|
||||
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
|
||||
.sslSocketFactory(anySslSocketFactory, (X509TrustManager) trustAnyCerts[0])
|
||||
.hostnameVerifier((hostname, session) -> true)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void pipelineCreateEvent(String projectId, String pipelineId) {
|
||||
callBackPipelineEvent(projectId, pipelineId, CallBackEvent.CREATE_PIPELINE);
|
||||
}
|
||||
|
||||
public void pipelineDeleteEvent(String projectId, String pipelineId) {
|
||||
callBackPipelineEvent(projectId, pipelineId, CallBackEvent.DELETE_PIPELINE);
|
||||
}
|
||||
|
||||
public void pipelineUpdateEvent(String projectId, String pipelineId) {
|
||||
callBackPipelineEvent(projectId, pipelineId, CallBackEvent.UPDATE_PIPELINE);
|
||||
}
|
||||
|
||||
public void pipelineRestoreEvent(String projectId, String pipelineId) {
|
||||
callBackPipelineEvent(projectId, pipelineId, CallBackEvent.RESTORE_PIPELINE);
|
||||
}
|
||||
|
||||
public void projectCreate(String projectId, String projectName, String userId) {
|
||||
callBackProjectEvent(projectId, projectName, userId, true, CallBackEvent.PROJECT_CREATE);
|
||||
}
|
||||
|
||||
public void projectUpdate(String projectId, String projectName, String userId) {
|
||||
callBackProjectEvent(projectId, projectName, userId, true, CallBackEvent.PROJECT_UPDATE);
|
||||
}
|
||||
|
||||
public void projectEnable(String projectId, String projectName, String userId) {
|
||||
callBackProjectEvent(projectId, projectName, userId, true, CallBackEvent.PROJECT_ENABLE);
|
||||
}
|
||||
|
||||
public void projectDisable(String projectId, String projectName, String userId) {
|
||||
callBackProjectEvent(projectId, projectName, userId, false, CallBackEvent.PROJECT_DISABLE);
|
||||
}
|
||||
|
||||
public void pipelineStreamEnabledEvent(PipelineStreamEnabledEvent event) {
|
||||
logger.info(event.getProjectId() + "|STREAM_ENABLED|callback stream enable event");
|
||||
List<ProjectPipelineCallBack> list = projectPipelineCallBackService.listProjectCallBack(
|
||||
event.getProjectId(),
|
||||
CallBackEvent.STREAM_ENABLED.name()
|
||||
);
|
||||
StreamEnabledEvent streamEnabledEvent = new StreamEnabledEvent(
|
||||
event.getUserId(),
|
||||
event.getGitProjectId(),
|
||||
event.getGitProjectUrl(),
|
||||
event.isEnable()
|
||||
);
|
||||
sendToCallBack(new CallBackData<StreamEnabledEvent>(CallBackEvent.STREAM_ENABLED, streamEnabledEvent), list);
|
||||
}
|
||||
|
||||
private void callBackPipelineEvent(String projectId, String pipelineId, CallBackEvent callBackEvent) {
|
||||
logger.info(projectId + "|" + pipelineId + "|" + callBackEvent + "|callback pipeline event");
|
||||
List<ProjectPipelineCallBack> list = projectPipelineCallBackService.listProjectCallBack(
|
||||
projectId,
|
||||
callBackEvent.name()
|
||||
);
|
||||
if (list.isEmpty()) {
|
||||
logger.info("[" + pipelineId + "]|[" + callBackEvent + "]| no callback");
|
||||
return;
|
||||
}
|
||||
|
||||
PipelineInfo pipelineInfo = pipelineRepositoryService.getPipelineInfo(
|
||||
projectId,
|
||||
pipelineId,
|
||||
null,
|
||||
false
|
||||
);
|
||||
if (pipelineInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PipelineEvent pipelineEvent = new PipelineEvent(
|
||||
pipelineInfo.getPipelineId(),
|
||||
pipelineInfo.getPipelineName(),
|
||||
pipelineInfo.getLastModifyUser(),
|
||||
pipelineInfo.getUpdateTime(),
|
||||
pipelineInfo.getProjectId()
|
||||
);
|
||||
|
||||
sendToCallBack(new CallBackData<>(callBackEvent, pipelineEvent), list);
|
||||
}
|
||||
|
||||
private void callBackProjectEvent(
|
||||
String projectId,
|
||||
String projectName,
|
||||
String userId,
|
||||
boolean enable,
|
||||
CallBackEvent callBackEvent
|
||||
) {
|
||||
logger.info(projectId + "|" + projectName + "|" + callBackEvent + "|callback project event");
|
||||
List<ProjectPipelineCallBack> list = projectPipelineCallBackService.listProjectCallBack(
|
||||
CallbackConstants.DEVOPS_ALL_PROJECT,
|
||||
callBackEvent.name()
|
||||
);
|
||||
if (list.isEmpty()) {
|
||||
logger.info("no [" + callBackEvent + "] project callback");
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectCallbackEvent projectEvent = new ProjectCallbackEvent(
|
||||
projectId,
|
||||
projectName,
|
||||
enable,
|
||||
userId
|
||||
);
|
||||
|
||||
sendToCallBack(new CallBackData<>(callBackEvent, projectEvent), list);
|
||||
}
|
||||
|
||||
public void callBackBuildEvent(PipelineBuildStatusBroadCastEvent event) {
|
||||
String projectId = event.getProjectId();
|
||||
String pipelineId = event.getPipelineId();
|
||||
String buildId = event.getBuildId();
|
||||
if (event.getAtomCode() != null && VmOperateTaskGenerator.isVmAtom(event.getAtomCode())) {
|
||||
return;
|
||||
}
|
||||
CallBackEvent callBackEvent = EventUtils.toEventType(event);
|
||||
if (callBackEvent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(projectId + "|" + pipelineId + "|" + buildId + "|" + callBackEvent.name() + "|" +
|
||||
event.getStageId() + "|" + event.getTaskId() + "|callback");
|
||||
|
||||
List<ProjectPipelineCallBack> list = new ArrayList<>();
|
||||
list.addAll(projectPipelineCallBackService.listProjectCallBack(
|
||||
projectId,
|
||||
callBackEvent.name()
|
||||
));
|
||||
|
||||
List<ProjectPipelineCallBack> pipelineCallback = projectPipelineCallBackService.getPipelineCallback(
|
||||
projectId,
|
||||
pipelineId,
|
||||
callBackEvent.name()
|
||||
);
|
||||
if (pipelineCallback.isEmpty()) {
|
||||
pipelineCallback = pipelineRepositoryService.getPipelineResourceVersion(
|
||||
projectId,
|
||||
pipelineId,
|
||||
null,
|
||||
false
|
||||
).getModel().getPipelineCallBack(
|
||||
projectId,
|
||||
callBackEvent
|
||||
);
|
||||
if (pipelineCallback == null) {
|
||||
pipelineCallback = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
if (!pipelineCallback.isEmpty()) {
|
||||
list.addAll(pipelineCallback);
|
||||
}
|
||||
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModelDetail modelDetail = pipelineBuildDetailService.get(
|
||||
projectId,
|
||||
event.getBuildId(),
|
||||
false
|
||||
);
|
||||
if (modelDetail == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuildEvent buildEvent = new BuildEvent(
|
||||
event.getBuildId(),
|
||||
modelDetail.getPipelineId(),
|
||||
modelDetail.getPipelineName(),
|
||||
modelDetail.getUserId(),
|
||||
modelDetail.getTriggerUser(),
|
||||
modelDetail.getCancelUserId(),
|
||||
modelDetail.getStatus(),
|
||||
modelDetail.getStartTime(),
|
||||
modelDetail.getEndTime() != null ? modelDetail.getEndTime() : 0,
|
||||
new SimpleModel(parseModel(modelDetail.getModel())),
|
||||
event.getProjectId(),
|
||||
modelDetail.getTrigger(),
|
||||
event.getStageId(),
|
||||
event.getTaskId(),
|
||||
modelDetail.getBuildNum(),
|
||||
modelDetail.getDebug()
|
||||
);
|
||||
sendToCallBack(new CallBackData<>(callBackEvent, buildEvent), list);
|
||||
}
|
||||
|
||||
private <T> void sendToCallBack(CallBackData<T> callBackData, List<ProjectPipelineCallBack> list){
|
||||
String requestBody = com.alibaba.fastjson.JSON.toJSONString(callBackData);
|
||||
|
||||
list.forEach(callBack -> {
|
||||
String uniqueId = "";
|
||||
if (callBackData.getData() instanceof PipelineEvent) {
|
||||
uniqueId = ((PipelineEvent) callBackData.getData()).getPipelineId();
|
||||
} else if (callBackData.getData() instanceof BuildEvent) {
|
||||
uniqueId = ((BuildEvent) callBackData.getData()).getBuildId();
|
||||
}
|
||||
|
||||
Watcher watcher = new Watcher(callBack.getProjectId() + "|" + callBack.getCallBackUrl() +
|
||||
"|" + callBack.getEvents() + "|" + uniqueId);
|
||||
try {
|
||||
logger.info(callBack.getProjectId() + "|" + callBack.getCallBackUrl() + "|" +
|
||||
uniqueId + "|" + callBack.getEvents() + "|send to callback");
|
||||
if (callBack.getCallBackUrl().isBlank()) {
|
||||
logger.warn("[" + callBack.getProjectId() + "]| call back url is empty!");
|
||||
return;
|
||||
}
|
||||
send(uniqueId, callBack, requestBody);
|
||||
} catch (Exception e) {
|
||||
logger.error("BKSystemErrorMonitor|" + callBack.getProjectId() + "|" +
|
||||
callBack.getCallBackUrl() + "|" + callBack.getEvents() + "|" + e.getMessage(), e);
|
||||
} finally {
|
||||
watcher.stop();
|
||||
LogUtils.printCostTimeWE(watcher, 2000,5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void send(String uniqueId, ProjectPipelineCallBack callBack, String requestBody) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Request.Builder builder = new Request.Builder()
|
||||
.url(callBack.getCallBackUrl())
|
||||
.header("X-DEVOPS-WEBHOOK-TOKEN", callBack.getSecretToken() != null ? callBack.getSecretToken() : "NONE")
|
||||
// TODO .header(TraceTag.TRACE_HEADER_DEVOPS_BIZID, TraceTag.buildBiz())
|
||||
.post(RequestBody.create(JSON, requestBody));
|
||||
|
||||
if (callBack.getSecretParam() != null) {
|
||||
callBack.getSecretParam().secret(builder);
|
||||
}
|
||||
|
||||
Request request = builder.build();
|
||||
|
||||
String errorMsg = null;
|
||||
ProjectPipelineCallbackStatus status = ProjectPipelineCallbackStatus.SUCCESS;
|
||||
CircuitBreaker breaker = callbackCircuitBreakerRegistry.circuitBreaker(callBack.getCallBackUrl());
|
||||
try {
|
||||
breaker.executeCallable(() -> {
|
||||
// TODO HttpRetryUtils.retry(MAX_RETRY_COUNT, () -> {
|
||||
// callbackClient.newCall(request).execute().closeQuietly();
|
||||
// });
|
||||
if (callBack.getFailureTime() != null) {
|
||||
projectPipelineCallBackService.updateFailureTime(
|
||||
callBack.getProjectId(),
|
||||
callBack.getId(),
|
||||
null
|
||||
);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
} catch (CallNotPermittedException e) {
|
||||
logger.warn(
|
||||
"[" + callBack.getProjectId() + "]|CALL_BACK|url=" + callBack.getCallBackUrl() +
|
||||
"|" + callBack.getEvents() + "|failureRate=" + breaker.getMetrics().getFailureRate() +
|
||||
"|" + e.getMessage()
|
||||
);
|
||||
checkIfNeedDisable(breaker, callBack);
|
||||
errorMsg = e.getMessage();
|
||||
status = ProjectPipelineCallbackStatus.FAILED;
|
||||
} catch (Exception e) {
|
||||
logger.warn(
|
||||
"BKSystemErrorMonitor|[" + callBack.getProjectId() + "]|CALL_BACK|" +
|
||||
"url=" + callBack.getCallBackUrl() + "|" + callBack.getEvents(),
|
||||
e
|
||||
);
|
||||
errorMsg = e.getMessage();
|
||||
status = ProjectPipelineCallbackStatus.FAILED;
|
||||
} finally {
|
||||
String originUrl = projectPipelineCallBackUrlGenerator.decodeCallbackUrl(
|
||||
request.url().toString()
|
||||
);
|
||||
String realUrl = originUrl.substring(originUrl.indexOf("?"));
|
||||
try {
|
||||
String host = new URL(realUrl).getHost();
|
||||
Counter.builder(PIPELINE_CALLBACK_COUNT)
|
||||
.tags(
|
||||
Tags.of("status", status.name())
|
||||
.and("host",host)
|
||||
.and("event", callBack.getEvents())
|
||||
)
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
saveHistory(
|
||||
callBack,
|
||||
Collections.singletonList(new ProjectPipelineCallBackHistory.CallBackHeader("X-DEVOPS-WEBHOOK-UNIQUE-ID", uniqueId)),
|
||||
status.name(),
|
||||
errorMsg,
|
||||
startTime,
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfNeedDisable(CircuitBreaker breaker, ProjectPipelineCallBack callBack) {
|
||||
if (breaker.getMetrics().getFailureRate() == 100.0F) {
|
||||
long duration = 0;
|
||||
if (callBack.getFailureTime() != null) {
|
||||
duration = System.currentTimeMillis() - callBack.getFailureTime().atOffset(ZoneOffset.UTC).toInstant().toEpochMilli();
|
||||
} else {
|
||||
projectPipelineCallBackService.updateFailureTime(
|
||||
callBack.getProjectId(),
|
||||
callBack.getId(),
|
||||
LocalDateTime.now()
|
||||
);
|
||||
}
|
||||
if (duration >= failureDisableTimePeriod) {
|
||||
logger.warn(
|
||||
"disable callbacks because of 100% failure rate|" +
|
||||
"[" + callBack.getProjectId() + "]|CALL_BACK|url=" + callBack.getCallBackUrl() +
|
||||
"|" + callBack.getEvents() + "|duration=" + duration
|
||||
);
|
||||
projectPipelineCallBackService.disable(callBack.getProjectId(), callBack.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveHistory(
|
||||
ProjectPipelineCallBack callBack,
|
||||
List<ProjectPipelineCallBackHistory.CallBackHeader> requestHeaders,
|
||||
String status,
|
||||
String errorMsg,
|
||||
long startTime,
|
||||
long endTime
|
||||
) {
|
||||
try {
|
||||
projectPipelineCallBackService.createHistory(
|
||||
new ProjectPipelineCallBackHistory(
|
||||
serviceAllocIdResource.generateSegmentId(AllocIdGenerateConstant.PROJECT_PIPELINE_CALLBACK_HISTORY)
|
||||
,
|
||||
callBack.getProjectId(),
|
||||
callBack.getCallBackUrl(),
|
||||
callBack.getEvents(),
|
||||
status,
|
||||
requestHeaders,
|
||||
"",
|
||||
0,
|
||||
"",
|
||||
errorMsg,
|
||||
null,
|
||||
startTime,
|
||||
endTime
|
||||
// client.get(ServiceAllocIdResource.class)
|
||||
// .generateSegmentId("PROJECT_PIPELINE_CALLBACK_HISTORY").getData()
|
||||
)
|
||||
);
|
||||
} catch (Throwable e) {
|
||||
logger.error("[" + callBack.getProjectId() + "]|[" + callBack.getCallBackUrl() +
|
||||
"]|[" + callBack.getEvents() + "]|save fail", e);
|
||||
}
|
||||
}
|
||||
|
||||
List<SimpleStage> parseModel(Model model) {
|
||||
List<SimpleStage> stages = new ArrayList<>();
|
||||
for (int pos = 0; pos < model.getStages().size(); pos++) {
|
||||
Stage s = model.getStages().get(pos);
|
||||
List<SimpleJob> jobs = new ArrayList<>();
|
||||
SimpleStage stage = new SimpleStage(
|
||||
"Stage-" + (pos + 1),
|
||||
s.getName() != null ? s.getName() : "",
|
||||
jobs
|
||||
);
|
||||
logger.info("parseModel " + model.getName() + "|" + stage.getStageName() +
|
||||
"|" + stage.getName() + "|");
|
||||
stage.setStartTime(s.getStartEpoch() != null ? s.getStartEpoch() : 0);
|
||||
stages.add(stage);
|
||||
|
||||
Triple<Long, Long, BuildStatus> triple = parseJob(s, jobs);
|
||||
long stageStartTimeMills = triple.getLeft();
|
||||
long stageEndTimeMills = triple.getMiddle();
|
||||
BuildStatus stageStatus = triple.getRight();
|
||||
|
||||
if (stage.getStartTime() == 0L && stageStartTimeMills > 0) {
|
||||
stage.setStartTime(stageStartTimeMills);
|
||||
}
|
||||
|
||||
if (stageEndTimeMills > 0) {
|
||||
stage.setEndTime(stageEndTimeMills);
|
||||
}
|
||||
|
||||
stage.setStatus(stageStatus.name());
|
||||
}
|
||||
return stages;
|
||||
}
|
||||
|
||||
private Triple<Long, Long, BuildStatus> parseJob(Stage s, List<SimpleJob> jobs) {
|
||||
long stageStartTimeMills = Long.MAX_VALUE;
|
||||
long stageEndTimeMills = 1L;
|
||||
BuildStatus stageStatus = BuildStatus.QUEUE;
|
||||
for (Container c : s.getContainers()) {
|
||||
BuildStatus jobStatus = BuildStatus.parse(c.getStatus());
|
||||
long jobStartTimeMills = c.getStartEpoch() != null ? c.getStartEpoch() : 0L;
|
||||
long jobEndTimeMills = jobStatus.isFinish() ?
|
||||
jobStartTimeMills + (c.getElementElapsed() != null ? c.getElementElapsed() : 0) +
|
||||
(c.getSystemElapsed() != null ? c.getSystemElapsed() : 0) : 0;
|
||||
|
||||
if (stageStartTimeMills > jobStartTimeMills) {
|
||||
stageStartTimeMills = jobStartTimeMills;
|
||||
}
|
||||
|
||||
if (jobEndTimeMills == 0L) {
|
||||
stageStatus = jobStatus;
|
||||
stageEndTimeMills = jobEndTimeMills;
|
||||
} else if (stageEndTimeMills >= 1 && stageEndTimeMills < jobEndTimeMills) {
|
||||
stageEndTimeMills = jobEndTimeMills;
|
||||
if (jobStatus.isFailure()) {
|
||||
stageStatus = jobStatus;
|
||||
}
|
||||
}
|
||||
|
||||
jobs.add(
|
||||
new SimpleJob(
|
||||
c.getName(),
|
||||
jobStatus.name(),
|
||||
jobStartTimeMills,
|
||||
jobEndTimeMills,
|
||||
parseTask(c)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (stageEndTimeMills > 0 && !stageStatus.isFinish()) {
|
||||
stageStatus = BuildStatus.SUCCEED;
|
||||
}
|
||||
return new ImmutableTriple<>(stageStartTimeMills, stageEndTimeMills, stageStatus);
|
||||
}
|
||||
|
||||
private List<SimpleTask> parseTask(Container c) {
|
||||
List<SimpleTask> tasks = new ArrayList<>();
|
||||
for (Element e : c.getElements()) {
|
||||
long taskStartTimeMills = e.getStartEpoch() != null ? e.getStartEpoch() : 0;
|
||||
BuildStatus taskStatus = BuildStatus.parse(e.getStatus());
|
||||
long taskEndTimeMills = taskStatus.isFinish() ?
|
||||
taskStartTimeMills + (e.getElapsed() != null ? e.getElapsed() : 0) : 0;
|
||||
tasks.add(
|
||||
new SimpleTask(
|
||||
e.getId(),
|
||||
e.getName(),
|
||||
e.getAtomCode(),
|
||||
taskStatus.name(),
|
||||
taskStartTimeMills,
|
||||
taskEndTimeMills
|
||||
)
|
||||
);
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.ci.process.process.service.audit;
|
||||
|
||||
import cd.casic.ci.common.pipeline.model.SQLPage;
|
||||
import cd.casic.ci.process.api.process.pojo.audit.Audit;
|
||||
import cd.casic.ci.process.api.process.pojo.audit.AuditInfo;
|
||||
import cd.casic.ci.process.api.process.pojo.audit.QueryAudit;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
public interface AuditService {
|
||||
Long createAudit(Audit audit);
|
||||
|
||||
Pair<SQLPage<AuditInfo>, Boolean> userList(QueryAudit queryAudit, Integer offset, Integer limit);
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package cd.casic.ci.process.process.service.audit.impl;
|
||||
|
||||
import cd.casic.ci.common.pipeline.constant.CommonConstants;
|
||||
import cd.casic.ci.common.pipeline.model.SQLPage;
|
||||
import cd.casic.ci.process.api.process.pojo.audit.Audit;
|
||||
import cd.casic.ci.process.api.process.pojo.audit.AuditInfo;
|
||||
import cd.casic.ci.process.api.process.pojo.audit.QueryAudit;
|
||||
import cd.casic.ci.process.process.constant.AllocIdGenerateConstant;
|
||||
import cd.casic.ci.process.process.dal.audit.AuditDao;
|
||||
import cd.casic.ci.process.process.dataObject.TAuditResourceRecord;
|
||||
import cd.casic.ci.process.process.service.audit.AuditService;
|
||||
import cd.casic.ci.project.service.ServiceAllocIdResource;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AuditServiceImpl implements AuditService {
|
||||
@Resource
|
||||
private AuditDao auditDao;
|
||||
@Resource
|
||||
private ServiceAllocIdResource serviceAllocIdResource;
|
||||
|
||||
@Override
|
||||
public Long createAudit(Audit audit) {
|
||||
Long id = serviceAllocIdResource.generateSegmentId(AllocIdGenerateConstant.AUDIT_RESOURCE);
|
||||
return auditDao.create(
|
||||
audit.getResourceType(),
|
||||
audit.getResourceId(),
|
||||
audit.getResourceName(),
|
||||
audit.getUserId(),
|
||||
audit.getAction(),
|
||||
audit.getActionContent(),
|
||||
audit.getProjectId(),
|
||||
id
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<SQLPage<AuditInfo>, Boolean> userList(QueryAudit queryAudit, Integer offset, Integer limit) {
|
||||
Long count = auditDao.countByResourceTye(queryAudit);
|
||||
List<TAuditResourceRecord> auditRecordList = auditDao.listByResourceTye(queryAudit, offset, limit);
|
||||
List<AuditInfo> auditList = auditRecordList.stream().map(it -> {
|
||||
String statusStr = "1".equals(it.getStatus()) ? CommonConstants.SUCCESS : CommonConstants.FAIL;
|
||||
return new AuditInfo(
|
||||
it.getStatus(),
|
||||
it.getResourceType(),
|
||||
it.getResourceId(),
|
||||
it.getResourceName(),
|
||||
it.getUserId(),
|
||||
it.getCreatedTime().getTime(),
|
||||
it.getAction(),
|
||||
it.getActionContent()
|
||||
);
|
||||
}).toList();
|
||||
|
||||
return new ImmutablePair<>(new SQLPage<>(count,auditList),true);
|
||||
}
|
||||
}
|
@ -0,0 +1,304 @@
|
||||
package cd.casic.ci.process.process.service.base;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.Model;
|
||||
import cd.casic.ci.common.pipeline.container.Container;
|
||||
import cd.casic.ci.common.pipeline.container.Stage;
|
||||
import cd.casic.ci.process.process.service.base.dispatcher.PipelineEventDispatcher;
|
||||
import cd.casic.ci.common.pipeline.enums.BuildStatus;
|
||||
import cd.casic.ci.common.pipeline.enums.ChannelCode;
|
||||
import cd.casic.ci.common.pipeline.pojo.element.Element;
|
||||
import cd.casic.ci.process.api.process.pojo.BuildStageStatus;
|
||||
import cd.casic.ci.process.process.dal.pipeline.PipelineBuildDao;
|
||||
import cd.casic.ci.process.process.dal.record.BuildDetailDao;
|
||||
import cd.casic.ci.process.process.dataObject.TPipelineBuildDetailRecord;
|
||||
import cd.casic.ci.process.process.service.base.pojo.PipelineBuildWebSocketPushEvent;
|
||||
import cd.casic.ci.process.process.service.base.pojo.enums.RefreshType;
|
||||
import cd.casic.framework.commons.util.watcher.LogUtils;
|
||||
import cd.casic.framework.commons.util.watcher.Watcher;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.assertj.core.util.Preconditions;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cd.casic.ci.common.pipeline.constant.CommonConstants.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BaseBuildDetailServiceImpl {
|
||||
|
||||
|
||||
protected static final String TRIGGER_STAGE = "stage-1";
|
||||
|
||||
protected PipelineBuildDao pipelineBuildDao;
|
||||
protected BuildDetailDao buildDetailDao;
|
||||
private StageTagServiceImpl stageTagServiceImpl;
|
||||
private PipelineEventDispatcher pipelineEventDispatcher;
|
||||
|
||||
// TODO 更改redis逻辑
|
||||
// protected RedisOperation redisOperation;
|
||||
|
||||
public BaseBuildDetailServiceImpl(
|
||||
PipelineBuildDao pipelineBuildDao,
|
||||
BuildDetailDao buildDetailDao,
|
||||
StageTagServiceImpl stageTagServiceImpl,
|
||||
PipelineEventDispatcher pipelineEventDispatcher
|
||||
// RedisOperation redisOperation
|
||||
) {
|
||||
|
||||
this.pipelineBuildDao = pipelineBuildDao;
|
||||
this.buildDetailDao = buildDetailDao;
|
||||
this.stageTagServiceImpl = stageTagServiceImpl;
|
||||
this.pipelineEventDispatcher = pipelineEventDispatcher;
|
||||
// this.redisOperation = redisOperation;
|
||||
}
|
||||
|
||||
public Model getBuildModel(String projectId, String buildId) {
|
||||
var record = buildDetailDao.get(projectId, buildId);
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseObject(record.getModel(), Model.class);
|
||||
}
|
||||
|
||||
protected Model update(
|
||||
String projectId,
|
||||
String buildId,
|
||||
ModelInterface modelInterface,
|
||||
BuildStatus buildStatus,
|
||||
String cancelUser,
|
||||
String operation
|
||||
) {
|
||||
Watcher watcher = new Watcher("updateDetail#" + buildId + "#" + operation);
|
||||
String message = "nothing";
|
||||
TPipelineBuildDetailRecord record = null;
|
||||
// var lock = new PipelineBuildDetailLock(redisOperation, buildId);
|
||||
ReentrantLock lock = new ReentrantLock();
|
||||
try {
|
||||
watcher.start("lock");
|
||||
lock.lock();
|
||||
|
||||
watcher.start("getDetail");
|
||||
record = buildDetailDao.get(projectId, buildId);
|
||||
Preconditions.checkArgument(record != null, "The build detail is not exist");
|
||||
|
||||
watcher.start("model");
|
||||
var model = JSON.parseObject(record.getModel(), Model.class);
|
||||
|
||||
watcher.start("traverseModel");
|
||||
traverseModel(model, modelInterface);
|
||||
watcher.stop();
|
||||
|
||||
String modelStr = null;
|
||||
if (modelInterface.needUpdate()) {
|
||||
watcher.start("toJson");
|
||||
modelStr = JSON.toJSONString(model, false);
|
||||
}
|
||||
|
||||
var statusPair = takeBuildStatus(record, buildStatus);
|
||||
if ((modelStr == null || modelStr.isBlank()) && !statusPair.getFirst()) {
|
||||
message = "Will not update";
|
||||
return model;
|
||||
}
|
||||
|
||||
watcher.start("updateModel");
|
||||
buildDetailDao.update(
|
||||
projectId,
|
||||
buildId,
|
||||
modelStr,
|
||||
statusPair.getSecond(),
|
||||
cancelUser != null ? cancelUser :
|
||||
(buildStatus.isCancel() && record.getCancelUser() == null) ? "System" : null
|
||||
);
|
||||
|
||||
message = "update done";
|
||||
return model;
|
||||
} catch (Throwable ignored) {
|
||||
message = ignored.getMessage() != null ? ignored.getMessage() : "";
|
||||
log.warn("[" + buildId + "]| Fail to update the build detail: " + ignored.getMessage(), ignored);
|
||||
watcher.start("getDetail");
|
||||
Preconditions.checkArgument(record != null, "The build detail is not exist");
|
||||
watcher.start("model");
|
||||
return JSON.parseObject(record.getModel(), Model.class);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
log.info("[" + buildId + "|" + buildStatus + "]|" + operation + "|update_detail_model| " + message);
|
||||
if (message.equals("update done")) {
|
||||
watcher.start("dispatchEvent");
|
||||
pipelineDetailChangeEvent(projectId, buildId);
|
||||
}
|
||||
LogUtils.printCostTimeWE(watcher);
|
||||
}
|
||||
}
|
||||
|
||||
protected List<BuildStageStatus> fetchHistoryStageStatus(
|
||||
Model model,
|
||||
BuildStatus buildStatus,
|
||||
List<String> reviewers,
|
||||
String errorMsg,
|
||||
String cancelUser
|
||||
) {
|
||||
Map<String, String> stageTagMap = stageTagServiceImpl.getAllStageTag().stream()
|
||||
.collect(Collectors.toMap(tag -> tag.getId(), tag -> tag.getStageTagName()));
|
||||
|
||||
String statusMessage;
|
||||
String reason;
|
||||
if (buildStatus == BuildStatus.REVIEWING) {
|
||||
statusMessage = BUILD_REVIEWING;
|
||||
reason = reviewers != null ? String.join(",", reviewers) : null;
|
||||
} else if (buildStatus == BuildStatus.STAGE_SUCCESS) {
|
||||
statusMessage = BUILD_STAGE_SUCCESS;
|
||||
reason = null;
|
||||
} else if (buildStatus.isFailure()) {
|
||||
statusMessage = BUILD_FAILED;
|
||||
reason = errorMsg != null ? errorMsg : buildStatus.name();
|
||||
} else if (buildStatus.isCancel()) {
|
||||
statusMessage = BUILD_CANCELED;
|
||||
reason = cancelUser;
|
||||
} else if (buildStatus.isSuccess()) {
|
||||
statusMessage = BUILD_COMPLETED;
|
||||
reason = null;
|
||||
} else {
|
||||
statusMessage = BUILD_RUNNING;
|
||||
reason = null;
|
||||
}
|
||||
|
||||
return model.getStages().stream()
|
||||
.map(stage -> new BuildStageStatus(
|
||||
stage.getId(),
|
||||
stage.getName() != null ? stage.getName() : stage.getId(),
|
||||
stage.getStatus(),
|
||||
stage.getTag() != null ? stage.getTag().stream()
|
||||
.map(tag -> stageTagMap.getOrDefault(tag, "null"))
|
||||
.collect(Collectors.toList()) : null,
|
||||
stage.getStartEpoch(),
|
||||
stage.getElapsed(),
|
||||
null,
|
||||
stage.getId().equals(TRIGGER_STAGE) ?
|
||||
"" : null
|
||||
))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Pair<Boolean, BuildStatus> takeBuildStatus(
|
||||
TPipelineBuildDetailRecord record,
|
||||
BuildStatus buildStatus
|
||||
) {
|
||||
var oldStatus = BuildStatus.parse(record.getStatus());
|
||||
if (!oldStatus.isFinish()) {
|
||||
return new Pair<>(true, buildStatus);
|
||||
} else {
|
||||
return new Pair<>(false, oldStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private void traverseModel(Model model, ModelInterface modelInterface) {
|
||||
for (var stage : model.getStages()) {
|
||||
var traverse = modelInterface.onFindStage(stage, model);
|
||||
if (traverse == Traverse.BREAK) {
|
||||
return;
|
||||
} else if (traverse == Traverse.SKIP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var container : stage.getContainers()) {
|
||||
var cTraverse = modelInterface.onFindContainer(container, stage);
|
||||
if (cTraverse == Traverse.BREAK) {
|
||||
return;
|
||||
} else if (cTraverse == Traverse.SKIP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var elements = container.getElements();
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
if (modelInterface.onFindElement(i, elements.get(i), container) == Traverse.BREAK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(container.getMatrixGroupFlag())) {
|
||||
var groupContainers = container.fetchGroupContainers();
|
||||
if (groupContainers != null) {
|
||||
for (var groupContainer : groupContainers) {
|
||||
var gTraverse = modelInterface.onFindContainer(groupContainer, stage);
|
||||
if (gTraverse == Traverse.BREAK) {
|
||||
return;
|
||||
} else if (gTraverse == Traverse.SKIP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var groupElements = groupContainer.getElements();
|
||||
for (int i = 0; i < groupElements.size(); i++) {
|
||||
if (modelInterface.onFindElement(i, groupElements.get(i), groupContainer) == Traverse.BREAK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pipelineDetailChangeEvent(String projectId, String buildId) {
|
||||
var pipelineBuildInfo = pipelineBuildDao.getUserBuildInfo( projectId, buildId);
|
||||
if (pipelineBuildInfo != null && pipelineBuildInfo.getChannelCode() == ChannelCode.GIT) {
|
||||
pipelineEventDispatcher.dispatch(
|
||||
new PipelineBuildWebSocketPushEvent(
|
||||
"recordDetail",
|
||||
pipelineBuildInfo.getProjectId(),
|
||||
pipelineBuildInfo.getPipelineId(),
|
||||
pipelineBuildInfo.getStartUser(),
|
||||
buildId,
|
||||
RefreshType.DETAIL.getBinary() | RefreshType.RECORD.getBinary(),
|
||||
pipelineBuildInfo.getExecuteCount()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected interface ModelInterface {
|
||||
default Traverse onFindStage(Stage stage, Model model) {
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
default Traverse onFindContainer(Container container, Stage stage) {
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
default Traverse onFindElement(int index, Element e, Container c) {
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
boolean needUpdate();
|
||||
}
|
||||
|
||||
public enum Traverse {
|
||||
BREAK,
|
||||
CONTINUE,
|
||||
SKIP
|
||||
}
|
||||
|
||||
public static class Pair<A, B> {
|
||||
private final A first;
|
||||
private final B second;
|
||||
|
||||
public Pair(A first, B second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public A getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public B getSecond() {
|
||||
return second;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,375 @@
|
||||
package cd.casic.ci.process.process.service.base;
|
||||
|
||||
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.Model;
|
||||
import cd.casic.ci.common.pipeline.container.Container;
|
||||
import cd.casic.ci.common.pipeline.container.Stage;
|
||||
import cd.casic.ci.common.pipeline.enums.BuildStatus;
|
||||
import cd.casic.ci.common.pipeline.enums.StartType;
|
||||
import cd.casic.ci.common.pipeline.pojo.BuildFormProperty;
|
||||
import cd.casic.ci.common.pipeline.pojo.element.Element;
|
||||
import cd.casic.ci.common.pipeline.pojo.element.ElementAdditionalOptions;
|
||||
import cd.casic.ci.process.api.engine.pojo.BuildInfo;
|
||||
import cd.casic.ci.process.api.engine.pojo.PipelineInfo;
|
||||
import cd.casic.ci.process.api.process.pojo.BuildStageStatus;
|
||||
import cd.casic.ci.process.api.process.utils.PipelineVarUtil;
|
||||
import cd.casic.ci.process.process.dal.engin.PipelineTriggerReviewDao;
|
||||
import cd.casic.ci.process.process.dataObject.TPipelineBuildDetailRecord;
|
||||
import cd.casic.ci.process.process.dataObject.TPipelineBuildSummaryRecord;
|
||||
import cd.casic.ci.process.process.service.base.dispatcher.PipelineEventDispatcher;
|
||||
import cd.casic.ci.common.pipeline.utils.ModelUtils;
|
||||
import cd.casic.ci.process.api.process.pojo.pipeline.ModelDetail;
|
||||
import cd.casic.ci.process.process.dal.pipeline.PipelineBuildDao;
|
||||
import cd.casic.ci.process.process.dal.record.BuildDetailDao;
|
||||
import cd.casic.ci.process.process.dal.record.PipelineBuildSummaryDao;
|
||||
import cd.casic.ci.process.process.service.base.engin.service.PipelineRepositoryService;
|
||||
import cd.casic.ci.process.process.service.base.engin.util.ContainerUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.github.fppt.jedismock.operations.RedisOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PipelineBuildDetailServiceImpl extends BaseBuildDetailServiceImpl {
|
||||
|
||||
@Value("${pipeline.build.retry.limit_days:21}")
|
||||
private int retryLimitDays;
|
||||
|
||||
private final PipelineRepositoryService pipelineRepositoryService;
|
||||
private PipelineBuildSummaryDao pipelineBuildSummaryDao;
|
||||
private final PipelineTriggerReviewDao pipelineTriggerReviewDao;
|
||||
|
||||
@Autowired
|
||||
public PipelineBuildDetailServiceImpl(
|
||||
PipelineRepositoryService pipelineRepositoryService,
|
||||
PipelineBuildSummaryDao pipelineBuildSummaryDao,
|
||||
PipelineTriggerReviewDao pipelineTriggerReviewDao,
|
||||
PipelineBuildDao pipelineBuildDao,
|
||||
BuildDetailDao buildDetailDao,
|
||||
RedisOperation redisOperation,
|
||||
StageTagServiceImpl stageTagServiceImpl,
|
||||
PipelineEventDispatcher pipelineEventDispatcher
|
||||
) {
|
||||
super(pipelineBuildDao, buildDetailDao, stageTagServiceImpl, pipelineEventDispatcher);
|
||||
this.pipelineRepositoryService = pipelineRepositoryService;
|
||||
this.pipelineBuildSummaryDao = pipelineBuildSummaryDao;
|
||||
this.pipelineTriggerReviewDao = pipelineTriggerReviewDao;
|
||||
}
|
||||
|
||||
private boolean checkPassDays(Long startTime) {
|
||||
if (retryLimitDays < 0 || startTime == null) {
|
||||
return true;
|
||||
}
|
||||
return (System.currentTimeMillis() - startTime) < TimeUnit.DAYS.toMillis(retryLimitDays);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询ModelDetail
|
||||
* @param projectId 项目Id
|
||||
* @param buildId 构建Id
|
||||
* @param refreshStatus 是否刷新状态
|
||||
*/
|
||||
public ModelDetail get(String projectId, String buildId, boolean refreshStatus) {
|
||||
TPipelineBuildDetailRecord record = buildDetailDao.get(projectId, buildId);
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BuildInfo buildInfo = pipelineBuildDao.getUserBuildInfo(
|
||||
projectId,
|
||||
buildId
|
||||
);
|
||||
if (buildInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PipelineInfo pipelineInfo = pipelineRepositoryService.getPipelineInfo(projectId, buildInfo.getPipelineId(),null,false);
|
||||
if (pipelineInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TPipelineBuildSummaryRecord buildSummaryRecord = pipelineBuildSummaryDao.get(projectId, buildInfo.getPipelineId());
|
||||
Model model = JSON.parseObject(record.getModel(), Model.class);
|
||||
|
||||
if (refreshStatus) {
|
||||
if (checkPassDays(buildInfo.getStartTime())) {
|
||||
ModelUtils.refreshCanRetry(model);
|
||||
}
|
||||
}
|
||||
|
||||
var triggerContainer = model.getTriggerContainer();
|
||||
if (triggerContainer.getBuildNo() != null) {
|
||||
triggerContainer.getBuildNo().setCurrentBuildNo(
|
||||
buildSummaryRecord != null ? buildSummaryRecord.getBuildNo() : triggerContainer.getBuildNo().getBuildNo()
|
||||
);
|
||||
}
|
||||
|
||||
List<BuildFormProperty> params = triggerContainer.getParams();
|
||||
List<BuildFormProperty> newParams = new ArrayList<BuildFormProperty>(params.size());
|
||||
params.forEach(it -> {
|
||||
var newVarName = PipelineVarUtil.oldVarToNewVar(it.getId());
|
||||
if (newVarName != null && !newVarName.isBlank()) {
|
||||
BuildFormProperty buildFormProperty = new BuildFormProperty();
|
||||
BeanUtils.copyProperties(it,buildFormProperty);
|
||||
buildFormProperty.setId(newVarName);
|
||||
newParams.add(buildFormProperty);
|
||||
} else {
|
||||
newParams.add(it);
|
||||
}
|
||||
});
|
||||
triggerContainer.setParams(newParams);
|
||||
|
||||
model.getStages().forEach(stage -> {
|
||||
stage.resetBuildOption(false);
|
||||
stage.getContainers().forEach(container -> {
|
||||
container.setContainerHashId(container.getContainerHashId() != null ?
|
||||
container.getContainerHashId() : container.getContainerId());
|
||||
container.setContainerId(container.getId());
|
||||
});
|
||||
});
|
||||
|
||||
List<String> triggerReviewers = pipelineTriggerReviewDao.getTriggerReviewers(
|
||||
projectId,
|
||||
pipelineInfo.getPipelineId(),
|
||||
buildId
|
||||
);
|
||||
|
||||
return new ModelDetail(
|
||||
record.getBuildId(),
|
||||
buildInfo.getPipelineId(),
|
||||
model.getName(),
|
||||
record.getStartUser() != null ? record.getStartUser() : "",
|
||||
buildInfo.getTriggerUser(),
|
||||
StartType.toReadableString(
|
||||
buildInfo.getTrigger(),
|
||||
buildInfo.getChannelCode(),
|
||||
""
|
||||
),
|
||||
record.getStartTime() != null ? record.getStartTime().getTime() :
|
||||
LocalDateTime.now().atOffset(ZoneOffset.UTC).toInstant().toEpochMilli(),
|
||||
record.getEndTime() != null ? record.getEndTime().getTime() : null,
|
||||
record.getStatus() != null ? record.getStatus() : "",
|
||||
model,
|
||||
System.currentTimeMillis(),
|
||||
buildInfo.getBuildNum(),
|
||||
record.getCancelUser() != null ? record.getCancelUser() : "",
|
||||
buildInfo.getVersion(),
|
||||
pipelineInfo.getVersion(),
|
||||
buildSummaryRecord != null ? buildSummaryRecord.getBuildNum() : -1,
|
||||
pipelineInfo.getLastModifyUser(),
|
||||
buildInfo.getExecuteTime(),
|
||||
triggerReviewers,
|
||||
buildInfo.isDebug()
|
||||
);
|
||||
}
|
||||
|
||||
public void updateModel(String projectId, String buildId, Model model) {
|
||||
buildDetailDao.update(
|
||||
projectId,
|
||||
buildId,
|
||||
JSON.toJSONString(model, false),
|
||||
BuildStatus.RUNNING,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public void buildCancel(String projectId, String buildId, BuildStatus buildStatus, String cancelUser) {
|
||||
log.info("Cancel the build {} by {}", buildId, cancelUser);
|
||||
update(
|
||||
projectId,
|
||||
buildId,
|
||||
new ModelInterface() {
|
||||
private boolean update = false;
|
||||
|
||||
@Override
|
||||
public Traverse onFindStage(Stage stage, Model model) {
|
||||
if (BuildStatus.parse(stage.getStatus()).isRunning()) {
|
||||
stage.setStatus(buildStatus.name());
|
||||
if (stage.getStartEpoch() == null) {
|
||||
stage.setElapsed(0L);
|
||||
} else {
|
||||
stage.setElapsed(System.currentTimeMillis() - stage.getStartEpoch());
|
||||
}
|
||||
update = true;
|
||||
}
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Traverse onFindContainer(Container container, Stage stage) {
|
||||
var status = BuildStatus.parse(container.getStatus());
|
||||
if (status == BuildStatus.PREPARE_ENV) {
|
||||
if (container.getStartEpoch() == null) {
|
||||
container.setSystemElapsed(0L);
|
||||
} else {
|
||||
container.setSystemElapsed(System.currentTimeMillis() - container.getStartEpoch());
|
||||
}
|
||||
update = true;
|
||||
}
|
||||
|
||||
var refreshFlag = status.isRunning() &&
|
||||
(container.getElements().get(0).getStatus() == null ||
|
||||
container.getElements().get(0).getStatus().isBlank()) &&
|
||||
container.getContainPostTaskFlag() != Boolean.TRUE;
|
||||
|
||||
if (status == BuildStatus.PREPARE_ENV || refreshFlag) {
|
||||
container.setName(ContainerUtils.getClearedQueueContainerName(container.getName()));
|
||||
container.setStatus(buildStatus.name());
|
||||
}
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Traverse onFindElement(int index, Element e, Container c) {
|
||||
if (e.getStatus() != null &&
|
||||
(e.getStatus().equals(BuildStatus.RUNNING.name()) ||
|
||||
e.getStatus().equals(BuildStatus.REVIEWING.name()))) {
|
||||
|
||||
String status;
|
||||
if (e.getStatus().equals(BuildStatus.RUNNING.name())) {
|
||||
var runCondition = e.getAdditionalOptions() != null ?
|
||||
e.getAdditionalOptions().getRunCondition() : null;
|
||||
if (runCondition == ElementAdditionalOptions.RunCondition.PRE_TASK_FAILED_EVEN_CANCEL) {
|
||||
status = BuildStatus.RUNNING.name();
|
||||
} else {
|
||||
status = BuildStatus.CANCELED.name();
|
||||
}
|
||||
} else {
|
||||
status = buildStatus.name();
|
||||
}
|
||||
|
||||
e.setStatus(status);
|
||||
if (c.getContainPostTaskFlag() != Boolean.TRUE) {
|
||||
c.setStatus(status);
|
||||
}
|
||||
|
||||
if (BuildStatus.parse(status).isFinish()) {
|
||||
if (e.getStartEpoch() != null) {
|
||||
e.setElapsed(System.currentTimeMillis() - e.getStartEpoch());
|
||||
}
|
||||
|
||||
long elementElapsed = 0L;
|
||||
for (var element : c.getElements()) {
|
||||
elementElapsed += element.getElapsed() != null ? element.getElapsed() : 0;
|
||||
if (element == e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
c.setElementElapsed(elementElapsed);
|
||||
}
|
||||
update = true;
|
||||
}
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needUpdate() {
|
||||
return update;
|
||||
}
|
||||
},
|
||||
BuildStatus.RUNNING,
|
||||
cancelUser,
|
||||
"buildCancel"
|
||||
);
|
||||
}
|
||||
|
||||
public Pair<Model, List<BuildStageStatus>> buildEnd(
|
||||
String projectId,
|
||||
String buildId,
|
||||
BuildStatus buildStatus,
|
||||
String errorMsg
|
||||
) {
|
||||
log.info("[{}]|BUILD_END|buildStatus={}", buildId, buildStatus);
|
||||
final List<BuildStageStatus> allStageStatus = new ArrayList<>();
|
||||
|
||||
var model = update(
|
||||
projectId,
|
||||
buildId,
|
||||
new ModelInterface() {
|
||||
private boolean update = false;
|
||||
|
||||
@Override
|
||||
public Traverse onFindContainer(Container container, Stage stage) {
|
||||
if (BuildStatus.parse(container.getStatus()).isRunning()) {
|
||||
container.setStatus(buildStatus.name());
|
||||
update = true;
|
||||
if (container.getStartEpoch() == null) {
|
||||
container.setElementElapsed(0L);
|
||||
} else {
|
||||
container.setElementElapsed(System.currentTimeMillis() - container.getStartEpoch());
|
||||
}
|
||||
container.setName(ContainerUtils.getClearedQueueContainerName(container.getName()));
|
||||
}
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Traverse onFindStage(Stage stage, Model model) {
|
||||
if (allStageStatus.isEmpty()) {
|
||||
allStageStatus.addAll(fetchHistoryStageStatus(model, buildStatus,null, errorMsg,null));
|
||||
}
|
||||
if (BuildStatus.parse(stage.getStatus()).isRunning()) {
|
||||
stage.setStatus(buildStatus.name());
|
||||
update = true;
|
||||
if (stage.getStartEpoch() == null) {
|
||||
stage.setElapsed(0L);
|
||||
} else {
|
||||
stage.setElapsed(System.currentTimeMillis() - stage.getStartEpoch());
|
||||
}
|
||||
}
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Traverse onFindElement(int index, Element e, Container c) {
|
||||
if (e.getStatus() != null && !e.getStatus().isBlank() &&
|
||||
BuildStatus.valueOf(e.getStatus()).isRunning()) {
|
||||
e.setStatus(buildStatus.name());
|
||||
update = true;
|
||||
if (e.getStartEpoch() != null) {
|
||||
e.setElapsed(System.currentTimeMillis() - e.getStartEpoch());
|
||||
}
|
||||
|
||||
long elementElapsed = 0L;
|
||||
for (var element : c.getElements()) {
|
||||
elementElapsed += element.getElapsed() != null ? element.getElapsed() : 0;
|
||||
if (element == e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
c.setElementElapsed(elementElapsed);
|
||||
}
|
||||
return Traverse.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needUpdate() {
|
||||
return update;
|
||||
}
|
||||
},
|
||||
buildStatus,null,
|
||||
"buildEnd"
|
||||
);
|
||||
return new Pair<>(model, allStageStatus);
|
||||
}
|
||||
|
||||
public void updateBuildCancelUser(String projectId, String buildId, String cancelUserId) {
|
||||
buildDetailDao.updateBuildCancelUser(
|
||||
projectId,
|
||||
buildId,
|
||||
cancelUserId
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package cd.casic.ci.process.process.service.base;
|
||||
|
||||
import cd.casic.ci.common.pipeline.UUIDUtil;
|
||||
import cd.casic.ci.common.pipeline.constant.CommonMessageCode;
|
||||
import cd.casic.ci.process.api.process.pojo.PipelineStageTag;
|
||||
import cd.casic.ci.process.process.dal.pipeline.PipelineStageTagDao;
|
||||
import cd.casic.ci.process.process.dataObject.TPipelineStageTagRecord;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* StageTag为后台插入,更新由平台OP控制,基本不会更新,只需要缓存在内存即可。即使出错也不影响正常逻辑,暂不引入redis
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class StageTagServiceImpl {
|
||||
|
||||
private static final String ALL = "ALL";
|
||||
private static final String DEFAULT = "DEFAULT";
|
||||
@Resource
|
||||
private PipelineStageTagDao pipelineStageTagDao;
|
||||
// TODO 不引入缓存
|
||||
// StageTag为后台插入,更新由平台OP控制,不会经常更新,所以只需要缓存在内存即可。即使出错也不影响正常逻辑,暂不引入redis
|
||||
// private LoadingCache<String, PipelineStageTag> defaultTagCache = Caffeine.newBuilder()
|
||||
// .expireAfterWrite(Duration.ofMinutes(1))
|
||||
// .maximumSize(1)
|
||||
// .build(key -> pipelineStageTagDao.getDefaultStageTag());
|
||||
|
||||
// StageTag为后台插入,更新由平台OP控制,不会经常更新,所以只需要缓存在内存即可。即使出错也不影响正常逻辑,暂不引入redis
|
||||
private final LoadingCache<String, List<PipelineStageTag>> allTagCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(Duration.ofMinutes(1))
|
||||
.maximumSize(1)
|
||||
.build(key -> {
|
||||
List<PipelineStageTag> pipelineStageTagList = new ArrayList<>();
|
||||
List<TPipelineStageTagRecord> allStageTag = pipelineStageTagDao.getAllStageTag();
|
||||
for (int i = 0; i < allStageTag.size(); i++) {
|
||||
pipelineStageTagList.add(PipelineStageTagDao.convert(allStageTag.get(i), i == 0));
|
||||
}
|
||||
return pipelineStageTagList;
|
||||
});
|
||||
|
||||
@Autowired
|
||||
public StageTagServiceImpl( PipelineStageTagDao pipelineStageTagDao) {
|
||||
|
||||
this.pipelineStageTagDao = pipelineStageTagDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有阶段标签信息
|
||||
*/
|
||||
public List<PipelineStageTag> getAllStageTag() {
|
||||
return allTagCache.get(ALL);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取默认标签
|
||||
// */
|
||||
// public PipelineStageTag getDefaultStageTag() {
|
||||
// return defaultTagCache.get(DEFAULT);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 根据id获取阶段标签信息
|
||||
*/
|
||||
public PipelineStageTag getStageTag(String id) {
|
||||
List<PipelineStageTag> all = allTagCache.getIfPresent(ALL);
|
||||
PipelineStageTag data;
|
||||
if (all == null || all.isEmpty()) {
|
||||
TPipelineStageTagRecord pipelineStageTagRecord = pipelineStageTagDao.getStageTag(id);
|
||||
log.info("the pipelineStageTagRecord is :{}", pipelineStageTagRecord);
|
||||
data = pipelineStageTagRecord != null ?
|
||||
PipelineStageTagDao.convert(pipelineStageTagRecord, false) : null;
|
||||
} else {
|
||||
data = all.stream()
|
||||
.filter(tag -> tag.getId().equals(id))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存阶段标签信息
|
||||
*/
|
||||
public Boolean saveStageTag(String stageTag, int weight) {
|
||||
log.info("the save stageTagName is:{}", stageTag);
|
||||
// 判断阶段标签名称是否存在
|
||||
int count = getCountByNameOrWeight(stageTag, weight);
|
||||
if (count > 0) {
|
||||
// 抛出错误提示
|
||||
return false;
|
||||
}
|
||||
String id = UUIDUtil.generate();
|
||||
pipelineStageTagDao.add(id, stageTag, weight);
|
||||
// defaultTagCache.invalidateAll();
|
||||
allTagCache.invalidateAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新阶段标签信息
|
||||
*/
|
||||
public Boolean updateStageTag(String id, String stageTagName, int weight) {
|
||||
log.info("the update stageTagName is:{}", stageTagName);
|
||||
// 判断阶段标签代码是否存在
|
||||
if (getCountByNameOrWeight(stageTagName, weight) > 0) {
|
||||
// 判断更新的阶段标签代码是否属于自已
|
||||
TPipelineStageTagRecord pipelineStageTag = pipelineStageTagDao.getStageTag(id);
|
||||
if (pipelineStageTag != null && !stageTagName.equals(pipelineStageTag.getStageTagName())) {
|
||||
// 抛出错误提示
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pipelineStageTagDao.update(id, stageTagName, weight);
|
||||
// defaultTagCache.invalidateAll();
|
||||
// allTagCache.invalidateAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除阶段标签信息
|
||||
*/
|
||||
public Boolean deleteStageTag(String id) {
|
||||
log.info("the delete id is :{}", id);
|
||||
pipelineStageTagDao.delete( id);
|
||||
// defaultTagCache.invalidateAll();
|
||||
allTagCache.invalidateAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据阶段标签名称和权重查询重复数据库记录数
|
||||
*/
|
||||
private int getCountByNameOrWeight(String stageTagName, int weight) {
|
||||
Integer count = pipelineStageTagDao.countByNameOrWeight(stageTagName, weight);
|
||||
int result = 0;
|
||||
if (count != null) {
|
||||
result = count;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package cd.casic.ci.process.process.service.base.dispatcher;
|
||||
|
||||
|
||||
import cd.casic.ci.event.pojo.IEvent;
|
||||
|
||||
public interface EventDispatcher <T extends IEvent>{
|
||||
void dispatch(T events);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package cd.casic.ci.process.process.service.base.dispatcher;
|
||||
|
||||
import cd.casic.ci.event.pojo.pipeline.IPipelineEvent;
|
||||
|
||||
public interface PipelineEventDispatcher extends EventDispatcher<IPipelineEvent>{
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
package cd.casic.ci.process.process.service.base.engin.service;
|
||||
|
||||
import cd.casic.ci.common.pipeline.Model;
|
||||
import cd.casic.ci.common.pipeline.dialect.IPipelineDialect;
|
||||
import cd.casic.ci.common.pipeline.enums.BranchVersionAction;
|
||||
import cd.casic.ci.common.pipeline.enums.ChannelCode;
|
||||
import cd.casic.ci.common.pipeline.enums.VersionStatus;
|
||||
import cd.casic.ci.common.pipeline.pojo.setting.PipelineSetting;
|
||||
import cd.casic.ci.common.pipeline.pojo.transfer.YamlWithVersion;
|
||||
import cd.casic.ci.process.api.engine.pojo.PipelineInfo;
|
||||
import cd.casic.ci.process.api.engine.pojo.PipelineModelTask;
|
||||
import cd.casic.ci.process.api.process.pojo.PipelineCollation;
|
||||
import cd.casic.ci.process.api.process.pojo.PipelineName;
|
||||
import cd.casic.ci.process.api.process.pojo.PipelineSortType;
|
||||
import cd.casic.ci.process.api.process.pojo.pipeline.DeletePipelineResult;
|
||||
import cd.casic.ci.process.api.process.pojo.pipeline.DeployPipelineResult;
|
||||
import cd.casic.ci.process.api.process.pojo.pipeline.PipelineResourceVersion;
|
||||
import cd.casic.ci.process.api.process.pojo.pipeline.PipelineYamlVo;
|
||||
import cd.casic.ci.process.api.process.pojo.setting.PipelineModelVersion;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Repository
|
||||
public interface PipelineRepositoryService {
|
||||
|
||||
DeployPipelineResult deployPipeline(
|
||||
Model model,
|
||||
String projectId,
|
||||
String signPipelineId,
|
||||
String userId,
|
||||
ChannelCode channelCode,
|
||||
boolean create,
|
||||
YamlWithVersion yaml,
|
||||
Integer baseVersion,
|
||||
Boolean useSubscriptionSettings,
|
||||
Boolean useConcurrencyGroup,
|
||||
String templateId,
|
||||
Boolean updateLastModifyUser,
|
||||
PipelineSetting setting,
|
||||
VersionStatus versionStatus,
|
||||
String branchName,
|
||||
String description,
|
||||
PipelineYamlVo yamlInfo,
|
||||
Boolean pipelineDisable
|
||||
);
|
||||
|
||||
List<PipelineModelTask> initModel(
|
||||
Model model,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String userId,
|
||||
boolean create,
|
||||
VersionStatus versionStatus,
|
||||
ChannelCode channelCode,
|
||||
PipelineYamlVo yamlInfo,
|
||||
IPipelineDialect pipelineDialect
|
||||
);
|
||||
|
||||
PipelineSetting createDefaultSetting(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String pipelineName,
|
||||
ChannelCode channelCode
|
||||
);
|
||||
|
||||
PipelineInfo getPipelineInfo(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
ChannelCode channelCode,
|
||||
Boolean delete
|
||||
);
|
||||
|
||||
Map<String, Model> listModel(String projectId, Collection<String> pipelineIds);
|
||||
|
||||
Triple<PipelineInfo, PipelineResourceVersion, Boolean> getBuildTriggerInfo(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
Integer version
|
||||
);
|
||||
|
||||
PipelineResourceVersion getPipelineResourceVersion(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
Integer version,
|
||||
Boolean includeDraft
|
||||
);
|
||||
|
||||
PipelineResourceVersion getDraftVersionResource(
|
||||
String projectId,
|
||||
String pipelineId
|
||||
);
|
||||
|
||||
PipelineResourceVersion getBranchVersionResource(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String branchName
|
||||
);
|
||||
|
||||
int getActiveBranchVersionCount(
|
||||
String projectId,
|
||||
String pipelineId
|
||||
);
|
||||
|
||||
PipelineResourceVersion rollbackDraftFromVersion(
|
||||
String userId,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
PipelineResourceVersion targetVersion,
|
||||
Boolean ignoreBase
|
||||
);
|
||||
|
||||
DeletePipelineResult deletePipeline(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String userId,
|
||||
ChannelCode channelCode,
|
||||
boolean delete
|
||||
);
|
||||
|
||||
boolean isPipelineExist(
|
||||
String projectId,
|
||||
String pipelineName,
|
||||
ChannelCode channelCode,
|
||||
String excludePipelineId
|
||||
);
|
||||
|
||||
int countByProjectIds(Set<String> projectIds, ChannelCode channelCode);
|
||||
|
||||
Map<String, String> listPipelineNameByIds(
|
||||
String projectId,
|
||||
Set<String> pipelineIds,
|
||||
boolean filterDelete
|
||||
);
|
||||
|
||||
Map<String, String> listPipelineIdByName(
|
||||
String projectId,
|
||||
Set<String> pipelineNames,
|
||||
boolean filterDelete
|
||||
);
|
||||
|
||||
Integer getBuildNo(String projectId, String pipelineId);
|
||||
|
||||
PipelineSetting getSetting(String projectId, String pipelineId);
|
||||
|
||||
PipelineSetting getSettingByPipelineVersion(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
Integer pipelineVersion
|
||||
);
|
||||
|
||||
PipelineName saveSetting(
|
||||
String userId,
|
||||
PipelineSetting setting,
|
||||
int version,
|
||||
VersionStatus versionStatus,
|
||||
Boolean updateLastModifyUser,
|
||||
boolean isTemplate
|
||||
);
|
||||
|
||||
void batchUpdatePipelineModel(
|
||||
String userId,
|
||||
List<PipelineModelVersion> pipelineModelVersionList
|
||||
);
|
||||
|
||||
List<PipelineInfo> listDeletePipelineIdByProject(
|
||||
String projectId,
|
||||
Long days,
|
||||
Integer offset,
|
||||
Integer limit,
|
||||
PipelineSortType sortType,
|
||||
PipelineCollation collation,
|
||||
String filterByPipelineName
|
||||
);
|
||||
|
||||
PipelineResourceVersion restorePipeline(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String userId,
|
||||
ChannelCode channelCode,
|
||||
Long days
|
||||
);
|
||||
|
||||
int countByPipelineIds(
|
||||
String projectId,
|
||||
ChannelCode channelCode,
|
||||
List<String> pipelineIds
|
||||
);
|
||||
|
||||
void updateModelName(
|
||||
String pipelineId,
|
||||
String projectId,
|
||||
String modelName,
|
||||
String userId
|
||||
);
|
||||
|
||||
int updateMaxConRunningQueueSize(
|
||||
String userId,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
int maxConRunningQueueSize
|
||||
);
|
||||
|
||||
DeployPipelineResult updateSettingVersion(
|
||||
String userId,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
PipelineSetting savedSetting,
|
||||
Boolean updateLastModifyUser
|
||||
);
|
||||
|
||||
void updatePipelineBranchVersion(
|
||||
String userId,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String branchName,
|
||||
BranchVersionAction branchVersionAction
|
||||
);
|
||||
|
||||
boolean updateLocked(
|
||||
String userId,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
boolean locked
|
||||
);
|
||||
|
||||
String getPipelineOauthUser(String projectId, String pipelineId);
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package cd.casic.ci.process.process.service.base.engin.service;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.model.SQLPage;
|
||||
import cd.casic.ci.common.pipeline.pojo.event.CallBackNetWorkRegionType;
|
||||
import cd.casic.ci.common.pipeline.pojo.event.PipelineCallbackEvent;
|
||||
import cd.casic.ci.common.pipeline.pojo.event.ProjectPipelineCallBack;
|
||||
import cd.casic.ci.common.pipeline.pojo.secret.ISecretParam;
|
||||
import cd.casic.ci.process.api.process.pojo.CreateCallBackResult;
|
||||
import cd.casic.ci.process.api.process.pojo.ProjectPipelineCallBackHistory;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ProjectPipelineCallBackService {
|
||||
|
||||
CreateCallBackResult createCallBack(
|
||||
String userId,
|
||||
String projectId,
|
||||
String url,
|
||||
CallBackNetWorkRegionType region,
|
||||
String event,
|
||||
String secretToken,
|
||||
ISecretParam secretParam,
|
||||
boolean needCheckPermission
|
||||
);
|
||||
|
||||
List<ProjectPipelineCallBack> listProjectCallBack(
|
||||
String projectId,
|
||||
String events
|
||||
);
|
||||
|
||||
SQLPage<ProjectPipelineCallBack> listByPage(
|
||||
String userId,
|
||||
String projectId,
|
||||
int offset,
|
||||
int limit
|
||||
);
|
||||
|
||||
void delete(
|
||||
String userId,
|
||||
String projectId,
|
||||
long id,
|
||||
boolean needCheckPermission
|
||||
);
|
||||
|
||||
void disable(
|
||||
String projectId,
|
||||
long id
|
||||
);
|
||||
|
||||
void batchDisable(
|
||||
String projectId,
|
||||
String callbackIds
|
||||
);
|
||||
|
||||
void sendDisableNotifyMessage(
|
||||
String projectId,
|
||||
long id
|
||||
);
|
||||
|
||||
void enable(
|
||||
ProjectPipelineCallBack callBack
|
||||
);
|
||||
|
||||
void enableByIds(
|
||||
String projectId,
|
||||
String callbackIds
|
||||
);
|
||||
|
||||
void updateFailureTime(
|
||||
String projectId,
|
||||
long id,
|
||||
LocalDateTime failureTime
|
||||
);
|
||||
|
||||
List<ProjectPipelineCallBack> getDisableCallbackList(
|
||||
int offset,
|
||||
int limit,
|
||||
String projectId,
|
||||
String url
|
||||
);
|
||||
|
||||
void createHistory(
|
||||
ProjectPipelineCallBackHistory projectPipelineCallBackHistory
|
||||
);
|
||||
|
||||
ProjectPipelineCallBackHistory getHistory(
|
||||
String userId,
|
||||
String projectId,
|
||||
long id
|
||||
);
|
||||
|
||||
SQLPage<ProjectPipelineCallBackHistory> listHistory(
|
||||
String userId,
|
||||
String projectId,
|
||||
String callBackUrl,
|
||||
String events,
|
||||
Long startTime,
|
||||
Long endTime,
|
||||
int offset,
|
||||
int limit
|
||||
);
|
||||
|
||||
void retry(
|
||||
String userId,
|
||||
String projectId,
|
||||
long id
|
||||
);
|
||||
|
||||
void bindPipelineCallBack(
|
||||
String userId,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
PipelineCallbackEvent callbackInfo
|
||||
);
|
||||
|
||||
List<ProjectPipelineCallBack> getPipelineCallback(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String event
|
||||
);
|
||||
|
||||
void checkParam(
|
||||
String userId,
|
||||
String projectId
|
||||
);
|
||||
|
||||
void validAuth(
|
||||
String userId,
|
||||
String projectId
|
||||
);
|
||||
|
||||
void validProjectManager(
|
||||
String userId,
|
||||
String projectId
|
||||
);
|
||||
|
||||
String projectPipelineListUrl(String projectId);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cd.casic.ci.process.process.service.base.engin.service;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.pojo.event.CallBackNetWorkRegionType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ProjectPipelineCallBackUrlGenerator {
|
||||
|
||||
String generateCallBackUrl(
|
||||
@Nullable CallBackNetWorkRegionType region,
|
||||
String url
|
||||
);
|
||||
|
||||
String encodeCallbackUrl(String url);
|
||||
|
||||
String decodeCallbackUrl(String url);
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package cd.casic.ci.process.process.service.base.engin.util;
|
||||
|
||||
import cd.casic.ci.common.pipeline.container.Container;
|
||||
import cd.casic.ci.common.pipeline.container.NormalContainer;
|
||||
import cd.casic.ci.common.pipeline.container.VMBuildContainer;
|
||||
import cd.casic.ci.common.pipeline.enums.BuildStatus;
|
||||
import cd.casic.ci.process.api.process.constant.ProcessMessageCode;
|
||||
|
||||
public class ContainerUtils {
|
||||
|
||||
private ContainerUtils() {
|
||||
// 私有构造函数,防止实例化
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取容器启动键
|
||||
* @param pipelineId 流水线ID
|
||||
* @param buildId 构建ID
|
||||
* @param containerId 容器ID
|
||||
* @return 容器启动键
|
||||
*/
|
||||
public static String getContainerStartupKey(String pipelineId, String buildId, String containerId) {
|
||||
return String.format("container:startup:%s:%s:%s", pipelineId, buildId, containerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取容器运行事件取消任务键
|
||||
* @param pipelineId 流水线ID
|
||||
* @param buildId 构建ID
|
||||
* @param containerId 容器ID
|
||||
* @return 容器运行事件取消任务键
|
||||
*/
|
||||
public static String getContainerRunEvenCancelTaskKey(String pipelineId, String buildId, String containerId) {
|
||||
return String.format("container:taskEvenCancel:%s:%s:%s", pipelineId, buildId, containerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断普通容器是否启用
|
||||
* @param normalContainer 普通容器
|
||||
* @return 是否启用
|
||||
*/
|
||||
public static boolean isNormalContainerEnable(NormalContainer normalContainer) {
|
||||
if (normalContainer.getJobControlOption() != null) {
|
||||
return normalContainer.getJobControlOption().getEnable();
|
||||
}
|
||||
return !normalContainer.getEnableSkip();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断VM构建容器是否启用
|
||||
* @param container VM构建容器
|
||||
* @return 是否启用
|
||||
*/
|
||||
public static boolean isVMBuildContainerEnable(VMBuildContainer container) {
|
||||
return container.getJobControlOption() == null || container.getJobControlOption().getEnable();
|
||||
}
|
||||
|
||||
private static String getMutexPrefix() {
|
||||
return ProcessMessageCode.BK_MUTEX_WAITING;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取互斥固定容器名称
|
||||
* @param containerName 容器名称
|
||||
* @return 处理后的容器名称
|
||||
*/
|
||||
public static String getMutexFixedContainerName(String containerName) {
|
||||
String prefix = getMutexPrefix();
|
||||
if (containerName.startsWith(prefix)) {
|
||||
return containerName.substring(prefix.length());
|
||||
}
|
||||
return containerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取互斥等待名称
|
||||
* @param containerName 容器名称
|
||||
* @return 处理后的容器名称
|
||||
*/
|
||||
public static String getMutexWaitName(String containerName) {
|
||||
String prefix = getMutexPrefix();
|
||||
if (containerName.startsWith(prefix)) {
|
||||
return containerName;
|
||||
}
|
||||
return prefix + containerName;
|
||||
}
|
||||
|
||||
private static String getQueuePrefix() {
|
||||
return ProcessMessageCode.BK_QUEUING;
|
||||
}
|
||||
|
||||
private static String getReviewPrefix() {
|
||||
return ProcessMessageCode.BK_PENDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取清除队列容器名称
|
||||
* @param containerName 容器名称
|
||||
* @return 处理后的容器名称
|
||||
*/
|
||||
public static String getClearedQueueContainerName(String containerName) {
|
||||
String queuePrefix = getQueuePrefix();
|
||||
String reviewPrefix = getReviewPrefix();
|
||||
|
||||
if (containerName.startsWith(queuePrefix)) {
|
||||
return containerName.substring(queuePrefix.length());
|
||||
} else if (containerName.startsWith(reviewPrefix)) {
|
||||
return containerName.substring(reviewPrefix.length());
|
||||
}
|
||||
return containerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排队等待名称
|
||||
* @param containerName 容器名称
|
||||
* @param startBuildStatus 开始构建状态
|
||||
* @return 处理后的容器名称
|
||||
*/
|
||||
public static String getQueuingWaitName(String containerName, BuildStatus startBuildStatus) {
|
||||
String queuePrefix = getQueuePrefix();
|
||||
String reviewPrefix = getReviewPrefix();
|
||||
|
||||
if (containerName.startsWith(queuePrefix) || containerName.startsWith(reviewPrefix)) {
|
||||
return containerName;
|
||||
}
|
||||
|
||||
if (startBuildStatus == BuildStatus.TRIGGER_REVIEWING) {
|
||||
return reviewPrefix + containerName;
|
||||
}
|
||||
return queuePrefix + containerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为原始矩阵容器
|
||||
* @param container 容器
|
||||
* @return 是否为原始矩阵容器
|
||||
*/
|
||||
public static boolean isOriginMatrixContainer(Container container) {
|
||||
return container.fetchGroupContainers() != null;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BuildEvent {
|
||||
private final String buildId;
|
||||
private final String pipelineId;
|
||||
private final String pipelineName;
|
||||
private final String userId;
|
||||
private final String triggerUser;
|
||||
private final String cancelUserId;
|
||||
private final String status;
|
||||
private final long startTime;
|
||||
private final long endTime;
|
||||
private final SimpleModel model;
|
||||
private final String projectId;
|
||||
private final String trigger;
|
||||
private final String stageId;
|
||||
private final String taskId;
|
||||
private final int buildNo;
|
||||
private final Boolean debug;
|
||||
|
||||
// 构造函数,使用了默认值的设置
|
||||
public BuildEvent(String buildId, String pipelineId, String pipelineName, String userId, String triggerUser, String cancelUserId, String status, long startTime, long endTime, SimpleModel model, String projectId, String trigger, String stageId, String taskId, int buildNo, Boolean debug) {
|
||||
this.buildId = buildId;
|
||||
this.pipelineId = pipelineId;
|
||||
this.pipelineName = pipelineName;
|
||||
this.userId = userId;
|
||||
this.triggerUser = triggerUser;
|
||||
this.cancelUserId = cancelUserId;
|
||||
this.status = status;
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
this.model = model;
|
||||
this.projectId = projectId;
|
||||
this.trigger = trigger;
|
||||
this.stageId = stageId;
|
||||
this.taskId = taskId;
|
||||
this.buildNo = buildNo;
|
||||
this.debug = debug;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
import cd.casic.ci.common.pipeline.enums.CallBackEvent;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CallBackData<T> {
|
||||
private final CallBackEvent event;
|
||||
private final T data;
|
||||
|
||||
// 构造函数
|
||||
public CallBackData(CallBackEvent event, T data) {
|
||||
this.event = event;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.enums.CallBackEvent;
|
||||
import cd.casic.ci.event.enums.ActionType;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 事件工具类
|
||||
*/
|
||||
public class EventUtils {
|
||||
|
||||
private static final Map<String, CallBackEvent> callBackEventMap = Stream.of(CallBackEvent.values())
|
||||
.collect(Collectors.toMap(Enum::name, event -> event));
|
||||
|
||||
private EventUtils() {
|
||||
// 私有构造函数,防止实例化
|
||||
}
|
||||
|
||||
/**
|
||||
* 将PipelineBuildStatusBroadCastEvent转换为CallBackEvent
|
||||
* @param event 构建状态广播事件
|
||||
* @return 回调事件类型
|
||||
*/
|
||||
public static CallBackEvent toEventType(PipelineBuildStatusBroadCastEvent event) {
|
||||
if (event.getType() != null && callBackEventMap.containsKey(event.getType().name())) {
|
||||
return callBackEventMap.get(event.getType().name());
|
||||
}
|
||||
|
||||
if (event.getTaskId() != null && !event.getTaskId().isBlank()) {
|
||||
if (event.getActionType() == ActionType.START) {
|
||||
return CallBackEvent.BUILD_TASK_START;
|
||||
}
|
||||
if (event.getActionType() == ActionType.REFRESH) {
|
||||
return CallBackEvent.BUILD_TASK_PAUSE;
|
||||
}
|
||||
if (event.getActionType() == ActionType.END) {
|
||||
return CallBackEvent.BUILD_TASK_END;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getContainerHashId() != null && !event.getContainerHashId().isBlank()) {
|
||||
if (event.getActionType() == ActionType.START) {
|
||||
return CallBackEvent.BUILD_JOB_START;
|
||||
}
|
||||
if (event.getActionType() == ActionType.END) {
|
||||
return CallBackEvent.BUILD_JOB_END;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getStageId() != null && !event.getStageId().isBlank()) {
|
||||
if (event.getActionType() == ActionType.START) {
|
||||
return CallBackEvent.BUILD_STAGE_START;
|
||||
}
|
||||
if (event.getActionType() == ActionType.END) {
|
||||
return CallBackEvent.BUILD_STAGE_END;
|
||||
}
|
||||
}
|
||||
|
||||
if ((event.getTaskId() == null || event.getTaskId().isBlank()) &&
|
||||
(event.getContainerHashId() == null || event.getContainerHashId().isBlank()) &&
|
||||
(event.getStageId() == null || event.getStageId().isBlank())) {
|
||||
if (event.getActionType() == ActionType.START) {
|
||||
return CallBackEvent.BUILD_START;
|
||||
}
|
||||
if (event.getActionType() == ActionType.END) {
|
||||
return CallBackEvent.BUILD_END;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
|
||||
import cd.casic.ci.event.enums.ActionType;
|
||||
import cd.casic.ci.event.enums.PipelineBuildStatusBroadCastEventType;
|
||||
|
||||
import cd.casic.ci.event.pojo.pipeline.IPipelineEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 构建状态的广播事件,用于通知等
|
||||
*/
|
||||
//@Event(destination = StreamBinding.PIPELINE_BUILD_CALL_BACK_FANOUT)
|
||||
public class PipelineBuildStatusBroadCastEvent extends IPipelineEvent {
|
||||
private final String buildId;
|
||||
@Nullable
|
||||
private final String stageId;
|
||||
@Nullable
|
||||
private final String containerHashId;
|
||||
@Nullable
|
||||
private final String jobId;
|
||||
@Nullable
|
||||
private final String taskId;
|
||||
@Nullable
|
||||
private final String stepId;
|
||||
@Nullable
|
||||
private final Integer executeCount;
|
||||
@Nullable
|
||||
private final String buildStatus;
|
||||
@Nullable
|
||||
private final String atomCode;
|
||||
@Nullable
|
||||
private final LocalDateTime eventTime;
|
||||
@Nullable
|
||||
private final PipelineBuildStatusBroadCastEventType type;
|
||||
@Nullable
|
||||
private final Map<String, String> labels;
|
||||
|
||||
public PipelineBuildStatusBroadCastEvent(
|
||||
String source,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String userId,
|
||||
String buildId,
|
||||
@Nullable String stageId,
|
||||
@Nullable String containerHashId,
|
||||
@Nullable String jobId,
|
||||
@Nullable String taskId,
|
||||
@Nullable String stepId,
|
||||
@Nullable Integer executeCount,
|
||||
@Nullable String buildStatus,
|
||||
@Nullable String atomCode,
|
||||
@Nullable LocalDateTime eventTime,
|
||||
@Nullable PipelineBuildStatusBroadCastEventType type,
|
||||
@Nullable Map<String, String> labels,
|
||||
ActionType actionType,
|
||||
int delayMills
|
||||
) {
|
||||
super(actionType, source, projectId, pipelineId, userId, delayMills);
|
||||
this.buildId = buildId;
|
||||
this.stageId = stageId;
|
||||
this.containerHashId = containerHashId;
|
||||
this.jobId = jobId;
|
||||
this.taskId = taskId;
|
||||
this.stepId = stepId;
|
||||
this.executeCount = executeCount;
|
||||
this.buildStatus = buildStatus;
|
||||
this.atomCode = atomCode;
|
||||
this.eventTime = eventTime;
|
||||
this.type = type;
|
||||
this.labels = labels;
|
||||
}
|
||||
|
||||
public PipelineBuildStatusBroadCastEvent(
|
||||
String source,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String userId,
|
||||
String buildId,
|
||||
@Nullable Integer executeCount,
|
||||
@Nullable String buildStatus,
|
||||
ActionType actionType
|
||||
) {
|
||||
this(
|
||||
source,
|
||||
projectId,
|
||||
pipelineId,
|
||||
userId,
|
||||
buildId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
executeCount,
|
||||
buildStatus,
|
||||
null,
|
||||
LocalDateTime.now(),
|
||||
null,
|
||||
null,
|
||||
actionType,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
public String getBuildId() {
|
||||
return buildId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getStageId() {
|
||||
return stageId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getContainerHashId() {
|
||||
return containerHashId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getStepId() {
|
||||
return stepId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getExecuteCount() {
|
||||
return executeCount;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getBuildStatus() {
|
||||
return buildStatus;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAtomCode() {
|
||||
return atomCode;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LocalDateTime getEventTime() {
|
||||
return eventTime;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PipelineBuildStatusBroadCastEventType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, String> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
PipelineBuildStatusBroadCastEvent that = (PipelineBuildStatusBroadCastEvent) o;
|
||||
return Objects.equals(buildId, that.buildId) &&
|
||||
Objects.equals(stageId, that.stageId) &&
|
||||
Objects.equals(containerHashId, that.containerHashId) &&
|
||||
Objects.equals(jobId, that.jobId) &&
|
||||
Objects.equals(taskId, that.taskId) &&
|
||||
Objects.equals(stepId, that.stepId) &&
|
||||
Objects.equals(executeCount, that.executeCount) &&
|
||||
Objects.equals(buildStatus, that.buildStatus) &&
|
||||
Objects.equals(atomCode, that.atomCode) &&
|
||||
Objects.equals(eventTime, that.eventTime) &&
|
||||
type == that.type &&
|
||||
Objects.equals(labels, that.labels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), buildId, stageId, containerHashId, jobId, taskId, stepId,
|
||||
executeCount, buildStatus, atomCode, eventTime, type, labels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PipelineBuildStatusBroadCastEvent{" +
|
||||
"buildId='" + buildId + '\'' +
|
||||
", stageId='" + stageId + '\'' +
|
||||
", containerHashId='" + containerHashId + '\'' +
|
||||
", jobId='" + jobId + '\'' +
|
||||
", taskId='" + taskId + '\'' +
|
||||
", stepId='" + stepId + '\'' +
|
||||
", executeCount=" + executeCount +
|
||||
", buildStatus='" + buildStatus + '\'' +
|
||||
", atomCode='" + atomCode + '\'' +
|
||||
", eventTime=" + eventTime +
|
||||
", type=" + type +
|
||||
", labels=" + labels +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import cd.casic.ci.event.enums.ActionType;
|
||||
import cd.casic.ci.event.pojo.pipeline.IPipelineEvent;
|
||||
|
||||
//@Event(StreamBinding.PIPELINE_BUILD_WEBSOCKET)
|
||||
public class PipelineBuildWebSocketPushEvent extends IPipelineEvent {
|
||||
|
||||
private final String buildId;
|
||||
private final long refreshTypes; // HISTORY or DETAIL or STATUS 位运算
|
||||
private final Integer executeCount;
|
||||
|
||||
public PipelineBuildWebSocketPushEvent(
|
||||
String source,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String userId,
|
||||
String buildId,
|
||||
long refreshTypes,
|
||||
Integer executeCount,
|
||||
ActionType actionType,
|
||||
int delayMills
|
||||
) {
|
||||
super(actionType, source, projectId, pipelineId, userId, delayMills);
|
||||
this.buildId = buildId;
|
||||
this.refreshTypes = refreshTypes;
|
||||
this.executeCount = executeCount;
|
||||
}
|
||||
|
||||
public PipelineBuildWebSocketPushEvent(
|
||||
String source,
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String userId,
|
||||
String buildId,
|
||||
long refreshTypes
|
||||
) {
|
||||
this(source, projectId, pipelineId, userId, buildId, refreshTypes, null, ActionType.REFRESH, 0);
|
||||
}
|
||||
|
||||
public PipelineBuildWebSocketPushEvent( String source, String projectId, String pipelineId, String userId, String buildId, long refreshTypes, Integer executeCount) {
|
||||
super(ActionType.REFRESH, source, projectId, pipelineId, userId,0);
|
||||
this.buildId = buildId;
|
||||
this.refreshTypes = refreshTypes;
|
||||
this.executeCount = executeCount;
|
||||
}
|
||||
|
||||
public String getBuildId() {
|
||||
return buildId;
|
||||
}
|
||||
|
||||
public long getRefreshTypes() {
|
||||
return refreshTypes;
|
||||
}
|
||||
|
||||
public Integer getExecuteCount() {
|
||||
return executeCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
PipelineBuildWebSocketPushEvent that = (PipelineBuildWebSocketPushEvent) o;
|
||||
|
||||
if (refreshTypes != that.refreshTypes) return false;
|
||||
if (!buildId.equals(that.buildId)) return false;
|
||||
return executeCount != null ? executeCount.equals(that.executeCount) : that.executeCount == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + buildId.hashCode();
|
||||
result = 31 * result + (int) (refreshTypes ^ (refreshTypes >>> 32));
|
||||
result = 31 * result + (executeCount != null ? executeCount.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PipelineBuildWebSocketPushEvent{" +
|
||||
"source='" + getSource() + '\'' +
|
||||
", projectId='" + getProjectId() + '\'' +
|
||||
", pipelineId='" + getPipelineId() + '\'' +
|
||||
", userId='" + getUserId() + '\'' +
|
||||
", buildId='" + buildId + '\'' +
|
||||
", refreshTypes=" + refreshTypes +
|
||||
", executeCount=" + executeCount +
|
||||
", actionType=" + getActionType() +
|
||||
", delayMills=" + getDelayMills() +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class PipelineEvent {
|
||||
private final String pipelineId;
|
||||
private final String pipelineName;
|
||||
private final String userId;
|
||||
private final long updateTime;
|
||||
private final String projectId;
|
||||
|
||||
public PipelineEvent(
|
||||
String pipelineId,
|
||||
String pipelineName,
|
||||
String userId,
|
||||
long updateTime,
|
||||
String projectId
|
||||
) {
|
||||
this.pipelineId = pipelineId;
|
||||
this.pipelineName = pipelineName;
|
||||
this.userId = userId;
|
||||
this.updateTime = updateTime;
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
public String getPipelineId() {
|
||||
return pipelineId;
|
||||
}
|
||||
|
||||
public String getPipelineName() {
|
||||
return pipelineName;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public long getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public String getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PipelineEvent that = (PipelineEvent) o;
|
||||
return updateTime == that.updateTime &&
|
||||
Objects.equals(pipelineId, that.pipelineId) &&
|
||||
Objects.equals(pipelineName, that.pipelineName) &&
|
||||
Objects.equals(userId, that.userId) &&
|
||||
Objects.equals(projectId, that.projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(pipelineId, pipelineName, userId, updateTime, projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PipelineEvent{" +
|
||||
"pipelineId='" + pipelineId + '\'' +
|
||||
", pipelineName='" + pipelineName + '\'' +
|
||||
", userId='" + userId + '\'' +
|
||||
", updateTime=" + updateTime +
|
||||
", projectId='" + projectId + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ProjectCallbackEvent {
|
||||
private final String projectId;
|
||||
private final String projectName;
|
||||
private final boolean enable;
|
||||
private final String userId;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SimpleJob {
|
||||
private final String jobName;
|
||||
private final String status;
|
||||
private final long startTime;
|
||||
private final long endTime;
|
||||
private final List<SimpleTask> tasks;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SimpleModel {
|
||||
private final List<SimpleStage> stages;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SimpleStage {
|
||||
private final String stageName;
|
||||
private final String name;
|
||||
private String status;
|
||||
private long startTime;
|
||||
private long endTime;
|
||||
private final List<SimpleJob> jobs;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SimpleTask {
|
||||
private final String taskId;
|
||||
private final String taskName;
|
||||
private final String atomCode;
|
||||
private final String status;
|
||||
private final long startTime;
|
||||
private final long endTime;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class StreamEnabledEvent {
|
||||
private final String userId;
|
||||
private final long gitProjectId;
|
||||
private final String gitProjectUrl;
|
||||
private final boolean enable;
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo;
|
||||
|
||||
|
||||
import cd.casic.ci.common.pipeline.container.Container;
|
||||
import cd.casic.ci.common.pipeline.pojo.element.ElementAdditionalOptions;
|
||||
import cd.casic.ci.common.pipeline.pojo.element.ElementPostInfo;
|
||||
import cd.casic.ci.process.api.engine.pojo.PipelineBuildTask;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 生成运行环境操作的插件任务
|
||||
*/
|
||||
@Repository
|
||||
public interface VmOperateTaskGenerator {
|
||||
|
||||
String START_VM_TASK_ATOM = "dispatchVMStartupTaskAtom";
|
||||
String SHUTDOWN_VM_TASK_ATOM = "dispatchVMShutdownTaskAtom";
|
||||
String START_NORMAL_TASK_ATOM = "dispatchBuildLessDockerStartupTaskAtom";
|
||||
String SHUTDOWN_NORMAL_TASK_ATOM = "dispatchBuildLessDockerShutdownTaskAtom";
|
||||
|
||||
static boolean isVmAtom(PipelineBuildTask task) {
|
||||
return isStartVM(task) || isStopVM(task);
|
||||
}
|
||||
|
||||
static boolean isVmAtom(String atomCode) {
|
||||
return isStartVM(atomCode) || isStopVM(atomCode);
|
||||
}
|
||||
|
||||
static boolean isStartVM(PipelineBuildTask task) {
|
||||
return START_VM_TASK_ATOM.equals(task.getTaskAtom()) ||
|
||||
START_NORMAL_TASK_ATOM.equals(task.getTaskAtom());
|
||||
}
|
||||
|
||||
static boolean isStopVM(PipelineBuildTask task) {
|
||||
return SHUTDOWN_VM_TASK_ATOM.equals(task.getTaskAtom()) ||
|
||||
SHUTDOWN_NORMAL_TASK_ATOM.equals(task.getTaskAtom());
|
||||
}
|
||||
|
||||
static boolean isStartVM(String atomCode) {
|
||||
return atomCode.startsWith(START_VM_TASK_ATOM) ||
|
||||
atomCode.startsWith(START_NORMAL_TASK_ATOM);
|
||||
}
|
||||
|
||||
static boolean isStopVM(String atomCode) {
|
||||
return atomCode.startsWith(SHUTDOWN_VM_TASK_ATOM) ||
|
||||
atomCode.startsWith(SHUTDOWN_NORMAL_TASK_ATOM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成编译环境的开机插件任务
|
||||
*/
|
||||
PipelineBuildTask makeStartVMContainerTask(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String buildId,
|
||||
String stageId,
|
||||
Container container,
|
||||
int taskSeq,
|
||||
String userId,
|
||||
int executeCount
|
||||
);
|
||||
|
||||
/**
|
||||
* 生成准备停机插件任务列表
|
||||
*/
|
||||
List<PipelineBuildTask> makeShutdownVMContainerTasks(
|
||||
String projectId,
|
||||
String pipelineId,
|
||||
String buildId,
|
||||
String stageId,
|
||||
Container container,
|
||||
int containerSeq,
|
||||
int taskSeq,
|
||||
String userId,
|
||||
int executeCount
|
||||
);
|
||||
|
||||
default ElementAdditionalOptions opts(Container container, String taskName, int taskSeq) {
|
||||
return new ElementAdditionalOptions(
|
||||
true, // continueWhenFailed
|
||||
1L, // timeout: 1分钟超时
|
||||
ElementAdditionalOptions.RunCondition.PARENT_TASK_FINISH,
|
||||
new ElementPostInfo(
|
||||
container.getId(),
|
||||
"",
|
||||
"",
|
||||
taskName,
|
||||
taskSeq
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo.constant;
|
||||
|
||||
public class CallbackConstants {
|
||||
// 项目级回调标志位
|
||||
public static final String DEVOPS_ALL_PROJECT = "DEVOPS_ALL_PROJECT";
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package cd.casic.ci.process.process.service.base.pojo.enums;
|
||||
|
||||
|
||||
/**
|
||||
* 2进制表示刷新控制位
|
||||
*/
|
||||
public enum RefreshType {
|
||||
HISTORY(2),
|
||||
DETAIL(4),
|
||||
STATUS(8),
|
||||
RECORD(16);
|
||||
|
||||
private final long binary;
|
||||
|
||||
RefreshType(long binary) {
|
||||
this.binary = binary;
|
||||
}
|
||||
|
||||
public long getBinary() {
|
||||
return binary;
|
||||
}
|
||||
}
|
@ -34,5 +34,9 @@
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>spring-boot-starter-monitor</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cd.casic.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mq</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,95 @@
|
||||
package cd.casic.ci.project.pojo;
|
||||
|
||||
import cd.casic.ci.project.dal.pojo.ProjectProperties;
|
||||
import cd.casic.ci.project.dal.pojo.SubjectScopeInfo;
|
||||
import cd.casic.ci.project.enums.ProjectAuthSecrecyStatus;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(title = "项目-修改模型")
|
||||
public class ProjectUpdateInfo {
|
||||
@Schema(title = "项目名称")
|
||||
private String projectName;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "项目类型")
|
||||
private Integer projectType = 0;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "事业群ID")
|
||||
private Long bgId = 0L;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "事业群名字")
|
||||
private String bgName = "";
|
||||
|
||||
@Schema(title = "业务线ID")
|
||||
private Long businessLineId;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "业务线名称")
|
||||
private String businessLineName = "";
|
||||
|
||||
@Schema(title = "中心ID")
|
||||
private Long centerId;
|
||||
|
||||
@Schema(title = "中心名称")
|
||||
private String centerName;
|
||||
|
||||
@Schema(title = "部门ID")
|
||||
private Long deptId;
|
||||
|
||||
@Schema(title = "部门名称")
|
||||
private String deptName;
|
||||
|
||||
@Schema(title = "描述")
|
||||
private String description;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "英文缩写")
|
||||
private String englishName = "";
|
||||
|
||||
@Schema(title = "cc app id")
|
||||
private Long ccAppId;
|
||||
|
||||
@Schema(title = "cc app name")
|
||||
private String ccAppName;
|
||||
|
||||
@Schema(title = "容器选择,0 是不选,1 是k8s, 2 是mesos")
|
||||
private Integer kind;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "是否保密")
|
||||
private Boolean secrecy = false;
|
||||
|
||||
@Schema(title = "项目相关配置")
|
||||
private ProjectProperties properties;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "项目最大可授权人员范围")
|
||||
private List<SubjectScopeInfo> subjectScopes = Collections.emptyList();
|
||||
|
||||
@Schema(title = "logo地址")
|
||||
private String logoAddress;
|
||||
|
||||
@Builder.Default
|
||||
@Schema(title = "项目性质")
|
||||
private Integer authSecrecy = ProjectAuthSecrecyStatus.PUBLIC.getValue();
|
||||
|
||||
@Schema(title = "运营产品ID")
|
||||
private Integer productId;
|
||||
|
||||
@Schema(title = "运营产品名称")
|
||||
private String productName;
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.ci.project.pojo.mq;
|
||||
|
||||
|
||||
import cd.casic.framework.mq.redis.core.stream.AbstractRedisStreamMessage;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class ProjectBroadCastEvent extends AbstractRedisStreamMessage {
|
||||
private String userId;
|
||||
private String projectId;
|
||||
private Integer retryCount;
|
||||
private Integer delayMills;
|
||||
private Integer retryTime;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cd.casic.ci.project.pojo.mq;
|
||||
|
||||
import cd.casic.ci.project.dal.pojo.ProjectCreateInfo;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class ProjectCreateBroadCastEvent extends ProjectBroadCastEvent{
|
||||
private ProjectCreateInfo projectInfo;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package cd.casic.ci.project.pojo.mq;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class ProjectEnableStatusBroadCastEvent extends ProjectBroadCastEvent{
|
||||
private Boolean enable;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cd.casic.ci.project.pojo.mq;
|
||||
|
||||
import cd.casic.ci.project.pojo.ProjectUpdateInfo;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class ProjectUpdateBroadCastEvent extends ProjectBroadCastEvent{
|
||||
private ProjectUpdateInfo projectInfo;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package cd.casic.ci.project.service;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ServiceAllocIdResource {
|
||||
|
||||
// @GET
|
||||
// @Path("/types/segment/tags/{bizTag}/generate")
|
||||
@Operation(summary = "按号段模式生成Id")
|
||||
Long generateSegmentId(String bizTag);
|
||||
|
||||
@Operation(summary = "按号段模式批量生成Id(本质是for循环实现,减少远程调用)")
|
||||
public List<Long> batchGenerateSegmentId(String bizTag,Integer number);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user