diff --git a/.idea/CopilotChatHistory.xml b/.idea/CopilotChatHistory.xml
index 6fcb2dba..c8155438 100644
--- a/.idea/CopilotChatHistory.xml
+++ b/.idea/CopilotChatHistory.xml
@@ -56,9 +56,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 067867a4..273bdc77 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -14,8 +14,8 @@
-
+
diff --git a/framework/commons/src/main/java/cd/casic/framework/commons/util/json/JsonUtils.java b/framework/commons/src/main/java/cd/casic/framework/commons/util/json/JsonUtils.java
index 4e98c817..26e01e4b 100644
--- a/framework/commons/src/main/java/cd/casic/framework/commons/util/json/JsonUtils.java
+++ b/framework/commons/src/main/java/cd/casic/framework/commons/util/json/JsonUtils.java
@@ -19,12 +19,12 @@ import java.util.ArrayList;
import java.util.List;
/**
- * JSON 工具类
+ * JSON 工具类 ,经量用hutool的
*
* @author mianbin
*/
@Slf4j
-public class JsonUtils {
+public class JsonUtils extends JSONUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
@@ -104,7 +104,7 @@ public class JsonUtils {
* 使用 {@link #parseObject(String, Class)} 时,在@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 的场景下,
* 如果 text 没有 class 属性,则会报错。此时,使用这个方法,可以解决。
*
- * @param text 字符串
+ * @param text 字符串
* @param clazz 类型
* @return 对象
*/
@@ -139,7 +139,7 @@ public class JsonUtils {
/**
* 解析 JSON 字符串成指定类型的对象,如果解析失败,则返回 null
*
- * @param text 字符串
+ * @param text 字符串
* @param typeReference 类型引用
* @return 指定类型的对象
*/
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/IModelTemplate.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/IModelTemplate.java
index 6ce042b7..0a9b66f5 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/IModelTemplate.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/IModelTemplate.java
@@ -25,7 +25,14 @@ public interface IModelTemplate {
@Schema(title = "变量", required = true)
Map getVariables();
+
+ /**
+ * 判读是否来自于模板
+ *
+ * @return true 是来自于模板|false 不是来自于模板
+ */
default boolean fromTemplate() {
- return getTemplate() != null && !getTemplate().isEmpty();
+ String template = getTemplate();
+ return template != null && !template.isEmpty();
}
}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/AgentReuseMutex.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/AgentReuseMutex.java
index dae7976d..197f4436 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/AgentReuseMutex.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/AgentReuseMutex.java
@@ -1,5 +1,6 @@
package cd.casic.ci.common.pipeline.container;
+import cd.casic.ci.common.pipeline.type.agent.AgentType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Container.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Container.java
index 89d32bc9..d78966b2 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Container.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Container.java
@@ -1,12 +1,16 @@
package cd.casic.ci.common.pipeline.container;
import cd.casic.ci.common.pipeline.IModelTemplate;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
import cd.casic.ci.common.pipeline.pojo.time.BuildRecordTimeCost;
+import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.NoArgsConstructor;
+import lombok.Getter;
+import lombok.experimental.SuperBuilder;
import java.util.List;
import java.util.Map;
@@ -20,8 +24,8 @@ import java.util.Map;
* @Filename:Container
* @description:Todo
*/
-
-
+@Data
+@SuperBuilder
@Schema(title = "流水线模型-多态基类")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
@JsonSubTypes({
@@ -29,50 +33,65 @@ import java.util.Map;
@JsonSubTypes.Type(value = NormalContainer.class, name = NormalContainer.classType),
@JsonSubTypes.Type(value = VMBuildContainer.class, name = VMBuildContainer.classType)
})
-public interface Container extends IModelTemplate {
- String getId();
- void setId(String id);
- String getName();
- void setName(String name);
- List getElements();
- void setElements(List elements);
- String getStatus();
- void setStatus(String status);
- Long getStartEpoch();
- void setStartEpoch(Long startEpoch);
- Long getSystemElapsed();
- void setSystemElapsed(Long systemElapsed);
- Long getElementElapsed();
- void setElementElapsed(Long elementElapsed);
- Boolean getCanRetry();
- void setCanRetry(Boolean canRetry);
- String getContainerId();
- void setContainerId(String containerId);
- String getContainerHashId();
- void setContainerHashId(String containerHashId);
- String getStartVMStatus();
- void setStartVMStatus(String startVMStatus);
- Integer getExecuteCount();
- void setExecuteCount(Integer executeCount);
- String getJobId();
- void setJobId(String jobId);
- Boolean getContainPostTaskFlag();
- void setContainPostTaskFlag(Boolean containPostTaskFlag);
- Boolean getMatrixGroupFlag();
- void setMatrixGroupFlag(Boolean matrixGroupFlag);
- BuildRecordTimeCost getTimeCost();
- void setTimeCost(BuildRecordTimeCost timeCost);
- Integer getStartVMTaskSeq();
- void setStartVMTaskSeq(Integer startVMTaskSeq);
+@Getter
+@AllArgsConstructor
+public abstract class Container implements IModelTemplate {
+ private String id;
+ private String name;
+ private List elements;
+ private String status;
+ @Deprecated
+ private Long startEpoch;
+ @Deprecated
+ private Long systemElapsed;
+ @Deprecated
+ private Long elementElapsed;
+ private Boolean canRetry;
+ private String containerId;
+ private String containerHashId;
+ private String startVMStatus;
+ private Integer executeCount;
+ private String jobId;
+ private Boolean containPostTaskFlag;
+ private Boolean matrixGroupFlag;
+ private BuildRecordTimeCost timeCost;
+ private Integer startVMTaskSeq;
- void resetBuildOption(int executeCount);
- void transformCompatibility();
- Map genTaskParams();
- String getClassType();
- Container getContainerById(String vmSeqId);
- void retryFreshMatrixOption();
- List fetchGroupContainers();
- Map fetchMatrixContext();
- Boolean containerEnabled();
- void setContainerEnable(Boolean enable);
-}
+ public void resetBuildOption(int executeCount) {
+ this.status = null;
+ this.timeCost = null;
+ this.startEpoch = null;
+ this.elementElapsed = null;
+ this.systemElapsed = null;
+ this.startVMStatus = null;
+ this.executeCount = executeCount;
+ }
+
+ public void transformCompatibility() {
+ if (elements != null) {
+ elements.forEach(Element::transformCompatibility);
+ }
+ }
+
+ public Map genTaskParams() {
+ Map configParams = JSONUtil.parseObj(this).toBean(Map.class);
+ if (elements != null && !elements.isEmpty()) {
+ configParams.put("elements", List.of());
+ }
+ return configParams;
+ }
+
+ public abstract String getClassType();
+
+ public abstract Container getContainerById(String vmSeqId);
+
+ public abstract void retryFreshMatrixOption();
+
+ public abstract List fetchGroupContainers();
+
+ public abstract Map fetchMatrixContext();
+
+ public abstract boolean containerEnabled();
+
+ public abstract void setContainerEnable(boolean enable);
+}
\ No newline at end of file
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/NormalContainer.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/NormalContainer.java
index c575bf43..1f83ca97 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/NormalContainer.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/NormalContainer.java
@@ -1,5 +1,10 @@
package cd.casic.ci.common.pipeline.container;
+import cd.casic.ci.common.pipeline.NameAndValue;
+import cd.casic.ci.common.pipeline.option.JobControlOption;
+import cd.casic.ci.common.pipeline.option.MatrixControlOption;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import cd.casic.ci.common.pipeline.pojo.time.BuildRecordTimeCost;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -130,6 +135,11 @@ public class NormalContainer implements Container {
jobControlOption = jobControlOption != null ? jobControlOption.copy(enable) : new JobControlOption(enable);
}
+ @Override
+ public void resetBuildOption(int executeCount) {
+
+ }
+
@Override
public void transformCompatibility() {
if (jobControlOption != null && jobControlOption.getTimeoutVar() == null || jobControlOption.getTimeoutVar().isBlank()) {
@@ -139,4 +149,24 @@ public class NormalContainer implements Container {
mutexGroup.setTimeoutVar(String.valueOf(mutexGroup.getTimeout()));
}
}
+
+ @Override
+ public Map genTaskParams() {
+ return null;
+ }
+
+ @Override
+ public String getTemplate() {
+ return null;
+ }
+
+ @Override
+ public String getRef() {
+ return null;
+ }
+
+ @Override
+ public Map getVariables() {
+ return null;
+ }
}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Stage.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Stage.java
index cd000fe9..dbaeb8bb 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Stage.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/Stage.java
@@ -1,6 +1,9 @@
package cd.casic.ci.common.pipeline.container;
+import cd.casic.ci.common.pipeline.IModelTemplate;
+import cd.casic.ci.common.pipeline.option.StageControlOption;
import cd.casic.ci.common.pipeline.pojo.StagePauseCheck;
+import cd.casic.ci.common.pipeline.pojo.time.BuildRecordTimeCost;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -17,89 +20,103 @@ import java.util.Map;
* @Filename:Stage
* @description:Todo
*/
-public class Stage {
- @Data
- @NoArgsConstructor
- @Schema(title = "流水线模型-阶段")
- public class Stage implements IModelTemplate {
- @Schema(title = "容器集合", required = true)
- private List containers;
- @Schema(title = "阶段ID (系统标识,用户不可编辑)", required = false)
- private String id;
- @Schema(title = "阶段名称", required = true)
- private String name;
- @Schema(title = "阶段ID (用户可编辑)", required = false)
- private String stageIdForUser;
- @Schema(title = "阶段标签", required = false, readOnly = true)
- private List tag;
- @Schema(title = "阶段状态", required = false, readOnly = true)
- private String status;
- @Schema(title = "阶段启动时间", required = false, readOnly = true)
- @Deprecated
- private Long startEpoch;
- @Schema(title = "容器运行时间", required = false, readOnly = true)
- @Deprecated
- private Long elapsed;
- @Schema(title = "用户自定义环境变量", required = false)
- private Map customBuildEnv;
- @Schema(title = "是否启用容器失败快速终止阶段", required = false)
- private Boolean fastKill;
- @Schema(title = "标识是否为FinallyStage,每个Model只能包含一个FinallyStage,并且处于最后位置", required = false)
- private Boolean finally;
- @Schema(title = "当前Stage是否能重试", required = false)
- private Boolean canRetry;
- @Schema(title = "流程控制选项", required = true)
- private StageControlOption stageControlOption;
- @Schema(title = "stage准入配置", required = false)
- private StagePauseCheck checkIn;
- @Schema(title = "stage准出配置", required = false)
- private StagePauseCheck checkOut;
- @Schema(title = "步骤运行次数", required = false, readOnly = true)
- private Integer executeCount;
- @Schema(title = "各项耗时", required = true)
- private BuildRecordTimeCost timeCost;
+@Data
+@NoArgsConstructor
+@Schema(title = "流水线模型-阶段")
+public class Stage implements IModelTemplate {
+ @Schema(title = "容器集合", required = true)
+ private List containers;
+ @Schema(title = "阶段ID (系统标识,用户不可编辑)", required = false)
+ private String id;
+ @Schema(title = "阶段名称", required = true)
+ private String name;
+ @Schema(title = "阶段ID (用户可编辑)", required = false)
+ private String stageIdForUser;
+ @Schema(title = "阶段标签", required = false, readOnly = true)
+ private List tag;
+ @Schema(title = "阶段状态", required = false, readOnly = true)
+ private String status;
+ @Schema(title = "阶段启动时间", required = false, readOnly = true)
+ @Deprecated
+ private Long startEpoch;
+ @Schema(title = "容器运行时间", required = false, readOnly = true)
+ @Deprecated
+ private Long elapsed;
+ @Schema(title = "用户自定义环境变量", required = false)
+ private Map customBuildEnv;
+ @Schema(title = "是否启用容器失败快速终止阶段", required = false)
+ private Boolean fastKill;
+ @Schema(title = "标识是否为FinallyStage,每个Model只能包含一个FinallyStage,并且处于最后位置", required = false)
+ private Boolean finallyStage;
+ @Schema(title = "当前Stage是否能重试", required = false)
+ private Boolean canRetry;
+ @Schema(title = "流程控制选项", required = true)
+ private StageControlOption stageControlOption;
+ @Schema(title = "stage准入配置", required = false)
+ private StagePauseCheck checkIn;
+ @Schema(title = "stage准出配置", required = false)
+ private StagePauseCheck checkOut;
+ @Schema(title = "步骤运行次数", required = false, readOnly = true)
+ private Integer executeCount;
+ @Schema(title = "各项耗时", required = true)
+ private BuildRecordTimeCost timeCost;
- public void resetBuildOption(Boolean init) {
- if (init != null && init) {
- status = null;
- startEpoch = null;
- elapsed = null;
- }
- if (checkIn != null) {
- checkIn.fixReviewGroups(init != null && init);
- }
- if (checkOut != null) {
- checkOut.fixReviewGroups(init != null && init);
- }
- if (stageControlOption != null && stageControlOption.getManualTrigger() && checkIn == null) {
- checkIn = StagePauseCheck.convertControlOption(stageControlOption);
- }
- if (finally !=null && finally){
- canRetry = false;
- }
+ public void resetBuildOption(Boolean init) {
+ if (init != null && init) {
+ status = null;
+ startEpoch = null;
+ elapsed = null;
}
-
- public Container getContainer(String vmSeqId) {
- if (containers != null) {
- for (Container container : containers) {
- Container foundContainer = container.getContainerById(vmSeqId);
- if (foundContainer != null) {
- return foundContainer;
- }
- }
- }
- return null;
+ if (checkIn != null) {
+ checkIn.fixReviewGroups(init != null && init);
}
-
- public void transformCompatibility() {
- if (containers != null) {
- for (Container container : containers) {
- container.transformCompatibility();
- }
- }
+ if (checkOut != null) {
+ checkOut.fixReviewGroups(init != null && init);
}
-
- public Boolean stageEnabled() {
- return stageControlOption != null ? stageControlOption.getEnable() : true;
+ if (stageControlOption != null && stageControlOption.getManualTrigger() && checkIn == null) {
+ checkIn = StagePauseCheck.convertControlOption(stageControlOption);
+ }
+ if (finallyStage !=null && finallyStage){
+ canRetry = false;
}
}
+
+ public Container getContainer(String vmSeqId) {
+ if (containers != null) {
+ for (Container container : containers) {
+ Container foundContainer = container.getContainerById(vmSeqId);
+ if (foundContainer != null) {
+ return foundContainer;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void transformCompatibility() {
+ if (containers != null) {
+ for (Container container : containers) {
+ container.transformCompatibility();
+ }
+ }
+ }
+
+ public Boolean stageEnabled() {
+ return stageControlOption != null ? stageControlOption.getEnable() : true;
+ }
+
+ @Override
+ public String getTemplate() {
+ return null;
+ }
+
+ @Override
+ public String getRef() {
+ return null;
+ }
+
+ @Override
+ public Map getVariables() {
+ return null;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/VMBuildContainer.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/VMBuildContainer.java
index 4136b162..3f4589b0 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/VMBuildContainer.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/container/VMBuildContainer.java
@@ -1,5 +1,12 @@
package cd.casic.ci.common.pipeline.container;
+import cd.casic.ci.common.pipeline.NameAndValue;
+import cd.casic.ci.common.pipeline.enums.VMBaseOS;
+import cd.casic.ci.common.pipeline.option.JobControlOption;
+import cd.casic.ci.common.pipeline.option.MatrixControlOption;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import cd.casic.ci.common.pipeline.pojo.time.BuildRecordTimeCost;
+import cd.casic.ci.common.pipeline.type.DispatchType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -154,7 +161,7 @@ public class VMBuildContainer implements Container {
@Override
public void setContainerEnable(Boolean enable) {
- jobControlOption = jobControlOption != null ? jobControlOption.copy(enable) : new JobControlOption(enable);
+ jobControlOption = jobControlOption != null ? jobControlOption.setEnable(enable) : new JobControlOption(enable);
}
@Override
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/ClassicPipelineDialect.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/ClassicPipelineDialect.java
new file mode 100644
index 00000000..e6dd2aae
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/ClassicPipelineDialect.java
@@ -0,0 +1,32 @@
+package cd.casic.ci.common.pipeline.dialect;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.dialect
+ * @Project:ops-pro
+ * @name:ClassicPipelineDialect
+ * @Date:2025/03/27 10:36
+ * @Filename:ClassicPipelineDialect
+ * @description:Todo
+ */
+@Getter
+@Setter
+public class ClassicPipelineDialect implements IPipelineDialect {
+ @Override
+ public String getPipelineDialectType() {
+ return PipelineDialectType.CLASSIC.name();
+ }
+
+ @Override
+ public boolean supportUseExpression() {
+ return false;
+ }
+
+ @Override
+ public boolean supportChineseVarName() {
+ return true;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/ConstrainedPipelineDialect.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/ConstrainedPipelineDialect.java
new file mode 100644
index 00000000..2e609ddd
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/ConstrainedPipelineDialect.java
@@ -0,0 +1,32 @@
+package cd.casic.ci.common.pipeline.dialect;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.dialect
+ * @Project:ops-pro
+ * @name:ConstrainedPipelineDialect
+ * @Date:2025/03/27 10:36
+ * @Filename:ConstrainedPipelineDialect
+ * @description:Todo
+ */
+@Getter
+@Setter
+public class ConstrainedPipelineDialect implements IPipelineDialect {
+ @Override
+ public String getPipelineDialectType() {
+ return PipelineDialectType.CONSTRAINED.name();
+ }
+
+ @Override
+ public boolean supportUseExpression() {
+ return true;
+ }
+
+ @Override
+ public boolean supportChineseVarName() {
+ return false;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/IPipelineDialect.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/IPipelineDialect.java
new file mode 100644
index 00000000..ba48c9ce
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/IPipelineDialect.java
@@ -0,0 +1,24 @@
+package cd.casic.ci.common.pipeline.dialect;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.dialect
+ * @Project:ops-pro
+ * @name:IPipelineDialect
+ * @Date:2025/03/27 10:35
+ * @Filename:IPipelineDialect
+ * @description:Todo
+ */
+public interface IPipelineDialect {
+ String getPipelineDialectType();
+
+ /**
+ * 1. 仅支持双花括号,避免出现 bash 脚本变量在执行前被系统赋值的问题
+ * 2. 流程控制选项、插件入参、Job设置等流水线配置中均可使用函数
+ */
+ boolean supportUseExpression();
+ /**
+ * 是否支持中文变量名
+ */
+ boolean supportChineseVarName();
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/PipelineDialectType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/PipelineDialectType.java
new file mode 100644
index 00000000..40dbd626
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/PipelineDialectType.java
@@ -0,0 +1,24 @@
+package cd.casic.ci.common.pipeline.dialect;
+
+import lombok.Getter;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.dialect
+ * @Project:ops-pro
+ * @name:PipelineDialectType
+ * @Date:2025/03/27 10:36
+ * @Filename:PipelineDialectType
+ * @description:Todo
+ */
+@Getter
+public enum PipelineDialectType {
+ CLASSIC(new ClassicPipelineDialect()),
+ CONSTRAINED(new ConstrainedPipelineDialect());
+
+ private final IPipelineDialect dialect;
+
+ PipelineDialectType(IPipelineDialect dialect) {
+ this.dialect = dialect;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/PipelineDialectUtil.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/PipelineDialectUtil.java
new file mode 100644
index 00000000..c9725e0e
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/dialect/PipelineDialectUtil.java
@@ -0,0 +1,36 @@
+package cd.casic.ci.common.pipeline.dialect;
+
+import cd.casic.ci.common.pipeline.enums.ChannelCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.dialect
+ * @Project:ops-pro
+ * @name:PipelineDialectUtil
+ * @Date:2025/03/27 10:36
+ * @Filename:PipelineDialectUtil
+ * @description:Todo
+ */
+@NoArgsConstructor
+public class PipelineDialectUtil {
+ public static IPipelineDialect getPipelineDialect(String pipelineDialectType) {
+ return pipelineDialectType != null ? PipelineDialectType.valueOf(pipelineDialectType).getDialect() : PipelineDialectType.CLASSIC.getDialect();
+ }
+
+ public static IPipelineDialect getPipelineDialect(Boolean inheritedDialect, String projectDialect, String pipelineDialect) {
+ return getPipelineDialectType(inheritedDialect, projectDialect, pipelineDialect).getDialect();
+ }
+
+ public static PipelineDialectType getPipelineDialectType(Boolean inheritedDialect, String projectDialect, String pipelineDialect) {
+ if (inheritedDialect == null || inheritedDialect) {
+ if (projectDialect != null) {
+ return PipelineDialectType.valueOf(projectDialect);
+ }
+ } else if (pipelineDialect != null) {
+ return PipelineDialectType.valueOf(pipelineDialect);
+ }
+ return PipelineDialectType.CLASSIC;
+ }
+
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/enums/StartType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/enums/StartType.java
index e19f91db..2a8dd989 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/enums/StartType.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/enums/StartType.java
@@ -1,5 +1,6 @@
package cd.casic.ci.common.pipeline.enums;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.slf4j.LoggerFactory;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/extend/ModelCheckPlugin.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/extend/ModelCheckPlugin.java
new file mode 100644
index 00000000..80310cb2
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/extend/ModelCheckPlugin.java
@@ -0,0 +1,83 @@
+package cd.casic.ci.common.pipeline.extend;
+
+import cd.casic.ci.common.pipeline.Model;
+import cd.casic.ci.common.pipeline.container.Container;
+import cd.casic.ci.common.pipeline.dialect.IPipelineDialect;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import cd.casic.ci.common.pipeline.pojo.element.atom.BeforeDeleteParam;
+import cd.casic.ci.common.pipeline.pojo.setting.PipelineSetting;
+
+import java.util.Map;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.extend
+ * @Project:ops-pro
+ * @name:ModelCheckPlugin
+ * @Date:2025/03/27 10:39
+ * @Filename:ModelCheckPlugin
+ * @description:Todo
+ */
+public interface ModelCheckPlugin {
+
+ /**
+ * 检查[model]编排的完整性,并返回[JobSize + ElementSize = MetaSize]所有元素数量
+ *
+ * @param userId 操作人
+ * @param oauthUser 当前流水线权限代持人
+ * @param pipelineDialect 流水线方言,只有新增/编辑流水线或模版时才需要传入
+ * @throws ErrorCodeException 检查失败或异常
+ */
+ int checkModelIntegrity(
+ Model model,
+ String projectId,
+ String userId,
+ boolean isTemplate,
+ String oauthUser,
+ IPipelineDialect pipelineDialect,
+ String pipelineId
+ ) throws ErrorCodeException;
+
+ /**
+ * 检查[setting]配置的完整性
+ *
+ * @throws ErrorCodeException 检查失败或异常
+ */
+ void checkSettingIntegrity(PipelineSetting setting, String projectId) throws ErrorCodeException;
+
+ /**
+ * 清理Model--不删除里面的Element内的逻辑
+ */
+ void clearUpModel(Model model);
+
+ /**
+ * 在删除element前做的一些处理
+ * 对比sourceModel,并清理model中与之不同的Element
+ *
+ * @param existModel 目标Model(要清理的Model)
+ * @param sourceModel 源要比较的Model
+ */
+ void beforeDeleteElementInExistsModel(
+ Model existModel,
+ Model sourceModel,
+ BeforeDeleteParam param
+ );
+
+ /**
+ * 检查[container]下的[element]插件的超时配置是否合法。
+ * 如果使用了变量,则从变量表[contextMap]进行替换,如果值不符合,则抛出异常[ErrorCodeException]
+ */
+ void checkElementTimeoutVar(Container container, Element element, Map contextMap) throws ErrorCodeException;
+
+ /**
+ * 检查[container]下互斥组配置是否合法,
+ * 如果使用了变量,则从变量表[contextMap]进行替换,如果值不符合,则抛出异常[ErrorCodeException]
+ */
+ void checkMutexGroup(Container container, Map contextMap) throws ErrorCodeException;
+
+ /**
+ * 检查是否是[finallyStage]Stage的Job[container]下[JobControlOption]配置是否合法。
+ * 如果使用了变量,则从变量表[contextMap]进行替换,如果值不符合,则抛出异常[ErrorCodeException]
+ */
+ void checkJobCondition(Container container, boolean finallyStage, Map contextMap) throws ErrorCodeException;
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/StagePauseCheck.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/StagePauseCheck.java
index b5ef72ce..2c43dd86 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/StagePauseCheck.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/StagePauseCheck.java
@@ -1,6 +1,16 @@
package cd.casic.ci.common.pipeline.pojo;
+import cd.casic.ci.common.pipeline.EnvReplacementParser;
+import cd.casic.ci.common.pipeline.dialect.IPipelineDialect;
+import cd.casic.ci.common.pipeline.enums.BuildStatus;
+import cd.casic.ci.common.pipeline.enums.ManualReviewAction;
+import cd.casic.ci.common.pipeline.option.StageControlOption;
+import cd.casic.ci.common.pipeline.pojo.element.atom.ManualReviewParam;
+import cn.hutool.captcha.generator.RandomGenerator;
+import cn.hutool.core.lang.UUID;
+import cn.hutool.core.util.IdUtil;
import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -20,6 +30,7 @@ import java.util.stream.Collectors;
* @description:Todo
*/
@Data
+@Builder
@Accessors(chain = true)
@Schema(title = "stage准入准出配置模型")
public class StagePauseCheck {
@@ -192,11 +203,12 @@ public class StagePauseCheck {
}
public static StagePauseCheck convertControlOption(StageControlOption stageControlOption) {
+
return new StagePauseCheck()
.setManualTrigger(stageControlOption.getManualTrigger())
.setStatus(stageControlOption.getTriggered() ? BuildStatus.REVIEW_PROCESSED.name() : null)
.setReviewGroups(List.of(new StageReviewGroup()
- .setId(UUIDUtil.generate())
+ .setId(IdUtil.fastUUID())
.setReviewers(stageControlOption.getTriggerUsers())
.setStatus(stageControlOption.getTriggered() ? ManualReviewAction.PROCESS.name() : null)
.setParams(stageControlOption.getReviewParams())))
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/Element.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/Element.java
index 418a6054..6c285948 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/Element.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/Element.java
@@ -4,9 +4,19 @@ import cd.casic.ci.common.pipeline.IModelTemplate;
import cd.casic.ci.common.pipeline.NameAndValue;
import cd.casic.ci.common.pipeline.enums.BuildStatus;
import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.agent.*;
+import cd.casic.ci.common.pipeline.pojo.element.market.MarketBuildAtomElement;
+import cd.casic.ci.common.pipeline.pojo.element.market.MarketBuildLessAtomElement;
+import cd.casic.ci.common.pipeline.pojo.element.market.MarketCheckImageElement;
+import cd.casic.ci.common.pipeline.pojo.element.matrix.MatrixStatusElement;
+import cd.casic.ci.common.pipeline.pojo.element.quality.QualityGateInElement;
+import cd.casic.ci.common.pipeline.pojo.element.quality.QualityGateOutElement;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.*;
import cd.casic.ci.common.pipeline.pojo.time.BuildRecordTimeCost;
import cd.casic.ci.common.pipeline.pojo.transfer.PreStep;
import cd.casic.ci.common.pipeline.utils.ElementUtils;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -121,7 +131,7 @@ public abstract class Element implements IModelTemplate {
}
public Map genTaskParams() {
- return JsonUtil.toMutableMap(this);
+ return JSONUtil.parseObj(this).toBean(Map.class);
}
public void cleanUp() {
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/ElementProp.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/ElementProp.java
index ba39c489..2dde6217 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/ElementProp.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/ElementProp.java
@@ -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;
/**
@@ -13,6 +14,7 @@ import lombok.Data;
* @description:Todo
*/
@Data
+@AllArgsConstructor
@Schema(title = "插件属性")
public class ElementProp {
private String name;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/AtomBuildArchiveElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/AtomBuildArchiveElement.java
similarity index 97%
rename from modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/AtomBuildArchiveElement.java
rename to modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/AtomBuildArchiveElement.java
index 303c031f..1d6405d8 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/AtomBuildArchiveElement.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/AtomBuildArchiveElement.java
@@ -1,4 +1,4 @@
-package cd.casic.ci.common.pipeline.pojo.market;
+package cd.casic.ci.common.pipeline.pojo.element.market;
import cd.casic.ci.common.pipeline.pojo.element.Element;
import io.swagger.v3.oas.annotations.media.Schema;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketBuildAtomElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketBuildAtomElement.java
similarity index 97%
rename from modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketBuildAtomElement.java
rename to modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketBuildAtomElement.java
index 3221f6b1..7735f1b6 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketBuildAtomElement.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketBuildAtomElement.java
@@ -1,4 +1,4 @@
-package cd.casic.ci.common.pipeline.pojo.market;
+package cd.casic.ci.common.pipeline.pojo.element.market;
import cd.casic.ci.common.pipeline.NameAndValue;
import cd.casic.ci.common.pipeline.pojo.element.Element;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketBuildLessAtomElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketBuildLessAtomElement.java
similarity index 97%
rename from modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketBuildLessAtomElement.java
rename to modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketBuildLessAtomElement.java
index cf83f4f2..32504c1c 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketBuildLessAtomElement.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketBuildLessAtomElement.java
@@ -1,4 +1,4 @@
-package cd.casic.ci.common.pipeline.pojo.market;
+package cd.casic.ci.common.pipeline.pojo.element.market;
import cd.casic.ci.common.pipeline.NameAndValue;
import cd.casic.ci.common.pipeline.pojo.element.Element;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketCheckImageElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketCheckImageElement.java
similarity index 95%
rename from modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketCheckImageElement.java
rename to modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketCheckImageElement.java
index f3c1a8eb..7f9d870f 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/market/MarketCheckImageElement.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/market/MarketCheckImageElement.java
@@ -1,4 +1,4 @@
-package cd.casic.ci.common.pipeline.pojo.market;
+package cd.casic.ci.common.pipeline.pojo.element.market;
import cd.casic.ci.common.pipeline.pojo.element.Element;
import io.swagger.v3.oas.annotations.media.Schema;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/matrix/MatrixStatusElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/matrix/MatrixStatusElement.java
similarity index 97%
rename from modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/matrix/MatrixStatusElement.java
rename to modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/matrix/MatrixStatusElement.java
index bbbf7ebb..cddfda7b 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/matrix/MatrixStatusElement.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/matrix/MatrixStatusElement.java
@@ -1,4 +1,4 @@
-package cd.casic.ci.common.pipeline.pojo.matrix;
+package cd.casic.ci.common.pipeline.pojo.element.matrix;
import cd.casic.ci.common.pipeline.NameAndValue;
import cd.casic.ci.common.pipeline.pojo.element.Element;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/quality/QualityGateInElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/quality/QualityGateInElement.java
similarity index 97%
rename from modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/quality/QualityGateInElement.java
rename to modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/quality/QualityGateInElement.java
index a6733bfb..c9d866c8 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/quality/QualityGateInElement.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/quality/QualityGateInElement.java
@@ -1,4 +1,4 @@
-package cd.casic.ci.common.pipeline.pojo.quality;
+package cd.casic.ci.common.pipeline.pojo.element.quality;
import cd.casic.ci.common.pipeline.pojo.element.Element;
import io.swagger.v3.oas.annotations.media.Schema;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/quality/QualityGateOutElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/quality/QualityGateOutElement.java
similarity index 97%
rename from modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/quality/QualityGateOutElement.java
rename to modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/quality/QualityGateOutElement.java
index 88478857..d5898a5f 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/quality/QualityGateOutElement.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/quality/QualityGateOutElement.java
@@ -1,4 +1,4 @@
-package cd.casic.ci.common.pipeline.pojo.quality;
+package cd.casic.ci.common.pipeline.pojo.element.quality;
import cd.casic.ci.common.pipeline.pojo.element.Element;
import io.swagger.v3.oas.annotations.media.Schema;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGitWebHookTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGitWebHookTriggerElement.java
new file mode 100644
index 00000000..60a248e4
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGitWebHookTriggerElement.java
@@ -0,0 +1,225 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.api.enums.TriggerRepositoryType;
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.CodeEventType;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.PathFilterType;
+import cd.casic.ci.common.pipeline.utils.TriggerElementPropUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:CodeGitWebHookTriggerElement
+ * @Date:2025/03/27 10:20
+ * @Filename:CodeGitWebHookTriggerElement
+ * @description:Todo
+ */
+@Accessors(chain = true)
+@Schema(title = "Git事件触发", description = CodeGitWebHookTriggerElement.classType)
+public class CodeGitWebHookTriggerElement extends WebHookTriggerElement {
+ public static final String classType = "codeGitWebHookTrigger";
+ public static final String MERGE_ACTION_OPEN = "open";
+ public static final String MERGE_ACTION_CLOSE = "close";
+ public static final String MERGE_ACTION_REOPEN = "reopen";
+ public static final String MERGE_ACTION_PUSH_UPDATE = "push-update";
+ public static final String MERGE_ACTION_MERGE = "merge";
+ public static final String PUSH_ACTION_CREATE_BRANCH = "new-branch";
+ public static final String PUSH_ACTION_PUSH_FILE = "push-file";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "Git事件触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "仓库ID", required = true)
+ private String repositoryHashId;
+
+ @Schema(title = "分支名称", required = false)
+ private String branchName;
+
+ @Schema(title = "用于排除的分支名", required = false)
+ private String excludeBranchName;
+
+ @Schema(title = "路径过滤类型", required = true)
+ private PathFilterType pathFilterType = PathFilterType.NamePrefixFilter;
+
+ @Schema(title = "用于包含的路径", required = false)
+ private String includePaths;
+
+ @Schema(title = "用于排除的路径", required = false)
+ private String excludePaths;
+
+ @Schema(title = "用户白名单", required = false)
+ private List includeUsers;
+
+ @Schema(title = "用于排除的user id", required = false)
+ private List excludeUsers;
+
+ @Schema(title = "事件类型", required = false)
+ private CodeEventType eventType;
+
+ @Schema(title = "是否为block", required = false)
+ private Boolean block;
+
+ @Schema(title = "新版的git原子的类型")
+ private TriggerRepositoryType repositoryType;
+
+ @Schema(title = "新版的git代码库名")
+ private String repositoryName;
+
+ @Schema(title = "tag名称", required = false)
+ private String tagName;
+
+ @Schema(title = "用于排除的tag名称", required = false)
+ private String excludeTagName;
+
+ @Schema(title = "tag从哪条分支创建", required = false)
+ private String fromBranches;
+
+ @Schema(title = "用于排除的源分支名称", required = false)
+ private String excludeSourceBranchName;
+
+ @Schema(title = "用于包含的源分支名称", required = false)
+ private String includeSourceBranchName;
+
+ @Schema(title = "webhook队列", required = false)
+ private Boolean webhookQueue = false;
+
+ @Schema(title = "code review 状态", required = false)
+ private List includeCrState;
+
+ @Schema(title = "code review 类型", required = false)
+ private List includeCrTypes;
+
+ @Schema(title = "code note comment", required = false)
+ private String includeNoteComment;
+
+ @Schema(title = "code note 类型", required = false)
+ private List includeNoteTypes;
+
+ @Schema(title = "是否启用回写")
+ private Boolean enableCheck = true;
+
+ @Schema(title = "issue事件action")
+ private List includeIssueAction;
+
+ @Schema(title = "mr事件action")
+ private List includeMrAction;
+
+ @Schema(title = "push事件action")
+ private List includePushAction;
+
+ @Schema(title = "是否启用第三方过滤")
+ private Boolean enableThirdFilter = false;
+
+ @Schema(title = "第三方应用地址")
+ private String thirdUrl;
+
+ @Schema(title = "第三方应用鉴权token")
+ private String thirdSecretToken;
+
+ @Schema(title = "跳过WIP")
+ private Boolean skipWip = false;
+
+ public CodeGitWebHookTriggerElement(String name, String id, String status) {
+ super(name, id, status);
+ }
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return StartType.WEB_HOOK.name().equals(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+
+ @Override
+ public List triggerCondition() {
+ List props;
+ switch (eventType) {
+ case PUSH:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", joinToString(includePushAction)),
+ TriggerElementPropUtils.vuexInput("branchName", branchName),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", excludeBranchName),
+ TriggerElementPropUtils.vuexInput("includePaths", includePaths),
+ TriggerElementPropUtils.vuexInput("excludePaths", excludePaths),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ );
+ break;
+ case MERGE_REQUEST:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", joinToString(includeMrAction)),
+ TriggerElementPropUtils.selector("skip-wip", List.of((skipWip != null ? skipWip.toString() : "false"))),
+ TriggerElementPropUtils.vuexInput("branchName", branchName),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", excludeBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includePaths", includePaths),
+ TriggerElementPropUtils.vuexInput("excludePaths", excludePaths),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ );
+ break;
+ case MERGE_REQUEST_ACCEPT:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", "merge"),
+ TriggerElementPropUtils.vuexInput("branchName", branchName),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", excludeBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includePaths", includePaths),
+ TriggerElementPropUtils.vuexInput("excludePaths", excludePaths),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ );
+ break;
+ case TAG_PUSH:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("tagName", tagName),
+ TriggerElementPropUtils.vuexInput("excludeTagName", excludeTagName),
+ TriggerElementPropUtils.vuexInput("fromBranches", fromBranches),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ );
+ break;
+ case REVIEW:
+ props = List.of(
+ TriggerElementPropUtils.selector("includeCrState", includeCrState),
+ TriggerElementPropUtils.selector("includeCrTypes", includeCrTypes)
+ );
+ break;
+ case ISSUES:
+ props = List.of(
+ TriggerElementPropUtils.selector("includeIssueAction", includeIssueAction)
+ );
+ break;
+ case NOTE:
+ props = List.of(
+ TriggerElementPropUtils.selector("includeNoteTypes", includeNoteTypes),
+ TriggerElementPropUtils.vuexInput("includeNoteComment", includeNoteComment)
+ );
+ break;
+ default:
+ props = List.of();
+ }
+ return props.stream().filter(java.util.Objects::nonNull).toList();
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGithubWebHookTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGithubWebHookTriggerElement.java
new file mode 100644
index 00000000..37cad728
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGithubWebHookTriggerElement.java
@@ -0,0 +1,134 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.api.enums.TriggerRepositoryType;
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.CodeEventType;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.PathFilterType;
+import cd.casic.ci.common.pipeline.utils.TriggerElementPropUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:CodeGithubWebHookTriggerElement
+ * @Date:2025/03/27 9:42
+ * @Filename:CodeGithubWebHookTriggerElement
+ * @description:Todo
+ */
+@Accessors(chain = true)
+@Schema(title = "Github事件触发", description = CodeGithubWebHookTriggerElement.classType)
+public class CodeGithubWebHookTriggerElement extends WebHookTriggerElement {
+ public static final String classType = "codeGithubWebHookTrigger";
+ public static final String MERGE_ACTION_OPEN = "open";
+ public static final String MERGE_ACTION_CLOSE = "close";
+ public static final String MERGE_ACTION_REOPEN = "reopen";
+ public static final String MERGE_ACTION_PUSH_UPDATE = "push-update";
+ public static final String MERGE_ACTION_MERGE = "merge";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "GitHub事件触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "仓库ID", required = true)
+ private String repositoryHashId;
+
+ @Schema(title = "分支名称", required = false)
+ private String branchName;
+
+ @Schema(title = "用于排除的分支名称", required = false)
+ private String excludeBranchName;
+
+ @Schema(title = "路径过滤类型", required = true)
+ private PathFilterType pathFilterType = PathFilterType.NamePrefixFilter;
+
+ @Schema(title = "用于包含的路径", required = false)
+ private String includePaths;
+
+ @Schema(title = "用于排除的路径", required = false)
+ private String excludePaths;
+
+ @Schema(title = "用户白名单", required = false)
+ private List includeUsers;
+
+ @Schema(title = "用于排除的user id", required = false)
+ private String excludeUsers;
+
+ @Schema(title = "tag名称", required = false)
+ private String tagName;
+
+ @Schema(title = "用于排除的tag名称", required = false)
+ private String excludeTagName;
+
+ @Schema(title = "tag从哪条分支创建", required = false)
+ private String fromBranches;
+
+ @Schema(title = "用于排除的源分支名称", required = false)
+ private String excludeSourceBranchName;
+
+ @Schema(title = "用于包含的源分支名称", required = false)
+ private String includeSourceBranchName;
+
+ @Schema(title = "webhook队列", required = false)
+ private Boolean webhookQueue = false;
+
+ @Schema(title = "code review 类型", required = false)
+ private List includeCrTypes;
+
+ @Schema(title = "是否启用回写")
+ private Boolean enableCheck = true;
+
+ @Schema(title = "push事件action")
+ private List includePushAction;
+
+ @Schema(title = "是否启用第三方过滤")
+ private Boolean enableThirdFilter = false;
+
+ @Schema(title = "事件类型", required = false)
+ private CodeEventType eventType;
+
+ @Schema(title = "新版的github原子的类型")
+ private TriggerRepositoryType repositoryType;
+
+ @Schema(title = "新版的github代码库名")
+ private String repositoryName;
+
+ @Schema(title = "code review 状态", required = false)
+ private List includeCrState;
+
+ @Schema(title = "code note comment", required = false)
+ private String includeNoteComment;
+
+ @Schema(title = "code note 类型", required = false)
+ private List includeNoteTypes;
+
+ @Schema(title = "issue事件action")
+ private List includeIssueAction;
+
+ @Schema(title = "pull request事件action")
+ private List includeMrAction = List.of(MERGE_ACTION_OPEN, MERGE_ACTION_REOPEN, MERGE_ACTION_PUSH_UPDATE);
+
+ public CodeGithubWebHookTriggerElement(String name, String id, String status) {
+ super(name, id, status);
+ }
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return StartType.WEB_HOOK.name().equals(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGitlabWebHookTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGitlabWebHookTriggerElement.java
new file mode 100644
index 00000000..8f15b68f
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeGitlabWebHookTriggerElement.java
@@ -0,0 +1,164 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.api.enums.TriggerRepositoryType;
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.CodeEventType;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.PathFilterType;
+import cd.casic.ci.common.pipeline.utils.TriggerElementPropUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:CodeGitlabWebHookTriggerElement
+ * @Date:2025/03/27 10:22
+ * @Filename:CodeGitlabWebHookTriggerElement
+ * @description:Todo
+ */
+@Accessors(chain = true)
+@Schema(title = "GitLab仓库代码提交触发", description = CodeGitlabWebHookTriggerElement.classType)
+public class CodeGitlabWebHookTriggerElement extends WebHookTriggerElement {
+ public static final String classType = "codeGitlabWebHookTrigger";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "Gitlab变更触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "仓库ID", required = true)
+ private String repositoryHashId;
+
+ @Schema(title = "分支名称", required = false)
+ private String branchName;
+
+ @Schema(title = "新版的gitlab原子的类型")
+ private TriggerRepositoryType repositoryType;
+
+ @Schema(title = "新版的gitlab代码库名")
+ private String repositoryName;
+
+ @Schema(title = "事件类型", required = false)
+ private CodeEventType eventType = CodeEventType.PUSH;
+
+ @Schema(title = "用于排除的分支名", required = false)
+ private String excludeBranchName;
+
+ @Schema(title = "路径过滤类型", required = true)
+ private PathFilterType pathFilterType = PathFilterType.NamePrefixFilter;
+
+ @Schema(title = "用于包含的路径", required = false)
+ private String includePaths;
+
+ @Schema(title = "用于排除的路径", required = false)
+ private String excludePaths;
+
+ @Schema(title = "用于包含的user id", required = false)
+ private List includeUsers;
+
+ @Schema(title = "用于排除的user id", required = false)
+ private List excludeUsers;
+
+ @Schema(title = "是否为block", required = false)
+ private Boolean block;
+
+ @Schema(title = "tag名称", required = false)
+ private String tagName;
+
+ @Schema(title = "用于排除的tag名称", required = false)
+ private String excludeTagName;
+
+ @Schema(title = "用于排除的源分支名称", required = false)
+ private String excludeSourceBranchName;
+
+ @Schema(title = "用于包含的源分支名称", required = false)
+ private String includeSourceBranchName;
+
+ @Schema(title = "用于包含的提交信息", required = false)
+ private String includeCommitMsg;
+
+ @Schema(title = "用于排除的提交信息", required = false)
+ private String excludeCommitMsg;
+
+ @Schema(title = "push事件action")
+ private List includePushAction;
+
+ @Schema(title = "mr事件action")
+ private List includeMrAction;
+
+ public CodeGitlabWebHookTriggerElement(String name, String id, String status) {
+ super(name, id, status);
+ }
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return StartType.WEB_HOOK.name().equals(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+
+ @Override
+ public List triggerCondition() {
+ List props;
+ switch (eventType) {
+ case PUSH:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", joinToString(includePushAction)),
+ TriggerElementPropUtils.vuexInput("branchName", branchName),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", excludeBranchName),
+ TriggerElementPropUtils.vuexInput("includePaths", includePaths),
+ TriggerElementPropUtils.vuexInput("excludePaths", excludePaths),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ );
+ break;
+ case MERGE_REQUEST:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", joinToString(includeMrAction)),
+ TriggerElementPropUtils.vuexInput("branchName", branchName),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", excludeBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includePaths", includePaths),
+ TriggerElementPropUtils.vuexInput("excludePaths", excludePaths),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ );
+ break;
+ case MERGE_REQUEST_ACCEPT:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", "merge"),
+ TriggerElementPropUtils.vuexInput("branchName", branchName),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", excludeBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", includeSourceBranchName),
+ TriggerElementPropUtils.vuexInput("includePaths", includePaths),
+ TriggerElementPropUtils.vuexInput("excludePaths", excludePaths),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ );
+ break;
+ case TAG_PUSH:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("tagName", tagName),
+ TriggerElementPropUtils.vuexInput("excludeTagName", excludeTagName)
+ );
+ break;
+ default:
+ props = List.of();
+ }
+ return props.stream().filter(java.util.Objects::nonNull).toList();
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeP4WebHookTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeP4WebHookTriggerElement.java
new file mode 100644
index 00000000..2699df7b
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeP4WebHookTriggerElement.java
@@ -0,0 +1,100 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.api.enums.TriggerRepositoryType;
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.CodeEventType;
+import cd.casic.ci.common.pipeline.utils.TriggerElementPropUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:CodeP4WebHookTriggerElement
+ * @Date:2025/03/27 10:20
+ * @Filename:CodeP4WebHookTriggerElement
+ * @description:Todo
+ */
+@Data
+@Accessors(chain = true)
+@Schema(title = "p4事件触发", description = CodeP4WebHookTriggerElement.classType)
+public class CodeP4WebHookTriggerElement extends WebHookTriggerElement {
+ public static final String classType = "codeP4WebHookTrigger";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "P4事件触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "数据", required = true)
+ private CodeP4WebHookTriggerData data;
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return StartType.WEB_HOOK.name().equals(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+
+ @Override
+ public List triggerCondition() {
+ CodeP4WebHookTriggerInput input = data.getInput();
+ List props;
+ switch (input.getEventType()) {
+ case CHANGE_COMMIT:
+ case CHANGE_SUBMIT:
+ case CHANGE_CONTENT:
+ case SHELVE_COMMIT:
+ case SHELVE_SUBMIT:
+ case SHELVE_DELETE:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("includePaths", input.getIncludePaths()),
+ TriggerElementPropUtils.vuexInput("excludePaths", input.getExcludePaths())
+ );
+ break;
+ default:
+ props = List.of();
+ }
+ return props.stream().filter(java.util.Objects::nonNull).toList();
+ }
+}
+
+@Data
+@Accessors(chain = true)
+class CodeP4WebHookTriggerData {
+ private CodeP4WebHookTriggerInput input;
+}
+
+@Data
+@Accessors(chain = true)
+class CodeP4WebHookTriggerInput {
+ @Schema(title = "仓库ID", required = true)
+ private String repositoryHashId;
+
+ @Schema(title = "新版的git原子的类型")
+ private TriggerRepositoryType repositoryType;
+
+ @Schema(title = "新版的git代码库名")
+ private String repositoryName;
+
+ @Schema(title = "用于包含的路径", required = false)
+ private String includePaths;
+
+ @Schema(title = "用于排除的路径", required = false)
+ private String excludePaths;
+
+ @Schema(title = "事件类型", required = false)
+ private CodeEventType eventType;
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeSVNWebHookTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeSVNWebHookTriggerElement.java
new file mode 100644
index 00000000..c2c9be0c
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeSVNWebHookTriggerElement.java
@@ -0,0 +1,81 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.api.enums.TriggerRepositoryType;
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.PathFilterType;
+import cd.casic.ci.common.pipeline.utils.TriggerElementPropUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:CodeSVNWebHookTriggerElement
+ * @Date:2025/03/27 10:09
+ * @Filename:CodeSVNWebHookTriggerElement
+ * @description:Todo
+ */
+@Data
+@Accessors(chain = true)
+@Schema(title = "SVN仓库代码提交触发", description = CodeSVNWebHookTriggerElement.classType)
+public class CodeSVNWebHookTriggerElement extends WebHookTriggerElement {
+ public static final String classType = "codeSVNWebHookTrigger";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "SVN事件触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "仓库ID", required = true)
+ private String repositoryHashId;
+
+ @Schema(title = "路径过滤类型", required = true)
+ private PathFilterType pathFilterType = PathFilterType.NamePrefixFilter;
+
+ @Schema(title = "相对路径", required = true)
+ private String relativePath;
+
+ @Schema(title = "排除的路径", required = false)
+ private String excludePaths;
+
+ @Schema(title = "用户黑名单", required = false)
+ private List excludeUsers;
+
+ @Schema(title = "用户白名单", required = false)
+ private List includeUsers;
+
+ @Schema(title = "新版的svn原子的类型")
+ private TriggerRepositoryType repositoryType;
+
+ @Schema(title = "新版的svn代码库名")
+ private String repositoryName;
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return StartType.WEB_HOOK.name().equals(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+
+ @Override
+ public List triggerCondition() {
+ return List.of(
+ TriggerElementPropUtils.vuexInput("relativePath", relativePath),
+ TriggerElementPropUtils.vuexInput("excludePaths", excludePaths),
+ TriggerElementPropUtils.staffInput("includeUsers", includeUsers),
+ TriggerElementPropUtils.staffInput("excludeUsers", excludeUsers)
+ ).stream().filter(java.util.Objects::nonNull).toList();
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeTGitWebHookTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeTGitWebHookTriggerElement.java
new file mode 100644
index 00000000..74094ace
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/CodeTGitWebHookTriggerElement.java
@@ -0,0 +1,222 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.api.enums.TriggerRepositoryType;
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.CodeEventType;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.enums.PathFilterType;
+import cd.casic.ci.common.pipeline.utils.TriggerElementPropUtils;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:CodeTGitWebHookTriggerElement
+ * @Date:2025/03/27 10:05
+ * @Filename:CodeTGitWebHookTriggerElement
+ * @description:Todo
+ */
+@Accessors(chain = true)
+@Schema(title = "TGit事件触发", description = CodeTGitWebHookTriggerElement.classType)
+public class CodeTGitWebHookTriggerElement extends WebHookTriggerElement {
+ public static final String classType = "codeTGitWebHookTrigger";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "TGit事件触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "数据", required = true)
+ private CodeTGitWebHookTriggerData data;
+
+ public CodeTGitWebHookTriggerElement(String name, String id, String status) {
+ super(name, id, status);
+ }
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return StartType.WEB_HOOK.name().equals(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+
+ @Override
+ public List triggerCondition() {
+ CodeTGitWebHookTriggerInput input = data.getInput();
+ List props;
+ switch (input.getEventType()) {
+ case PUSH:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", joinToString(input.getIncludePushAction())),
+ TriggerElementPropUtils.vuexInput("branchName", input.getBranchName()),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", input.getExcludeBranchName()),
+ TriggerElementPropUtils.vuexInput("includePaths", input.getIncludePaths()),
+ TriggerElementPropUtils.vuexInput("excludePaths", input.getExcludePaths()),
+ TriggerElementPropUtils.staffInput("includeUsers", input.getIncludeUsers()),
+ TriggerElementPropUtils.staffInput("excludeUsers", input.getExcludeUsers())
+ );
+ break;
+ case MERGE_REQUEST:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", joinToString(input.getIncludeMrAction())),
+ TriggerElementPropUtils.selector("skip-wip", List.of((input.getSkipWip() != null ? input.getSkipWip().toString() : "false"))),
+ TriggerElementPropUtils.vuexInput("branchName", input.getBranchName()),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", input.getExcludeBranchName()),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", input.getIncludeSourceBranchName()),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", input.getIncludeSourceBranchName()),
+ TriggerElementPropUtils.vuexInput("includePaths", input.getIncludePaths()),
+ TriggerElementPropUtils.vuexInput("excludePaths", input.getExcludePaths()),
+ TriggerElementPropUtils.staffInput("includeUsers", input.getIncludeUsers()),
+ TriggerElementPropUtils.staffInput("excludeUsers", input.getExcludeUsers())
+ );
+ break;
+ case MERGE_REQUEST_ACCEPT:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("action", "merge"),
+ TriggerElementPropUtils.vuexInput("branchName", input.getBranchName()),
+ TriggerElementPropUtils.vuexInput("excludeBranchName", input.getExcludeBranchName()),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", input.getIncludeSourceBranchName()),
+ TriggerElementPropUtils.vuexInput("includeSourceBranchName", input.getIncludeSourceBranchName()),
+ TriggerElementPropUtils.vuexInput("includePaths", input.getIncludePaths()),
+ TriggerElementPropUtils.vuexInput("excludePaths", input.getExcludePaths()),
+ TriggerElementPropUtils.staffInput("includeUsers", input.getIncludeUsers()),
+ TriggerElementPropUtils.staffInput("excludeUsers", input.getExcludeUsers())
+ );
+ break;
+ case TAG_PUSH:
+ props = List.of(
+ TriggerElementPropUtils.vuexInput("tagName", input.getTagName()),
+ TriggerElementPropUtils.vuexInput("excludeTagName", input.getExcludeTagName()),
+ TriggerElementPropUtils.vuexInput("fromBranches", input.getFromBranches()),
+ TriggerElementPropUtils.staffInput("includeUsers", input.getIncludeUsers()),
+ TriggerElementPropUtils.staffInput("excludeUsers", input.getExcludeUsers())
+ );
+ break;
+ case REVIEW:
+ props = List.of(
+ TriggerElementPropUtils.selector("includeCrState", input.getIncludeCrState())
+ );
+ break;
+ case ISSUES:
+ props = List.of(
+ TriggerElementPropUtils.selector("includeIssueAction", input.getIncludeIssueAction())
+ );
+ break;
+ case NOTE:
+ props = List.of(
+ TriggerElementPropUtils.selector("includeNoteTypes", input.getIncludeNoteTypes()),
+ TriggerElementPropUtils.vuexInput("includeNoteComment", input.getIncludeNoteComment())
+ );
+ break;
+ default:
+ props = List.of();
+ }
+ return props.stream().filter(java.util.Objects::nonNull).toList();
+ }
+}
+
+@Data
+@Accessors(chain = true)
+class CodeTGitWebHookTriggerData {
+ private CodeTGitWebHookTriggerInput input;
+}
+
+@Data
+@Accessors(chain = true)
+class CodeTGitWebHookTriggerInput {
+ @Schema(title = "仓库ID", required = true)
+ private String repositoryHashId;
+
+ @Schema(title = "分支名称", required = false)
+ private String branchName;
+
+ @Schema(title = "用于排除的分支名", required = false)
+ private String excludeBranchName;
+
+ @Schema(title = "路径过滤类型", required = true)
+ private PathFilterType pathFilterType = PathFilterType.NamePrefixFilter;
+
+ @Schema(title = "用于包含的路径", required = false)
+ private String includePaths;
+
+ @Schema(title = "用于排除的路径", required = false)
+ private String excludePaths;
+
+ @Schema(title = "用户白名单", required = false)
+ private List includeUsers;
+
+ @Schema(title = "用于排除的user id", required = false)
+ private List excludeUsers;
+
+ @Schema(title = "事件类型", required = false)
+ private CodeEventType eventType;
+
+ @Schema(title = "是否为block", required = false)
+ private Boolean block;
+
+ @Schema(title = "新版的git原子的类型")
+ private TriggerRepositoryType repositoryType;
+
+ @Schema(title = "新版的git代码库名")
+ private String repositoryName;
+
+ @Schema(title = "tag名称", required = false)
+ private String tagName;
+
+ @Schema(title = "用于排除的tag名称", required = false)
+ private String excludeTagName;
+
+ @Schema(title = "tag从哪条分支创建", required = false)
+ private String fromBranches;
+
+ @Schema(title = "用于排除的源分支名称", required = false)
+ private String excludeSourceBranchName;
+
+ @Schema(title = "用于包含的源分支名称", required = false)
+ private String includeSourceBranchName;
+
+ @Schema(title = "webhook队列", required = false)
+ private Boolean webhookQueue = false;
+
+ @Schema(title = "code review 状态", required = false)
+ private List includeCrState;
+
+ @Schema(title = "code review 类型", required = false)
+ private List includeCrTypes;
+
+ @Schema(title = "code note comment", required = false)
+ private String includeNoteComment;
+
+ @Schema(title = "code note 类型", required = false)
+ private List includeNoteTypes;
+
+ @Schema(title = "是否启用回写")
+ private Boolean enableCheck = true;
+
+ @Schema(title = "issue事件action")
+ private List includeIssueAction;
+
+ @Schema(title = "mr事件action")
+ private List includeMrAction;
+
+ @Schema(title = "push事件action")
+ private List includePushAction;
+
+ @Schema(title = "是否启用第三方过滤")
+ private Boolean enableThirdFilter = false;
+
+ @Schema(title = "跳过WIP")
+ private Boolean skipWip = false;
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/ManualTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/ManualTriggerElement.java
new file mode 100644
index 00000000..0953c1a6
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/ManualTriggerElement.java
@@ -0,0 +1,52 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Set;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:ManualTriggerElement
+ * @Date:2025/03/27 10:04
+ * @Filename:ManualTriggerElement
+ * @description:Todo
+ */
+@Data
+@Accessors(chain = true)
+@Schema(title = "手动触发")
+public class ManualTriggerElement extends Element {
+ public static final String classType = "manualTrigger";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "手动触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "是否可跳过插件", required = false)
+ private Boolean canElementSkip;
+
+ @Schema(title = "是否使用最近一次的参数进行构建", required = false)
+ private Boolean useLatestParameters;
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ private Set startTypeSet = Set.of(StartType.MANUAL.name(), StartType.SERVICE.name(), StartType.PIPELINE.name());
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return startTypeSet.contains(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/RemoteTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/RemoteTriggerElement.java
new file mode 100644
index 00000000..dfe3207c
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/RemoteTriggerElement.java
@@ -0,0 +1,43 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:RemoteTriggerElement
+ * @Date:2025/03/27 10:01
+ * @Filename:RemoteTriggerElement
+ * @description:Todo
+ */
+@Data
+@Accessors(chain = true)
+@Schema(title = "远程触发触发")
+public class RemoteTriggerElement extends Element {
+
+ public static final String classType = "remoteTrigger";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "远程触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "是否可跳过插件", required = false)
+ private Boolean canElementSkip;
+
+ @Schema(title = "远程触发token", required = true)
+ private String remoteToken;
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/TimerTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/TimerTriggerElement.java
new file mode 100644
index 00000000..560f21f2
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/TimerTriggerElement.java
@@ -0,0 +1,92 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.api.enums.TriggerRepositoryType;
+import cd.casic.ci.common.pipeline.enums.StartType;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.*;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:TimerTriggerElement
+ * @Date:2025/03/27 10:00
+ * @Filename:TimerTriggerElement
+ * @description:Todo
+ */
+@Data
+@Accessors(chain = true)
+@Schema(title = "定时触发")
+public class TimerTriggerElement extends Element {
+ public static final String classType = "timerTrigger";
+
+ @Schema(title = "任务名称", required = true)
+ private String name = "定时触发";
+
+ @Schema(title = "id", required = false)
+ private String id;
+
+ @Schema(title = "状态", required = false)
+ private String status;
+
+ @Schema(title = "定时表达式", required = false)
+ @Deprecated
+ private String expression;
+
+ @Schema(title = "改进后的表达式", required = false)
+ private List newExpression;
+
+ @Schema(title = "高级定时表达式", required = false)
+ private List advanceExpression;
+
+ @Schema(title = "源代码未更新则不触发构建", required = false)
+ private Boolean noScm;
+
+ @Schema(title = "指定代码库分支", required = false)
+ private List branches;
+
+ @Schema(title = "代码库类型", required = false)
+ private TriggerRepositoryType repositoryType;
+
+ @Schema(title = "代码库HashId", required = false)
+ private String repoHashId;
+
+ @Schema(title = "指定代码库别名", required = false)
+ private String repoName;
+
+ @Override
+ public String getClassType() {
+ return classType;
+ }
+
+ private boolean isOldExpress() {
+ return (newExpression == null || newExpression.isEmpty()) &&
+ (advanceExpression == null || advanceExpression.isEmpty());
+ }
+
+ private String checkAndSetSecond(String expression) {
+ String trimmedExpression = expression.trim();
+ String[] expressionParts = trimmedExpression.split(" ");
+ if (!"0".equals(expressionParts[0])) {
+ List newExpressionParts = Arrays.asList(expressionParts);
+ newExpressionParts.set(0, "0");
+ return String.join(" ", newExpressionParts);
+ }
+ return trimmedExpression;
+ }
+
+ @Override
+ public String findFirstTaskIdByStartType(StartType startType) {
+ return StartType.TIME_TRIGGER.name().equals(startType.name()) ? this.id : super.findFirstTaskIdByStartType(startType);
+ }
+
+ public boolean enableRepoConfig() {
+ return TriggerRepositoryType.SELF.equals(repositoryType) ||
+ (TriggerRepositoryType.ID.equals(repositoryType) && repoHashId != null && !repoHashId.isBlank()) ||
+ (TriggerRepositoryType.NAME.equals(repositoryType) && repoName != null && !repoName.isBlank());
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/WebHookTriggerElement.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/WebHookTriggerElement.java
new file mode 100644
index 00000000..a627f4d6
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/WebHookTriggerElement.java
@@ -0,0 +1,35 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger;
+
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger
+ * @Project:ops-pro
+ * @name:WebHookTriggerElement
+ * @Date:2025/03/27 9:59
+ * @Filename:WebHookTriggerElement
+ * @description:Todo
+ */
+@Data
+@Accessors(chain = true)
+@Schema(title = "Webhook基础类")
+public abstract class WebHookTriggerElement extends Element {
+ public WebHookTriggerElement(String name, String id, String status) {
+ super(name, id, status);
+ }
+
+ public List triggerCondition() {
+ return List.of();
+ }
+
+ public String joinToString(List list) {
+ return list == null || list.isEmpty() ? "" : String.join(",", list);
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/CodeEventType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/CodeEventType.java
new file mode 100644
index 00000000..0d4b47c6
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/CodeEventType.java
@@ -0,0 +1,103 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger.enums;
+
+import cd.casic.ci.common.api.enums.ScmType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger.enums
+ * @Project:ops-pro
+ * @name:CodeEventType
+ * @Date:2025/03/27 10:26
+ * @Filename:CodeEventType
+ * @description:Todo
+ */
+public enum CodeEventType {
+ // Git events
+ PUSH,
+ TAG_PUSH,
+ MERGE_REQUEST,
+ MERGE_REQUEST_ACCEPT,
+ ISSUES,
+ NOTE,
+ REVIEW,
+ // GitHub events
+ CREATE,
+ PULL_REQUEST,
+ // SVN events
+ POST_COMMIT,
+ LOCK_COMMIT,
+ PRE_COMMIT,
+ // Perforce (P4) events
+ CHANGE_COMMIT,
+ PUSH_SUBMIT,
+ CHANGE_CONTENT,
+ CHANGE_SUBMIT,
+ PUSH_CONTENT,
+ PUSH_COMMIT,
+ FIX_ADD,
+ FIX_DELETE,
+ FORM_COMMIT,
+ SHELVE_COMMIT,
+ SHELVE_DELETE,
+ SHELVE_SUBMIT,
+
+ // Sub-pipeline
+ PARENT_PIPELINE;
+
+ public static final String MESSAGE_CODE_PREFIX = "EVENT_TYPE";
+
+ // Git events
+ public static final List CODE_GIT_EVENTS = List.of(
+ PUSH, MERGE_REQUEST, MERGE_REQUEST_ACCEPT, TAG_PUSH, NOTE, REVIEW, ISSUES
+ );
+
+ // GitHub events
+ public static final List CODE_GITHUB_EVENTS = List.of(
+ PUSH, PULL_REQUEST, CREATE, REVIEW, ISSUES, NOTE
+ );
+
+ // Perforce (P4) events
+ public static final List CODE_P4_EVENTS = List.of(
+ CHANGE_COMMIT, CHANGE_SUBMIT, CHANGE_CONTENT, SHELVE_COMMIT, SHELVE_SUBMIT
+ );
+
+ // GitLab events
+ public static final List CODE_GITLAB_EVENTS = List.of(
+ PUSH, MERGE_REQUEST, MERGE_REQUEST_ACCEPT, TAG_PUSH
+ );
+
+ // Tencent Git (TGit) events
+ public static final List CODE_TGIT_EVENTS = List.of(
+ PUSH, MERGE_REQUEST, MERGE_REQUEST_ACCEPT, TAG_PUSH, NOTE, ISSUES
+ );
+
+ // SVN events
+ public static final List CODE_SVN_EVENTS = List.of(
+ POST_COMMIT, PRE_COMMIT, LOCK_COMMIT
+ );
+
+ public static List getEventsByScmType(ScmType scmType) {
+ if (scmType == null) {
+ return List.of(values());
+ }
+ switch (scmType) {
+ case CODE_GIT:
+ return new ArrayList<>(CODE_GIT_EVENTS);
+ case CODE_TGIT:
+ return new ArrayList<>(CODE_TGIT_EVENTS);
+ case GITHUB:
+ return new ArrayList<>(CODE_GITHUB_EVENTS);
+ case CODE_GITLAB:
+ return new ArrayList<>(CODE_GITLAB_EVENTS);
+ case CODE_SVN:
+ return new ArrayList<>(CODE_SVN_EVENTS);
+ case CODE_P4:
+ return new ArrayList<>(CODE_P4_EVENTS);
+ default:
+ return List.of(values());
+ }
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/CodeType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/CodeType.java
new file mode 100644
index 00000000..bc1caa2d
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/CodeType.java
@@ -0,0 +1,19 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger.enums;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger.enums
+ * @Project:ops-pro
+ * @name:CodeType
+ * @Date:2025/03/27 10:28
+ * @Filename:CodeType
+ * @description:Todo
+ */
+public enum CodeType {
+ SVN,
+ GIT,
+ GITLAB,
+ GITHUB,
+ TGIT,
+ P4
+}
\ No newline at end of file
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/PathFilterType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/PathFilterType.java
new file mode 100644
index 00000000..a6f6d86b
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/element/trigger/enums/PathFilterType.java
@@ -0,0 +1,15 @@
+package cd.casic.ci.common.pipeline.pojo.element.trigger.enums;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.element.trigger.enums
+ * @Project:ops-pro
+ * @name:PathFilterType
+ * @Date:2025/03/27 10:28
+ * @Filename:PathFilterType
+ * @description:Todo
+ */
+public enum PathFilterType {
+ NamePrefixFilter,
+ RegexBasedFilter
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/git/GitPullMode.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/git/GitPullMode.java
new file mode 100644
index 00000000..e03d5b75
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/pojo/git/GitPullMode.java
@@ -0,0 +1,21 @@
+package cd.casic.ci.common.pipeline.pojo.git;
+
+import cd.casic.ci.common.pipeline.enums.GitPullModeType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.pojo.git
+ * @Project:ops-pro
+ * @name:GitPullMode
+ * @Date:2025/03/27 10:24
+ * @Filename:GitPullMode
+ * @description:Todo
+ */
+@Data
+@AllArgsConstructor
+public class GitPullMode {
+ private GitPullModeType type;
+ private String value;
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/BuildType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/BuildType.java
new file mode 100644
index 00000000..33b57cfd
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/BuildType.java
@@ -0,0 +1,45 @@
+package cd.casic.ci.common.pipeline.type;
+
+import cn.hutool.http.useragent.OS;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type
+ * @Project:ops-pro
+ * @name:BuildType
+ * @Date:2025/03/27 10:45
+ * @Filename:BuildType
+ * @description:Todo
+ */
+@Getter
+@AllArgsConstructor
+public enum BuildType {
+ ESXI("蓝盾公共构建资源", List.of(OS.MACOS), false, false, false),
+ MACOS("云托管: MacOS on DevCloud", List.of(OS.MACOS), false, false, false),
+ WINDOWS("云托管:Windows on DevCloud", List.of(OS.WINDOWS), false, false, false),
+ KUBERNETES("Kubernetes构建资源", List.of(OS.LINUX), false, false, false),
+ PUBLIC_DEVCLOUD("公共:Docker on DevCloud", List.of(OS.LINUX), true, false, false),
+ PUBLIC_BCS("公共:Docker on Bcs", List.of(OS.LINUX), false, false, false),
+ THIRD_PARTY_AGENT_ID("私有:单构建机", List.of(OS.MACOS, OS.LINUX, OS.WINDOWS), false, true, true),
+ THIRD_PARTY_AGENT_ENV("私有:构建集群", List.of(OS.MACOS, OS.LINUX, OS.WINDOWS), false, true, true),
+ THIRD_PARTY_PCG("PCG公共构建资源", List.of(OS.LINUX), false, false, false),
+ THIRD_PARTY_DEVCLOUD("腾讯自研云(云devnet资源)", List.of(OS.LINUX), false, false, false),
+ GIT_CI("工蜂CI", List.of(OS.LINUX), false, false, false),
+ DOCKER("Docker公共构建机", List.of(OS.LINUX), true, true, true),
+ STREAM("stream", List.of(OS.LINUX), false, false, false),
+ AGENT_LESS("无编译环境", List.of(OS.LINUX), false, false, false);
+
+ private final String value;
+ private final List osList;
+ private final boolean enableApp;
+ private final boolean clickable;
+ private final boolean visible;
+
+ public String getI18n(String language) {
+ return MessageUtil.getMessageByLocale("buildType." + this.name(), language);
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/DispatchRouteKeySuffix.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/DispatchRouteKeySuffix.java
new file mode 100644
index 00000000..7a076a49
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/DispatchRouteKeySuffix.java
@@ -0,0 +1,34 @@
+package cd.casic.ci.common.pipeline.type;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type
+ * @Project:ops-pro
+ * @name:DispatchRouteKeySuffix
+ * @Date:2025/03/27 10:45
+ * @Filename:DispatchRouteKeySuffix
+ * @description:Todo
+ */
+@Getter
+@AllArgsConstructor
+public enum DispatchRouteKeySuffix {
+ DOCKER_VM(".docker.vm"),
+ DOCKER_VM_DEMOTE(".docker.vm.demote"),
+ KUBERNETES(".kubernetes"),
+ KUBERNETES_DEMOTE(".kubernetes.demote"),
+ PCG(".pcg.sumeru"),
+ DEVCLOUD(".devcloud.public"),
+ BCS(".bcs.public"),
+ IDC(".idc.public"),
+ GITCI(".gitci.public"),
+ STREAM(".stream.docker"),
+ STREAM_DEMOTE(".stream.docker.demote"),
+ CODECC(".codecc.scan"),
+ MACOS(".macos"),
+ WINDOWS(".windows");
+
+ private final String routeKeySuffix;
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/DispatchType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/DispatchType.java
new file mode 100644
index 00000000..8e5a8106
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/DispatchType.java
@@ -0,0 +1,47 @@
+package cd.casic.ci.common.pipeline.type;
+
+import cd.casic.ci.common.pipeline.type.agent.ThirdPartyAgentEnvDispatchType;
+import cd.casic.ci.common.pipeline.type.agent.ThirdPartyAgentIDDispatchType;
+import cd.casic.ci.common.pipeline.utils.EnvUtils;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Map;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type
+ * @Project:ops-pro
+ * @name:DispatchType
+ * @Date:2025/03/27 10:45
+ * @Filename:DispatchType
+ * @description:Todo
+ */
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "buildType", visible = false)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = DockerDispatchType.class, name = "DOCKER"),
+ @JsonSubTypes.Type(value = KubernetesDispatchType.class, name = "KUBERNETES"),
+ @JsonSubTypes.Type(value = ThirdPartyAgentIDDispatchType.class, name = "THIRD_PARTY_AGENT_ID"),
+ @JsonSubTypes.Type(value = ThirdPartyAgentEnvDispatchType.class, name = "THIRD_PARTY_AGENT_ENV"),
+ @JsonSubTypes.Type(value = ThirdPartyDevCloudDispatchType.class, name = "THIRD_PARTY_DEVCLOUD")
+})
+@Getter
+@Setter
+public abstract class DispatchType {
+ private String value;
+ private DispatchRouteKeySuffix routeKeySuffix;
+
+ public void replaceVariable(Map variables) {
+ this.value = EnvUtils.parseEnv(value, variables);
+ replaceField(variables);
+ }
+
+ public abstract BuildType buildType();
+
+ protected abstract void replaceField(Map variables);
+
+ public abstract void cleanDataBeforeSave();
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/StoreDispatchType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/StoreDispatchType.java
new file mode 100644
index 00000000..dcf7f8b6
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/StoreDispatchType.java
@@ -0,0 +1,55 @@
+package cd.casic.ci.common.pipeline.type;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Optional;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type
+ * @Project:ops-pro
+ * @name:StoreDispatchType
+ * @Date:2025/03/27 10:45
+ * @Filename:StoreDispatchType
+ * @description:Todo
+ */
+@Getter
+@Setter
+public abstract class StoreDispatchType extends DispatchType {
+ @Schema(title = "docker构建版本", required = false)
+ private String dockerBuildVersion;
+
+ @Schema(title = "镜像类型", required = false)
+ private ImageType imageType = ImageType.BKDEVOPS;
+
+ @Schema(title = "凭证id", required = false)
+ private String credentialId = "";
+
+ @Schema(title = "凭证项目id", required = false)
+ private String credentialProject = "";
+
+ @Schema(title = "商店镜像代码", required = false)
+ private String imageCode = "";
+
+ @Schema(title = "商店镜像版本", required = false)
+ private String imageVersion = "";
+
+ @Schema(title = "商店镜像名称", required = false)
+ private String imageName = "";
+
+ @Schema(title = "商店镜像公共标识", required = false)
+ private Boolean imagePublicFlag = false;
+
+ @Schema(title = "商店镜像研发来源", required = false)
+ private String imageRDType = "";
+
+ @Schema(title = "商店镜像是否推荐", required = false)
+ private Boolean recommendFlag = true;
+
+ public StoreDispatchType(String dockerBuildVersion, DispatchRouteKeySuffix routeKeySuffix) {
+ super(Optional.ofNullable(dockerBuildVersion).orElse("StoreDispatchType empty image"), routeKeySuffix);
+ this.dockerBuildVersion = dockerBuildVersion;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/AgentType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/AgentType.java
new file mode 100644
index 00000000..d70392dc
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/AgentType.java
@@ -0,0 +1,25 @@
+package cd.casic.ci.common.pipeline.type.agent;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type.agent
+ * @Project:ops-pro
+ * @name:AgentType
+ * @Date:2025/03/27 10:47
+ * @Filename:AgentType
+ * @description:Todo
+ */
+@Getter
+@AllArgsConstructor
+public enum AgentType {
+ ID, // This is only for old pipeline, new pipelines will use name
+ NAME,
+ REUSE_JOB_ID; // 是否复用其他job的Agent节点
+
+ public boolean isReuse() {
+ return this == REUSE_JOB_ID;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentDispatch.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentDispatch.java
new file mode 100644
index 00000000..5d9a8160
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentDispatch.java
@@ -0,0 +1,60 @@
+package cd.casic.ci.common.pipeline.type.agent;
+
+import cd.casic.ci.common.pipeline.type.DispatchType;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Map;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type.agent
+ * @Project:ops-pro
+ * @name:ThirdPartyAgentDispatch
+ * @Date:2025/03/27 10:47
+ * @Filename:ThirdPartyAgentDispatch
+ * @description:Todo
+ */
+@Getter
+@Setter
+@JsonIgnoreProperties(ignoreUnknown = true)
+public abstract class ThirdPartyAgentDispatch extends DispatchType {
+ private String value;
+ private AgentType agentType;
+ private String workspace;
+ private ThirdPartyAgentDockerInfo dockerInfo;
+ private ReusedInfo reusedInfo;
+
+ public ThirdPartyAgentDispatch(String value, AgentType agentType, String workspace, ThirdPartyAgentDockerInfo dockerInfo, ReusedInfo reusedInfo) {
+ super(value);
+ this.value = value;
+ this.agentType = agentType;
+ this.workspace = workspace;
+ this.dockerInfo = dockerInfo;
+ this.reusedInfo = reusedInfo;
+ }
+
+ public boolean idType() {
+ return (agentType == AgentType.ID) || (reusedInfo != null && reusedInfo.getAgentType() == AgentType.ID) ||
+ (agentType == AgentType.REUSE_JOB_ID && reusedInfo == null);
+ }
+
+ public boolean hasReuseMutex() {
+ return this.agentType.isReuse() || this.reusedInfo != null;
+ }
+
+ public boolean isEnv() {
+ return this instanceof ThirdPartyAgentEnvDispatchType;
+ }
+
+ public boolean isSingle() {
+ return this instanceof ThirdPartyAgentIDDispatchType;
+ }
+
+ @Override
+ public abstract void replaceField(Map variables);
+
+ @Override
+ public abstract void cleanDataBeforeSave();
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentDockerInfo.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentDockerInfo.java
new file mode 100644
index 00000000..e5d549c7
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentDockerInfo.java
@@ -0,0 +1,112 @@
+package cd.casic.ci.common.pipeline.type.agent;
+
+import cd.casic.ci.common.pipeline.utils.EnvUtils;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type.agent
+ * @Project:ops-pro
+ * @name:ThirdPartyAgentDockerInfo
+ * @Date:2025/03/27 10:47
+ * @Filename:ThirdPartyAgentDockerInfo
+ * @description:Todo
+ */
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ThirdPartyAgentDockerInfo {
+ private String image;
+ private Credential credential;
+ private DockerOptions options;
+ private String imagePullPolicy;
+ private ImageType imageType = ImageType.THIRD;
+ private ThirdPartyAgentDockerInfoStoreImage storeImage;
+
+ public void replaceField(Map variables) {
+ image = EnvUtils.parseEnv(image, variables);
+ if (credential != null) {
+ if (!credential.getUser().isBlank()) {
+ credential.setUser(EnvUtils.parseEnv(credential.getUser(), variables));
+ }
+ if (!credential.getPassword().isBlank()) {
+ credential.setPassword(EnvUtils.parseEnv(credential.getPassword(), variables));
+ }
+ if (!credential.getCredentialId().isBlank()) {
+ credential.setCredentialId(EnvUtils.parseEnv(credential.getCredentialId(), variables));
+ }
+ }
+ if (options != null) {
+ options.setVolumes(options.getVolumes().stream().map(v -> EnvUtils.parseEnv(v, variables)).toList());
+ options.setMounts(options.getMounts().stream().map(m -> EnvUtils.parseEnv(m, variables)).toList());
+ options.setGpus(EnvUtils.parseEnv(options.getGpus(), variables));
+ options.setPrivileged(Boolean.parseBoolean(EnvUtils.parseEnv(String.valueOf(options.getPrivileged()), variables)));
+ }
+ if (imagePullPolicy != null) {
+ imagePullPolicy = EnvUtils.parseEnv(imagePullPolicy, variables);
+ }
+ }
+}
+
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+class Credential {
+ private String user;
+ private String password;
+ private String credentialId;
+ private String acrossTemplateId;
+ private String jobId;
+ private String credentialProjectId;
+}
+
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+class DockerOptions {
+ private List volumes;
+ private List mounts;
+ private String gpus;
+ private Boolean privileged;
+}
+
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+class ThirdPartyAgentDockerInfoStoreImage {
+ private String imageName;
+ private String imageCode;
+ private String imageVersion;
+}
+
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+class ThirdPartyAgentDockerInfoDispatch {
+ private String agentId;
+ private String secretKey;
+ private String image;
+ private Credential credential;
+ private DockerOptions options;
+ private String imagePullPolicy;
+
+ public ThirdPartyAgentDockerInfoDispatch(String agentId, String secretKey, ThirdPartyAgentDockerInfo info) {
+ this.agentId = agentId;
+ this.secretKey = secretKey;
+ this.image = info.getImage();
+ this.credential = info.getCredential();
+ this.options = info.getOptions();
+ this.imagePullPolicy = info.getImagePullPolicy();
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentEnvDispatchType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentEnvDispatchType.java
new file mode 100644
index 00000000..9d906c36
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentEnvDispatchType.java
@@ -0,0 +1,63 @@
+package cd.casic.ci.common.pipeline.type.agent;
+
+import cd.casic.ci.common.pipeline.type.BuildType;
+import cd.casic.ci.common.pipeline.utils.EnvUtils;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Map;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type.agent
+ * @Project:ops-pro
+ * @name:ThirdPartyAgentEnvDispatchType
+ * @Date:2025/03/27 10:48
+ * @Filename:ThirdPartyAgentEnvDispatchType
+ * @description:Todo
+ */
+@Getter
+@Setter
+public class ThirdPartyAgentEnvDispatchType extends ThirdPartyAgentDispatch {
+ @JsonProperty("value")
+ private String envName;
+ private String workspace;
+ private String envProjectId;
+ private AgentType agentType = AgentType.NAME;
+ private ThirdPartyAgentDockerInfo dockerInfo;
+ private ReusedInfo reusedInfo;
+
+ public ThirdPartyAgentEnvDispatchType(String envName, String workspace, String envProjectId, ThirdPartyAgentDockerInfo dockerInfo, ReusedInfo reusedInfo) {
+ super(envName, agentType, workspace, dockerInfo, reusedInfo);
+ this.envName = envName;
+ this.workspace = workspace;
+ this.envProjectId = envProjectId;
+ this.dockerInfo = dockerInfo;
+ this.reusedInfo = reusedInfo;
+ }
+
+ @Override
+ public void cleanDataBeforeSave() {
+ this.envName = this.envName.trim();
+ this.envProjectId = this.envProjectId != null ? this.envProjectId.trim() : null;
+ this.workspace = this.workspace != null ? this.workspace.trim() : null;
+ }
+
+ @Override
+ public void replaceField(Map variables) {
+ envName = EnvUtils.parseEnv(envName, variables);
+ envProjectId = EnvUtils.parseEnv(envProjectId, variables);
+ if (workspace != null && !workspace.isBlank()) {
+ workspace = EnvUtils.parseEnv(workspace, variables);
+ }
+ if (dockerInfo != null) {
+ dockerInfo.replaceField(variables);
+ }
+ }
+
+ @Override
+ public BuildType buildType() {
+ return BuildType.THIRD_PARTY_AGENT_ENV;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentIDDispatchType.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentIDDispatchType.java
new file mode 100644
index 00000000..d342c175
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/agent/ThirdPartyAgentIDDispatchType.java
@@ -0,0 +1,59 @@
+package cd.casic.ci.common.pipeline.type.agent;
+
+import cd.casic.ci.common.pipeline.type.BuildType;
+import cd.casic.ci.common.pipeline.utils.EnvUtils;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Map;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type.agent
+ * @Project:ops-pro
+ * @name:ThirdPartyAgentIDDispatchType
+ * @Date:2025/03/27 10:48
+ * @Filename:ThirdPartyAgentIDDispatchType
+ * @description:Todo
+ */
+@Getter
+@Setter
+public class ThirdPartyAgentIDDispatchType extends ThirdPartyAgentDispatch {
+ @JsonProperty("value")
+ private String displayName;
+ private String workspace;
+ private AgentType agentType = AgentType.NAME;
+ private ThirdPartyAgentDockerInfo dockerInfo;
+ private ReusedInfo reusedInfo;
+
+ public ThirdPartyAgentIDDispatchType(String displayName, String workspace, ThirdPartyAgentDockerInfo dockerInfo, ReusedInfo reusedInfo) {
+ super(displayName, agentType, workspace, dockerInfo, reusedInfo);
+ this.displayName = displayName;
+ this.workspace = workspace;
+ this.dockerInfo = dockerInfo;
+ this.reusedInfo = reusedInfo;
+ }
+
+ @Override
+ public void cleanDataBeforeSave() {
+ this.displayName = this.displayName.trim();
+ this.workspace = this.workspace != null ? this.workspace.trim() : null;
+ }
+
+ @Override
+ public void replaceField(Map variables) {
+ displayName = EnvUtils.parseEnv(displayName, variables);
+ if (workspace != null && !workspace.isBlank()) {
+ workspace = EnvUtils.parseEnv(workspace, variables);
+ }
+ if (dockerInfo != null) {
+ dockerInfo.replaceField(variables);
+ }
+ }
+
+ @Override
+ public BuildType buildType() {
+ return BuildType.THIRD_PARTY_AGENT_ID;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/package-info.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/package-info.java
new file mode 100644
index 00000000..6681d11c
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/type/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.type
+ * @Project:ops-pro
+ * @name:package-info
+ * @Date:2025/03/27 10:44
+ * @Filename:package-info
+ * @description:Todo
+ */
+package cd.casic.ci.common.pipeline.type;
\ No newline at end of file
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/EnvUtils.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/EnvUtils.java
new file mode 100644
index 00000000..f0744074
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/EnvUtils.java
@@ -0,0 +1,79 @@
+package cd.casic.ci.common.pipeline.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.common.pipeline.utils
+ * @Project:ops-pro
+ * @name:EnvUtils
+ * @Date:2025/03/27 15:20
+ * @Filename:EnvUtils
+ * @description:Todo
+ */
+public class EnvUtils {
+ private static final Pattern tPattern = Pattern.compile("(\\$[{](?[^$^{}]+)})|(\\$[{]{2}(?[^$^{}]+)[}]{2})");
+
+ public static String parseEnv(String command, Map data) {
+ return parseEnv(command, data, false, false);
+ }
+
+ public static String parseEnv(String command, Map data, boolean replaceWithEmpty, boolean isEscape) {
+ return parseEnv(command, data, replaceWithEmpty, isEscape, new HashMap<>());
+ }
+
+ public static String parseEnv(String command, Map data, boolean replaceWithEmpty, boolean isEscape, Map contextMap) {
+ if (command == null || command.isEmpty()) {
+ return command == null ? "" : command;
+ }
+ return parseTokenTwice(command, data, contextMap, replaceWithEmpty, isEscape, 1);
+ }
+
+ private static String parseTokenTwice(String command, Map data, Map contextMap, boolean replaceWithEmpty, boolean isEscape, int depth) {
+ if (depth < 0) {
+ return command;
+ }
+ Matcher matcher = tPattern.matcher(command);
+ StringBuffer buff = new StringBuffer();
+ while (matcher.find()) {
+ String key = matcher.group("single");
+ if (key == null) {
+ key = matcher.group("double");
+ }
+ key = key.trim();
+ String value = data.get(key);
+ if (value == null && contextMap != null) {
+ value = contextMap.get(key);
+ }
+ if (value == null) {
+ value = !replaceWithEmpty ? matcher.group() : "";
+ } else {
+ if (depth > 0 && tPattern.matcher(value).find()) {
+ value = parseTokenTwice(value, data, contextMap, replaceWithEmpty, isEscape, depth - 1);
+ } else if (isEscape) {
+ value = escapeSpecialWord(value);
+ }
+ }
+ matcher.appendReplacement(buff, Matcher.quoteReplacement(value));
+ }
+ matcher.appendTail(buff);
+ return buff.toString();
+ }
+
+ private static String escapeSpecialWord(String keyword) {
+ String replaceWord = keyword;
+ if (!keyword.isEmpty()) {
+ String[] wordList = {"\\", "\""};
+ for (String word : wordList) {
+ if (replaceWord.contains(word)) {
+ replaceWord = replaceWord.replace(word, "\\" + word);
+ }
+ }
+ }
+ return replaceWord;
+ }
+}
\ No newline at end of file
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ModelUtils.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ModelUtils.java
index 51bbd88b..1aa0837f 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ModelUtils.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ModelUtils.java
@@ -8,10 +8,16 @@ import cd.casic.ci.common.pipeline.container.VMBuildContainer;
import cd.casic.ci.common.pipeline.enums.BuildStatus;
import cd.casic.ci.common.pipeline.enums.JobRunCondition;
import cd.casic.ci.common.pipeline.option.JobControlOption;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
+import cd.casic.ci.common.pipeline.pojo.element.ElementAdditionalOptions;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.ManualTriggerElement;
+import cd.casic.ci.common.pipeline.pojo.element.trigger.RemoteTriggerElement;
import cd.casic.framework.commons.util.reflect.ReflectUtil;
import java.util.*;
+import static cd.casic.ci.common.pipeline.pojo.element.ElementAdditionalOptions.RunCondition.*;
+
/**
* @Author:mianbin
* @Package:cd.casic.ci.common.pipeline.utils
@@ -99,9 +105,9 @@ public class ModelUtils {
} else {
element.setCanRetry(null);
}
- } else if (additionalOptions.getRunCondition() == RunCondition.PRE_TASK_FAILED_ONLY ||
- additionalOptions.getRunCondition() == RunCondition.PRE_TASK_FAILED_BUT_CANCEL ||
- additionalOptions.getRunCondition() == RunCondition.PRE_TASK_FAILED_EVEN_CANCEL) {
+ } else if (additionalOptions.getRunCondition() == PRE_TASK_FAILED_ONLY ||
+ additionalOptions.getRunCondition() == PRE_TASK_FAILED_BUT_CANCEL ||
+ additionalOptions.getRunCondition() == PRE_TASK_FAILED_EVEN_CANCEL) {
element.setCanRetry(null);
element.setCanSkip(null);
failElements.forEach(e -> {
@@ -166,8 +172,8 @@ public class ModelUtils {
public static Set getModelAtoms(Model model) {
var atomCodes = new HashSet();
for (var stage : model.getStages()) {
- for (var container : stage.getContainers()) {
- for (var element : container.getElements()) {
+ for (Container container : stage.getContainers()) {
+ for (Element element : container.getElements()) {
atomCodes.add(element.getAtomCode());
}
}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ObjectReplaceEnvVarUtil.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ObjectReplaceEnvVarUtil.java
new file mode 100644
index 00000000..681d090b
--- /dev/null
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ObjectReplaceEnvVarUtil.java
@@ -0,0 +1,139 @@
+/*
+ * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license.
+ *
+ * A copy of the MIT License is included in this file.
+ *
+ *
+ * Terms of the MIT License:
+ * ---------------------------------------------------
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+ * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package cd.casic.ci.common.pipeline.utils;
+
+import cn.hutool.json.JSONUtil;
+
+import java.util.*;
+
+public class ObjectReplaceEnvVarUtil {
+ /**
+ * 把对象字段值中的占位符替换成环境变量
+ *
+ * @param obj 需要把占位符替换环境变量的对象(对象如果是集合对象,注意要选择支持增加、删除等操作的集合类型,不要选择类似SingletonMap这种)
+ * @param envMap 环境变量Map
+ * @return 变量替换后的对象
+ */
+ @SuppressWarnings("all")
+ public static Object replaceEnvVar(Object obj, Map envMap) {
+ if (obj instanceof Map) {
+ // 递归替换map对象中的变量
+ Set> entrySet = ((Map) obj).entrySet();
+ for (Map.Entry entry : entrySet) {
+ Object value = entry.getValue();
+ if (!isNormalReplaceEnvVar(value)) {
+ entry.setValue(replaceEnvVar(value, envMap));
+ } else {
+ entry.setValue(handleNormalEnvVar(value, envMap));
+ }
+ }
+ } else if (obj instanceof List) {
+ // 递归替换list对象中的变量
+ List dataList = (List) obj;
+ for (int i = 0; i < dataList.size(); i++) {
+ Object value = dataList.get(i);
+ if (!isNormalReplaceEnvVar(value)) {
+ dataList.set(i, replaceEnvVar(value, envMap));
+ } else {
+ dataList.set(i, handleNormalEnvVar(value, envMap));
+ }
+ }
+ } else if (obj instanceof Set) {
+ // 递归替换set对象中的变量
+ Set objSet = (Set) obj;
+ Set replaceObjSet = new HashSet(objSet);
+ Iterator it = replaceObjSet.iterator();
+ while (it.hasNext()) {
+ Object value = it.next();
+ objSet.remove(value);
+ if (!isNormalReplaceEnvVar(value)) {
+ objSet.add(replaceEnvVar(value, envMap));
+ } else {
+ objSet.add(handleNormalEnvVar(value, envMap));
+ }
+ }
+ } else if (isNormalReplaceEnvVar(obj)) {
+ // 替换基本类型对象或字符串对象中的变量
+ obj = handleNormalEnvVar(obj, envMap);
+ } else {
+ try {
+ // 把对象转换成map后进行递归替换变量
+ Map dataMap = JSONUtil.toBean(JSONUtil.toJsonStr(obj), Map.class);
+ replaceEnvVar(dataMap, envMap);
+ obj = JSONUtil.toBean(JSONUtil.toJsonStr(dataMap), obj.getClass());
+ } catch (Throwable e) {
+ // 转换不了map的对象则进行直接替换
+ obj = EnvUtils.parseEnv(JSONUtil.toJsonStr(obj), envMap, false, false);
+ }
+ }
+ return obj;
+ }
+
+ private static Object handleNormalEnvVar(Object obj, Map envMap) {
+ // 只有字符串参数才需要进行变量替换,其它基本类型参数无需进行变量替换
+ if (obj instanceof String) {
+ String objStr = ((String) obj).trim();
+ if (JSONUtil.isJsonObj(objStr)) {
+ try {
+ Object dataObj = JSONUtil.toBean((String) obj, Map.class);
+ // string能正常转换成map,则说明是json串,那么把dataObj进行递归替换变量后再转成json串
+ dataObj = replaceEnvVar(dataObj, envMap);
+ obj = JSONUtil.toJsonStr(dataObj);
+ } catch (Throwable e) {
+ // 转换不了map的字符串对象则直接替换
+ obj = EnvUtils.parseEnv(JSONUtil.toJsonStr(obj), envMap, false, false);
+ }
+ } else if (JSONUtil.isJsonObj(objStr)) {
+ try {
+ JSONUtil.toList(JSONUtil.parseArray((String) obj), Object.class);
+ Object dataObj = JSONUtil.toList((String) obj, List.class);
+ // string能正常转成list,说明是json串,把dataObj进行递归替换变量后再转成json串
+ dataObj = replaceEnvVar(dataObj, envMap);
+ obj = JSONUtil.toJsonStr(dataObj);
+ } catch (Throwable e1) {
+ // 转换不了list的字符串对象则直接替换
+ obj = EnvUtils.parseEnv(JSONUtil.toJsonStr(obj), envMap, false, false);
+ }
+ } else {
+ // 转换不了map或者list的字符串对象则直接替换
+ obj = EnvUtils.parseEnv(JSONUtil.toJsonStr(obj), envMap, false, false);
+ }
+ }
+ return obj;
+ }
+
+ /**
+ * 判断对象是否是普通替换对象
+ *
+ * @param obj 需要把占位符替换环境变量的对象(对象如果是集合对象,注意要选择支持增加、删除等操作的集合类型,不要选择类似SingletonMap这种)
+ * @return 是否是普通替换对象
+ */
+ private static Boolean isNormalReplaceEnvVar(Object obj) {
+ return obj == null || ReflectUtil.INSTANCE.isNativeType(obj) || obj instanceof String;
+ }
+}
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ParameterUtils.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ParameterUtils.java
index ced956ca..fc40b818 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ParameterUtils.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/ParameterUtils.java
@@ -1,6 +1,7 @@
package cd.casic.ci.common.pipeline.utils;
import cd.casic.ci.common.pipeline.pojo.BuildParameters;
+import cd.casic.ci.common.pipeline.pojo.element.Element;
import cd.casic.framework.commons.util.json.JsonUtils;
import java.util.List;
diff --git a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/TriggerElementPropUtils.java b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/TriggerElementPropUtils.java
index c3f0d1e0..7a1c11d3 100644
--- a/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/TriggerElementPropUtils.java
+++ b/modules/ci-commons/common-pipeline/src/main/java/cd/casic/ci/common/pipeline/utils/TriggerElementPropUtils.java
@@ -1,5 +1,7 @@
package cd.casic.ci.common.pipeline.utils;
+import cd.casic.ci.common.pipeline.pojo.element.ElementProp;
+
import java.util.List;
/**
@@ -17,20 +19,20 @@ public class TriggerElementPropUtils {
if (value == null || value.isBlank()) {
return null;
}
- return new ElementProp(name, value.split(","), ElementPropType.VUEX_INPUT);
+ return new ElementProp(name, value.split(","), ElementProp.ElementPropType.VUEX_INPUT);
}
public static ElementProp staffInput(String name, List value) {
if (value == null || value.isEmpty()) {
return null;
}
- return new ElementProp(name, value, ElementPropType.STAFF_INPUT);
+ return new ElementProp(name, value, ElementProp.ElementPropType.STAFF_INPUT);
}
public static ElementProp selector(String name, List value) {
if (value == null || value.isEmpty()) {
return null;
}
- return new ElementProp(name, value, ElementPropType.SELECTOR);
+ return new ElementProp(name, value, ElementProp.ElementPropType.SELECTOR);
}
}
diff --git a/modules/ci-process/pipeline-ci-process-api/pom.xml b/modules/ci-process/pipeline-ci-process-api/pom.xml
index 190442fd..ff8363c1 100644
--- a/modules/ci-process/pipeline-ci-process-api/pom.xml
+++ b/modules/ci-process/pipeline-ci-process-api/pom.xml
@@ -22,7 +22,11 @@
cd.casic.ci
- ci-commons
+ commons-api
+
+
+ cd.casic.ci
+ commons-pipeline
cd.casic.ci
diff --git a/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/Constants.java b/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/Constants.java
new file mode 100644
index 00000000..ceef36e7
--- /dev/null
+++ b/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/Constants.java
@@ -0,0 +1,143 @@
+package cd.casic.ci.process.api.process.utils;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.process.api.process.utils
+ * @Project:ops-pro
+ * @name:Constants
+ * @Date:2025/03/27 11:09
+ * @Filename:Constants
+ */
+public class Constants {
+ public static final String PIPELINE_VERSION = "BK_CI_PIPELINE_VERSION";
+ public static final String PIPELINE_START_PARENT_PROJECT_ID = "BK_CI_PARENT_PROJECT_ID";
+ public static final String PIPELINE_START_PARENT_PIPELINE_ID = "BK_CI_PARENT_PIPELINE_ID";
+ public static final String PIPELINE_START_PARENT_PIPELINE_NAME = "BK_CI_PARENT_PIPELINE_NAME";
+ public static final String PIPELINE_START_PARENT_BUILD_ID = "BK_CI_PARENT_BUILD_ID";
+ public static final String PIPELINE_START_PARENT_BUILD_NUM = "BK_CI_PARENT_BUILD_NUM";
+ public static final String PIPELINE_START_PARENT_BUILD_TASK_ID = "BK_CI_PARENT_BUILD_TASK_ID";
+ public static final String PIPELINE_START_PARENT_EXECUTE_COUNT = "BK_CI_PARENT_EXECUTE_COUNT";
+ public static final String PIPELINE_START_USER_ID = "BK_CI_START_USER_ID";
+ public static final String PIPELINE_START_USER_NAME = "BK_CI_START_USER_NAME";
+ public static final String PIPELINE_START_WEBHOOK_USER_ID = "BK_CI_START_WEBHOOK_USER_ID";
+ public static final String PIPELINE_START_PIPELINE_USER_ID = "BK_CI_START_PIPELINE_USER_ID";
+ public static final String PIPELINE_START_SERVICE_USER_ID = "BK_CI_START_SERVICE_USER_ID";
+ public static final String PIPELINE_START_MANUAL_USER_ID = "BK_CI_START_MANUAL_USER_ID";
+ public static final String PIPELINE_START_TIME_TRIGGER_USER_ID = "BK_CI_START_TIME_TRIGGER_USER_ID";
+ public static final String PIPELINE_START_REMOTE_USER_ID = "BK_CI_START_REMOTE_USER_ID";
+ public static final String PIPELINE_START_REMOTE_CLIENT_IP = "BK_CI_START_REMOTE_CLIENT_IP";
+ public static final String PIPELINE_START_TYPE = "BK_CI_START_TYPE";
+ public static final String PIPELINE_START_CHANNEL = "BK_CI_START_CHANNEL";
+ public static final String PIPELINE_BUILD_NUM = "BK_CI_BUILD_NUM";
+ public static final String PIPELINE_BUILD_LAST_UPDATE = "BK_CI_BUILD_LAST_UPDATE";
+ public static final String PIPELINE_BUILD_SVN_REVISION = "BK_CI_BUILD_SVN_REVISION";
+ public static final String PIPELINE_BUILD_NUM_ALIAS = "BK_CI_BUILD_NUM_ALIAS";
+ public static final String PIPELINE_BUILD_URL = "BK_CI_BUILD_URL";
+ public static final String PIPELINE_TIMER_DISABLE = "BK_CI_TIMER_DISABLE";
+ public static final String PIPELINE_START_SUB_RUN_MODE = "BK_CI_SUB_PIPELINE_RUN_MODE";
+
+ public static final String GIT_MR_NUMBER = "BK_CI_GIT_MR_NUMBER";
+ public static final String GITHUB_PR_NUMBER = "BK_CI_GITHUB_PR_NUMBER";
+
+ public static final String PIPELINE_NAME = "BK_CI_PIPELINE_NAME";
+ public static final String PIPELINE_ID = "BK_CI_PIPELINE_ID";
+ public static final String WORKSPACE = "WORKSPACE";
+
+ public static final String PIPELINE_TIME_DURATION = "BK_CI_BUILD_TOTAL_TIME";
+
+ public static final String PIPELINE_BUILD_ID = "BK_CI_BUILD_ID";
+ public static final String PIPELINE_VMSEQ_ID = "BK_CI_BUILD_JOB_ID";
+ public static final String PIPELINE_ELEMENT_ID = "BK_CI_BUILD_TASK_ID";
+ public static final String PIPELINE_TURBO_TASK_ID = "BK_CI_TURBO_ID";
+ public static final String PROJECT_NAME = "BK_CI_PROJECT_NAME";
+ public static final String REPORT_DYNAMIC_ROOT_URL = "BK_CI_REPORT_DYNAMIC_ROOT_URL";
+
+ public static final String PROJECT_NAME_CHINESE = "BK_CI_PROJECT_NAME_CN";
+
+ public static final String PIPELINE_START_MOBILE = "BK_CI_IS_MOBILE";
+
+ public static final String PIPELINE_START_TASK_ID = "BK_CI_START_TASK_ID";
+ public static final String PIPELINE_RETRY_COUNT = "BK_CI_RETRY_COUNT";
+ public static final String PIPELINE_RETRY_BUILD_ID = "BK_CI_RETRY_BUILD_ID";
+ public static final String PIPELINE_RETRY_START_TASK_ID = "BK_CI_RETRY_TASK_ID";
+ public static final String PIPELINE_RETRY_ALL_FAILED_CONTAINER = "BK_CI_RETRY_ALL_FAILED_CONTAINER";
+ public static final String PIPELINE_SKIP_FAILED_TASK = "BK_CI_SKIP_FAILED_TASK";
+
+ public static final String BK_CI_BUILD_FAIL_TASKS = "BK_CI_BUILD_FAIL_TASKS";
+ public static final String BK_CI_BUILD_FAIL_TASKNAMES = "BK_CI_BUILD_FAIL_TASKNAMES";
+
+ public static final String PIPELINE_VIEW_MY_PIPELINES = "myPipeline";
+ public static final String PIPELINE_VIEW_MY_LIST_PIPELINES = "myListPipeline";
+ public static final String PIPELINE_VIEW_FAVORITE_PIPELINES = "collect";
+ public static final String PIPELINE_VIEW_ALL_PIPELINES = "allPipeline";
+ public static final String PIPELINE_VIEW_UNCLASSIFIED = "unclassified";
+ public static final String PIPELINE_VIEW_RECENT_USE = "recentUse";
+
+ public static final String PIPELINE_MATERIAL_URL = "BK_CI_PIEPLEINE_MATERIAL_URL";
+ public static final String PIPELINE_MATERIAL_BRANCHNAME = "BK_CI_PIPELINE_MATERIAL_BRANCHNAME";
+ public static final String PIPELINE_MATERIAL_ALIASNAME = "BK_CI_PIPELINE_MATERIAL_ALIASNAME";
+ public static final String PIPELINE_MATERIAL_NEW_COMMIT_ID = "BK_CI_PIPELINE_MATERIAL_NEW_COMMIT_ID";
+ public static final String PIPELINE_MATERIAL_NEW_COMMIT_COMMENT = "BK_CI_PIPELINE_MATERIAL_NEW_COMMIT_COMMENT";
+ public static final String PIPELINE_MATERIAL_NEW_COMMIT_TIMES = "BK_CI_PIPELINE_MATERIAL_NEW_COMMIT_TIMES";
+
+ public static final String MAJORVERSION = "BK_CI_MAJOR_VERSION";
+ public static final String MINORVERSION = "BK_CI_MINOR_VERSION";
+ public static final String FIXVERSION = "BK_CI_FIX_VERSION";
+ public static final String BUILD_NO = "BK_CI_BUILD_NO";
+ public static final String BUILD_STATUS = "BK_CI_BUILD_STATUS";
+ public static final String BK_DOCKER_TARGE_IMAGE_TAG = "BK_DOCKER_TARGE_IMAGE_TAG";
+ public static final String BK_DOCKER_TARGE_IMAGE_NAME = "BK_DOCKER_TARGE_IMAGE_NAME";
+
+ public static final String JOB_RETRY_TASK_ID = "job.retry_task_id";
+
+ public static final String PIPELINE_CREATE_USER = "BK_CI_PIPELINE_CREATE_USER";
+ public static final String PIPELINE_UPDATE_USER = "BK_CI_PIPELINE_UPDATE_USER";
+ public static final String PIPELINE_BUILD_REMARK = "BK_CI_BUILD_REMARK";
+ public static final String PIPELINE_ATOM_NAME = "BK_CI_ATOM_NAME";
+ public static final String PIPELINE_ATOM_CODE = "BK_CI_ATOM_CODE";
+ public static final String PIPELINE_ATOM_VERSION = "BK_CI_ATOM_VERSION";
+ public static final String PIPELINE_TASK_NAME = "BK_CI_TASK_NAME";
+ public static final String PIPELINE_STEP_ID = "BK_CI_STEP_ID";
+ public static final String PIPELINE_ATOM_TIMEOUT = "BK_CI_ATOM_TIMEOUT";
+ public static final String PIPELINE_DIALECT = "BK_CI_PIPELINE_DIALECT";
+
+ public static final String BK_CI_MATERIAL_ID = "BK_CI_MATERIAL_ID";
+ public static final String BK_CI_MATERIAL_NAME = "BK_CI_MATERIAL_NAME";
+ public static final String BK_CI_MATERIAL_URL = "BK_CI_MATERIAL_URL";
+
+ public static final String BK_CI_AUTHORIZER = "BK_CI_AUTHORIZER";
+
+ public static final int PIPELINE_SETTING_MAX_QUEUE_SIZE_DEFAULT = 10;
+ public static final int TASK_FAIL_RETRY_MAX_COUNT = 5;
+ public static final int TASK_FAIL_RETRY_MIN_COUNT = 1;
+ public static final int PIPELINE_SETTING_MAX_QUEUE_SIZE_MIN = 0;
+ public static final int PIPELINE_SETTING_MAX_QUEUE_SIZE_MAX = 200;
+ public static final int PIPELINE_SETTING_MAX_CON_QUEUE_SIZE_DEFAULT = 50;
+ public static final int PIPELINE_SETTING_MAX_CON_QUEUE_SIZE_MAX = 200;
+ public static final int PIPELINE_SETTING_WAIT_QUEUE_TIME_MINUTE_DEFAULT = 1;
+ public static final int PIPELINE_SETTING_WAIT_QUEUE_TIME_MINUTE_MIN = 1;
+ public static final int PIPELINE_SETTING_WAIT_QUEUE_TIME_MINUTE_MAX = 1440;
+ public static final int PIPELINE_TASK_MESSAGE_STRING_LENGTH_MAX = 4000;
+ public static final int PIPELINE_MESSAGE_STRING_LENGTH_MAX = 30000;
+ public static final int PIPELINE_CON_RUNNING_CONTAINER_SIZE_MAX = 30;
+ public static final int PIPELINE_MATRIX_MAX_CON_RUNNING_SIZE_DEFAULT = 5;
+ public static final int PIPELINE_MATRIX_CON_RUNNING_SIZE_MAX = 20;
+ public static final int PIPELINE_STAGE_CONTAINERS_COUNT_MAX = 256;
+ public static final int PIPELINE_CONDITION_EXPRESSION_LENGTH_MAX = 512;
+ public static final int PIPELINE_VARIABLES_STRING_LENGTH_MAX = 4000;
+
+ public static final String PIPELINE_TIME_START = "BK_CI_BUILD_START_TIME";
+ public static final String PIPELINE_TIME_END = "BK_CI_BUILD_END_TIME";
+ public static final String PIPELINE_BUILD_MSG = "BK_CI_BUILD_MSG";
+
+ public static final int PIPELINE_RES_NUM_MIN = 50;
+
+ public static final String KEY_PIPELINE_ID = "pipelineId";
+ public static final String KEY_PIPELINE_NAME = "pipelineName";
+ public static final String KEY_PROJECT_ID = "projectId";
+ public static final String KEY_TEMPLATE_ID = "templateId";
+ public static final String KEY_STAGE = "stage";
+ public static final String KEY_JOB = "job";
+ public static final String KEY_TASK = "task";
+ public static final String KEY_TASK_ATOM = "taskAtom";
+}
diff --git a/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/CredentialUtils.java b/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/CredentialUtils.java
new file mode 100644
index 00000000..e4ca3f59
--- /dev/null
+++ b/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/CredentialUtils.java
@@ -0,0 +1,91 @@
+package cd.casic.ci.process.api.process.utils;
+
+import cd.casic.ci.log.scm.dal.pojo.CodeP4Repository;
+import cd.casic.ci.log.scm.dal.pojo.CodeSvnRepository;
+import cd.casic.ci.ticket.dal.enums.CredentialType;
+import cd.casic.framework.commons.util.encrypt.DHUtil;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
+
+import java.util.Base64;
+import java.util.List;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.process.api.process.utils
+ * @Project:ops-pro
+ * @name:CredentialUtils
+ * @Date:2025/03/27 14:35
+ * @Filename:CredentialUtils
+ * @description:Todo
+ */
+@Slf4j
+public class CredentialUtils {
+
+ public static Credential getCredential(Repository repository, List credentials, CredentialType credentialType) {
+ if (repository instanceof CodeSvnRepository && ((CodeSvnRepository) repository).getSvnType() == CodeSvnRepository.SVN_TYPE_HTTP) {
+ return switch (credentialType) {
+ case USERNAME_PASSWORD -> {
+ if (credentials.size() <= 1) {
+ log.warn("Fail to get the username of the svn repo {}", repository);
+ yield new Credential(repository.getUserName(), credentials.get(0), null);
+ } else {
+ yield new Credential(credentials.get(0), credentials.get(1), null);
+ }
+ }
+ case TOKEN_USERNAME_PASSWORD -> {
+ yield new Credential(
+ credentials.get(0),
+ credentials.getOrDefault(1, ""),
+ credentials.getOrDefault(2, ""),
+ null
+ );
+ }
+ default -> new Credential(repository.getUserName(), credentials.get(0), null);
+ };
+ } else if (repository instanceof CodeSvnRepository && credentialType == CredentialType.TOKEN_SSH_PRIVATEKEY) {
+ return new Credential(
+ credentials.get(0),
+ credentials.getOrDefault(1, ""),
+ repository.getUserName(),
+ credentials.getOrDefault(2, "")
+ );
+ } else if (repository instanceof CodeP4Repository && credentialType == CredentialType.USERNAME_PASSWORD) {
+ return new Credential(credentials.get(0), "", credentials.get(1));
+ } else {
+ String privateKey = credentials.get(0);
+ String passPhrase = credentials.size() > 1 && !credentials.get(1).isEmpty() ? credentials.get(1) : null;
+ return new Credential(repository.getUserName(), privateKey, passPhrase);
+ }
+ }
+
+ public static String decode(String encode, String publicKey, byte[] privateKey) {
+ if (!StringUtils.hasText(encode)) return "";
+ byte[] decodedBytes = Base64.getDecoder().decode(encode);
+ byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
+ return new String(DHUtil.decrypt(decodedBytes, publicKeyBytes, privateKey));
+ }
+
+ @Data
+ public static class Credential {
+ private String username;
+ private String privateKey;
+ private String passPhrase;
+ private String svnToken;
+ private CredentialType credentialType;
+
+ public Credential(String username, String privateKey, String passPhrase) {
+ this.username = username;
+ this.privateKey = privateKey;
+ this.passPhrase = passPhrase;
+ }
+
+ public Credential(String svnToken, String username, String privateKey, String passPhrase) {
+ this.svnToken = svnToken;
+ this.username = username;
+ this.privateKey = privateKey;
+ this.passPhrase = passPhrase;
+ }
+ }
+}
diff --git a/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/DependOnUtils.java b/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/DependOnUtils.java
new file mode 100644
index 00000000..4ddf69a9
--- /dev/null
+++ b/modules/ci-process/pipeline-ci-process-api/src/main/java/cd/casic/ci/process/api/process/utils/DependOnUtils.java
@@ -0,0 +1,183 @@
+package cd.casic.ci.process.api.process.utils;
+
+import cd.casic.ci.process.api.process.constant.ProcessMessageCode;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * @Author:mianbin
+ * @Package:cd.casic.ci.process.api.process.utils
+ * @Project:ops-pro
+ * @name:DependOnUtils
+ * @Date:2025/03/27 14:39
+ * @Filename:DependOnUtils
+ * @description:Todo
+ */
+@Slf4j
+public class DependOnUtils {
+
+ private static final Pattern REGEX = Pattern.compile("[,;]");
+
+ public static void checkRepeatedJobId(Stage stage) {
+ Set jobIdSet = new HashSet<>();
+ for (Container c : stage.getContainers()) {
+ String jobId = c.getJobId();
+ if (jobId == null || jobId.isEmpty()) {
+ continue;
+ }
+ if (jobIdSet.contains(jobId)) {
+ String jobName = getContainerName(stage, c, jobId);
+ throw new ErrorCodeException(
+ Response.Status.CONFLICT.getStatusCode(),
+ ProcessMessageCode.ERROR_PIPELINE_JOBID_EXIST,
+ new String[]{jobName, jobId},
+ jobName + " 的jobId(" + jobId + ")已存在"
+ );
+ }
+ jobIdSet.add(jobId);
+ }
+ removeNonexistentJob(stage, jobIdSet);
+ }
+
+ private static void removeNonexistentJob(Stage stage, Set jobIdSet) {
+ for (Container c : stage.getContainers()) {
+ JobControlOption jobControlOption = null;
+ if (c instanceof VMBuildContainer) {
+ jobControlOption = ((VMBuildContainer) c).getJobControlOption();
+ } else if (c instanceof NormalContainer) {
+ jobControlOption = ((NormalContainer) c).getJobControlOption();
+ }
+ if (jobControlOption == null) {
+ continue;
+ }
+ if (jobControlOption.getDependOnType() != DependOnType.ID || jobControlOption.getDependOnId() == null || jobControlOption.getDependOnId().isEmpty()) {
+ continue;
+ }
+ List existJobIds = jobControlOption.getDependOnId().stream()
+ .filter(jobIdSet::contains)
+ .toList();
+ jobControlOption.setDependOnId(existJobIds);
+ }
+ }
+
+ public static void initDependOn(Stage stage, Map params) {
+ Map allJobId2JobMap = new HashMap<>();
+ for (Container c : stage.getContainers()) {
+ String jobId = c.getJobId();
+ if (jobId == null || jobId.isEmpty()) {
+ continue;
+ }
+ allJobId2JobMap.put(jobId, c);
+ }
+ if (allJobId2JobMap.isEmpty()) {
+ return;
+ }
+
+ Map> cycleCheckJobMap = new HashMap<>();
+ for (Container c : stage.getContainers()) {
+ JobControlOption jobControlOption = null;
+ if (c instanceof VMBuildContainer) {
+ jobControlOption = ((VMBuildContainer) c).getJobControlOption();
+ } else if (c instanceof NormalContainer) {
+ jobControlOption = ((NormalContainer) c).getJobControlOption();
+ }
+ if (jobControlOption == null) {
+ continue;
+ }
+ List dependOnJobIds = getDependOnJobIds(new DependOnConfig(
+ jobControlOption.getDependOnType(),
+ jobControlOption.getDependOnId(),
+ jobControlOption.getDependOnName()
+ ), params);
+ if (dependOnJobIds.isEmpty()) {
+ continue;
+ }
+ if (c.getJobId() != null) {
+ cycleCheckJobMap.put(c.getJobId(), dependOnJobIds);
+ }
+ Map containerId2JobIds = new HashMap<>();
+ for (String dependOnJobId : dependOnJobIds) {
+ Container dependOnJob = allJobId2JobMap.get(dependOnJobId);
+ if (dependOnJob == null) {
+ continue;
+ }
+ containerId2JobIds.put(dependOnJob.getId(), dependOnJobId);
+ }
+ if (!containerId2JobIds.isEmpty()) {
+ jobControlOption.setDependOnContainerId2JobIds(containerId2JobIds);
+ }
+ }
+
+ Map visited = new HashMap<>();
+ for (String jobId : cycleCheckJobMap.keySet()) {
+ dsf(jobId, cycleCheckJobMap, visited, stage, allJobId2JobMap);
+ }
+ }
+
+ public static boolean enableDependOn(Container container) {
+ JobControlOption jobControlOption = null;
+ if (container instanceof VMBuildContainer) {
+ jobControlOption = ((VMBuildContainer) container).getJobControlOption();
+ } else if (container instanceof NormalContainer) {
+ jobControlOption = ((NormalContainer) container).getJobControlOption();
+ }
+ if (jobControlOption == null) {
+ return false;
+ }
+ return switch (jobControlOption.getDependOnType()) {
+ case ID -> jobControlOption.getDependOnId() != null && !jobControlOption.getDependOnId().isEmpty();
+ case NAME -> jobControlOption.getDependOnName() != null && !jobControlOption.getDependOnName().isEmpty();
+ default -> false;
+ };
+ }
+
+ private static List getDependOnJobIds(DependOnConfig dependOnConfig, Map params) {
+ return switch (dependOnConfig.getDependOnType()) {
+ case ID -> dependOnConfig.getDependOnId() != null ? dependOnConfig.getDependOnId() : Collections.emptyList();
+ case NAME -> {
+ if (dependOnConfig.getDependOnName() == null || dependOnConfig.getDependOnName().isEmpty()) {
+ yield Collections.emptyList();
+ } else {
+ String[] dependONames = dependOnConfig.getDependOnName().split(REGEX);
+ List result = new ArrayList<>();
+ for (String name : dependONames) {
+ result.add(EnvUtils.parseEnv(name, params));
+ }
+ yield result;
+ }
+ }
+ default -> Collections.emptyList();
+ };
+ }
+
+ private static void dsf(String jobId, Map> dependOnMap, Map visited, Stage stage, Map allJobId2JobMap) {
+ if (visited.getOrDefault(jobId, 0) == 1) {
+ String jobName = getContainerName(stage, allJobId2JobMap.get(jobId), jobId);
+ String dependJobName = getContainerName(stage, allJobId2JobMap.get(dependOnJobId), dependOnJobId);
+ throw new ErrorCodeException(
+ ProcessMessageCode.ERROR_PIPELINE_DEPENDON_CYCLE,
+ new String[]{jobName, dependJobName}
+ );
+ }
+ if (visited.getOrDefault(jobId, 0) == 2) {
+ return;
+ }
+
+ visited.put(jobId, 1);
+ List dependOnJobIds = dependOnMap.getOrDefault(jobId, Collections.emptyList());
+ for (String dependOnJobId : dependOnJobIds) {
+ dsf(dependOnJobId, dependOnMap, visited, stage, allJobId2JobMap);
+ }
+ visited.put(jobId, 2);
+ }
+
+ private static String getContainerName(Stage stage, Container container, String jobId) {
+ if (container == null) {
+ return jobId;
+ }
+ String namePrefix = stage.getName() != null ? stage.getName().replaceFirst("stage-", "") : "";
+ return namePrefix + "-" + container.getId();
+ }
+}