{
+
+}
diff --git a/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/dal/mysql/pipeline/PipelineInstanceNodeDetailMapper.java b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/dal/mysql/pipeline/PipelineInstanceNodeDetailMapper.java
new file mode 100644
index 00000000..a7280669
--- /dev/null
+++ b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/dal/mysql/pipeline/PipelineInstanceNodeDetailMapper.java
@@ -0,0 +1,18 @@
+package cn.odboy.devops.dal.mysql.pipeline;
+
+import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceNodeDetailTb;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ *
+ * 流水线实例节点明细 Mapper 接口
+ *
+ *
+ * @author codegen
+ * @since 2025-06-26
+ */
+@Mapper
+public interface PipelineInstanceNodeDetailMapper extends BaseMapper {
+
+}
diff --git a/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/dal/mysql/pipeline/PipelineTemplateMapper.java b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/dal/mysql/pipeline/PipelineTemplateMapper.java
new file mode 100644
index 00000000..1a96308b
--- /dev/null
+++ b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/dal/mysql/pipeline/PipelineTemplateMapper.java
@@ -0,0 +1,18 @@
+package cn.odboy.devops.dal.mysql.pipeline;
+
+import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ *
+ * 流水线模板 Mapper 接口
+ *
+ *
+ * @author codegen
+ * @since 2025-06-26
+ */
+@Mapper
+public interface PipelineTemplateMapper extends BaseMapper {
+
+}
diff --git a/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineJobBean.java b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineJobBean.java
new file mode 100644
index 00000000..98febce7
--- /dev/null
+++ b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineJobBean.java
@@ -0,0 +1,70 @@
+package cn.odboy.devops.framework.pipeline;
+
+import cn.odboy.devops.constant.pipeline.PipelineConst;
+import cn.odboy.framework.context.SpringBeanHolder;
+import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
+import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
+import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
+import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
+import cn.odboy.devops.service.pipeline.PipelineInstanceService;
+import cn.odboy.util.CsJsonUtil;
+import com.alibaba.fastjson2.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+@Slf4j
+public class PipelineJobBean extends QuartzJobBean {
+ private final ThreadPoolTaskExecutor executor = SpringBeanHolder.getBean("pipelineAsync");
+
+ @Override
+ public void executeInternal(JobExecutionContext context) {
+ JobDataMap mergedJobDataMap = context.getMergedJobDataMap();
+ // 实例、节点明细
+ PipelineInstanceService pipelineInstanceService = SpringBeanHolder.getBean(PipelineInstanceService.class);
+ PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService = SpringBeanHolder.getBean(PipelineInstanceNodeDetailService.class);
+ // 获取流水线实例
+ String pipelineInstanceId = mergedJobDataMap.getString(PipelineConst.INSTANCE_ID_KEY);
+ PipelineInstanceTb pipelineInstance = pipelineInstanceService.getPipelineInstance(pipelineInstanceId);
+ if (pipelineInstance == null) {
+ log.info("流水线实例不存在, instanceId={}", pipelineInstanceId);
+ return;
+ }
+ String pipelineTemplate = pipelineInstance.getPipelineTemplate();
+ // 流水线节点模板
+ List pipelineNodeTemplateVos = JSON.parseArray(pipelineTemplate, PipelineNodeTemplateVo.class);
+ // 流水线上下文参数
+ Map contextArgs = CsJsonUtil.toMap(pipelineInstance.getContext(), String.class, Object.class);
+ // 放置额外的参数
+ contextArgs.put(PipelineConst.INSTANCE_KEY, pipelineInstance);
+ // 执行节点任务
+ for (int i = 0; i < pipelineNodeTemplateVos.size(); i++) {
+ PipelineNodeTemplateVo pipelineNodeTemplateVo = pipelineNodeTemplateVos.get(i);
+ String code = pipelineNodeTemplateVo.getCode();
+ contextArgs.put(PipelineConst.INSTANCE_NODE_INDEX_KEY, i);
+ contextArgs.put(PipelineConst.INSTANCE_NODE_CODE_KEY, code);
+ contextArgs.put(PipelineConst.INSTANCE_NODE_NAME_KEY, pipelineNodeTemplateVo.getName());
+ contextArgs.put(PipelineConst.INSTANCE_NODE_TEMPLATE_ARGS_KEY, pipelineNodeTemplateVo.getParameters());
+ try {
+ List allServiceBeanName = SpringBeanHolder.getAllServiceBeanName();
+ System.err.println(allServiceBeanName);
+ PipelineNodeJobRunnable pipelineNodeJobRunnable = new PipelineNodeJobRunnable(
+ PipelineConst.EXECUTOR_PREFIX + code,
+ contextArgs,
+ pipelineInstanceNodeDetailService
+ );
+ Future> future = executor.submit(pipelineNodeJobRunnable);
+ PipelineNodeJobExecuteResult executeResult = (PipelineNodeJobExecuteResult) future.get();
+ System.err.println(executeResult);
+ } catch (Exception e) {
+ log.error("流水线节点任务执行失败", e);
+ }
+ }
+ }
+}
diff --git a/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineJobManage.java b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineJobManage.java
new file mode 100644
index 00000000..34e0b9cd
--- /dev/null
+++ b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineJobManage.java
@@ -0,0 +1,59 @@
+package cn.odboy.devops.framework.pipeline;
+
+import cn.odboy.devops.constant.pipeline.PipelineConst;
+import cn.odboy.framework.exception.BadRequestException;
+import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.*;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Slf4j
+@Component
+public class PipelineJobManage {
+ @Resource
+ private Scheduler scheduler;
+
+ /**
+ * 启动 job
+ */
+ public void startJob(PipelineInstanceTb pipelineInstance) {
+ try {
+ // 构建 JobDetail
+ JobDetail jobDetail = JobBuilder
+ .newJob(PipelineJobBean.class)
+ .withIdentity(pipelineInstance.getPipelineInstanceId())
+ .build();
+ // 构建Trigger
+ Trigger cronTrigger = TriggerBuilder.newTrigger()
+ .withIdentity(pipelineInstance.getPipelineInstanceId())
+ .startNow()
+ .build();
+ // 添加流水线实例
+ cronTrigger.getJobDataMap().put(PipelineConst.INSTANCE_ID_KEY, pipelineInstance.getPipelineInstanceId());
+ try {
+ scheduler.scheduleJob(jobDetail, cronTrigger);
+ } catch (ObjectAlreadyExistsException e) {
+ log.warn("定时任务已存在,跳过加载");
+ }
+ } catch (Exception e) {
+ log.error("创建定时任务失败", e);
+ throw new BadRequestException("创建定时任务失败");
+ }
+ }
+
+ /**
+ * 删除job
+ */
+ public void deleteJob(PipelineInstanceTb pipelineInstance) {
+ try {
+ JobKey jobKey = JobKey.jobKey(pipelineInstance.getPipelineInstanceId());
+ scheduler.pauseJob(jobKey);
+ scheduler.deleteJob(jobKey);
+ } catch (Exception e) {
+ log.error("删除定时任务失败", e);
+ throw new BadRequestException("删除定时任务失败");
+ }
+ }
+}
diff --git a/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineNodeJobExecutor.java b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineNodeJobExecutor.java
new file mode 100644
index 00000000..f1a37274
--- /dev/null
+++ b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineNodeJobExecutor.java
@@ -0,0 +1,11 @@
+package cn.odboy.devops.framework.pipeline;
+
+import cn.odboy.framework.exception.BadRequestException;
+import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
+import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
+
+import java.util.Map;
+
+public interface PipelineNodeJobExecutor {
+ PipelineNodeJobExecuteResult execute(Map contextArgs, PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService) throws BadRequestException;
+}
diff --git a/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineNodeJobRunnable.java b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineNodeJobRunnable.java
new file mode 100644
index 00000000..7247ac83
--- /dev/null
+++ b/cutejava/cutejava-module-devops/src/main/java/cn/odboy/devops/framework/pipeline/PipelineNodeJobRunnable.java
@@ -0,0 +1,29 @@
+package cn.odboy.devops.framework.pipeline;
+
+import cn.odboy.framework.context.SpringBeanHolder;
+import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+public class PipelineNodeJobRunnable implements Callable