feat(devops): 重构流水线执行逻辑

- 移除 PipelineJobBean 类,改为使用 PipelineNodeJobBean
- 重构 PipelineJobManage 类,支持按节点启动和删除任务
- 新增 PipelineInstanceDAO 类,用于处理 Redis 锁
- 更新数据库表结构,适应新的流水线模型
- 优化异步线程池配置
This commit is contained in:
2025-07-21 23:47:08 +08:00
parent 1a6363c159
commit de5df39ff0
67 changed files with 3500 additions and 1574 deletions
@@ -55,7 +55,7 @@
</div>
<div class="box-current-node">
<a @click="onCurrentNodeClick">
{{ templateData.currentNode }}
{{ templateData.currentNodeMsg }}
</a>
</div>
<el-row>
@@ -163,7 +163,7 @@ export default {
createTime: '2025-07-17 21:12:01',
updateTime: '2025-07-17 21:13:01',
startTime: '2025-07-17 21:13:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -176,7 +176,7 @@ export default {
createTime: '2025-07-17 21:13:01',
updateTime: '2025-07-17 21:18:01',
startTime: '2025-07-17 21:13:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -193,7 +193,7 @@ export default {
createTime: '2025-07-17 21:18:01',
updateTime: '2025-07-17 21:28:01',
startTime: '2025-07-17 21:18:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -210,7 +210,7 @@ export default {
createTime: '2025-07-17 21:28:01',
updateTime: '2025-07-17 21:28:21',
startTime: '2025-07-17 21:28:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -237,7 +237,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: '2025-07-17 21:28:21',
currentNode: '等待人工审批',
currentNodeMsg: '等待人工审批',
currentNodeStatus: 'running',
status: 'running'
},
@@ -258,7 +258,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
},
@@ -277,7 +277,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
},
@@ -290,7 +290,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
}
@@ -304,7 +304,7 @@ export default {
createTime: '2025-07-17 21:12:01',
updateTime: '2025-07-17 21:13:01',
startTime: '2025-07-17 21:13:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -317,7 +317,7 @@ export default {
createTime: '2025-07-17 21:13:01',
updateTime: '2025-07-17 21:18:01',
startTime: '2025-07-17 21:13:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -334,7 +334,7 @@ export default {
createTime: '2025-07-17 21:18:01',
updateTime: '2025-07-17 21:28:01',
startTime: '2025-07-17 21:18:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -351,7 +351,7 @@ export default {
createTime: '2025-07-17 21:28:01',
updateTime: '2025-07-17 21:28:21',
startTime: '2025-07-17 21:28:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -378,7 +378,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:30:21',
startTime: '2025-07-17 21:28:21',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -399,7 +399,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:58:21',
startTime: '2025-07-17 21:30:21',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -418,7 +418,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 22:10:21',
startTime: '2025-07-17 21:58:21',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -431,7 +431,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 22:10:58',
startTime: '2025-07-17 22:10:21',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
}
@@ -445,7 +445,7 @@ export default {
createTime: '2025-07-17 21:12:01',
updateTime: '2025-07-17 21:13:01',
startTime: '2025-07-17 21:13:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -458,7 +458,7 @@ export default {
createTime: '2025-07-17 21:13:01',
updateTime: '2025-07-17 21:18:01',
startTime: '2025-07-17 21:13:01',
currentNode: '执行成功',
currentNodeMsg: '执行成功',
currentNodeStatus: 'success',
status: 'success'
},
@@ -475,7 +475,7 @@ export default {
createTime: '2025-07-17 21:18:01',
updateTime: '2025-07-17 21:28:01',
startTime: '2025-07-17 21:18:01',
currentNode: '执行失败',
currentNodeMsg: '执行失败',
currentNodeStatus: 'fail',
status: 'fail'
},
@@ -492,7 +492,7 @@ export default {
createTime: '2025-07-17 21:28:01',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
},
@@ -519,7 +519,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
},
@@ -540,7 +540,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
},
@@ -559,7 +559,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
},
@@ -572,7 +572,7 @@ export default {
createTime: '2025-07-17 21:28:21',
updateTime: '2025-07-17 21:28:21',
startTime: null,
currentNode: '待执行',
currentNodeMsg: '待执行',
currentNodeStatus: 'pending',
status: 'pending'
}
@@ -33,9 +33,7 @@ public class AsyncTheadPoolConfig implements AsyncConfigurer {
// 自定义工厂
ThreadFactory factory = r -> new Thread(r, "default-async-" + new AtomicInteger(1).getAndIncrement());
// 自定义线程池
return new ThreadPoolExecutor(asyncTaskPool.getCorePoolSize(), asyncTaskPool.getMaxPoolSize(), asyncTaskPool.getKeepAliveSeconds(),
TimeUnit.SECONDS, new ArrayBlockingQueue<>(asyncTaskPool.getQueueCapacity()), factory,
new ThreadPoolExecutor.CallerRunsPolicy());
return new ThreadPoolExecutor(asyncTaskPool.getCorePoolSize(), asyncTaskPool.getMaxPoolSize(), asyncTaskPool.getKeepAliveSeconds(), TimeUnit.SECONDS, new ArrayBlockingQueue<>(asyncTaskPool.getQueueCapacity()), factory, new ThreadPoolExecutor.CallerRunsPolicy());
}
/**
@@ -61,25 +59,4 @@ public class AsyncTheadPoolConfig implements AsyncConfigurer {
executor.initialize();
return executor;
}
@Bean("pipelineAsync")
public ThreadPoolTaskExecutor pipelineAsync() {
ThreadPoolSettingModel asyncTaskPool = properties.getAsyncTaskPool();
// 用法 private ThreadPoolTaskExecutor pipelineAsync
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(asyncTaskPool.getCorePoolSize());
executor.setMaxPoolSize(asyncTaskPool.getMaxPoolSize());
executor.setQueueCapacity(asyncTaskPool.getQueueCapacity());
executor.setThreadNamePrefix("pipeline-async-");
executor.setKeepAliveSeconds(asyncTaskPool.getKeepAliveSeconds());
// DiscardOldestPolicy,抛弃最早的任务,将新任务加入队列。
// AbortPolicy,拒绝执行新任务,并抛出异常。
// CallerRunsPolicy,交由调用者线程执行新任务,如果调用者线程已关闭,则抛弃任务。
// DiscardPolicy,直接抛弃新任务。
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// 设置包装器
executor.setTaskDecorator(TtlRunnable::get);
executor.initialize();
return executor;
}
}
+1
View File
@@ -9,6 +9,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>cutejava-module-devops</artifactId>
<name>devops应用模块</name>
<dependencies>
<dependency>
<groupId>cn.odboy</groupId>
@@ -7,18 +7,25 @@ public interface PipelineConst {
/**
* 执行器服务前缀
*/
String EXECUTOR_PREFIX = "pipeline:executor:";
/**
* 流水线实例Key
*/
String INSTANCE_ID_KEY = "pipelineInstanceId";
String INSTANCE_KEY = "pipelineInstance";
/**
* 流水线实例节点相关Key
*/
String INSTANCE_NODE_INDEX_KEY = "pipelineInstanceNodeIndex";
String INSTANCE_NODE_CODE_KEY = "pipelineInstanceNodeCode";
String INSTANCE_NODE_NAME_KEY = "pipelineInstanceNodeName";
String INSTANCE_NODE_TEMPLATE_ARGS_KEY = "pipelineInstanceNodeTemplateArgs";
String INSTANCE_RETRY_NODE_INDEX_KEY = "pipelineInstanceRetryNodeIndex";
String INSTANCE_PREFIX = "pipeline_instance_";
String EXECUTOR_PREFIX = "pipeline_executor_";
// /**
// * 流水线实例Key
// */
// String INSTANCE_KEY = "pipelineInstance";
// /**
// * 流水线实例节点相关Key
// */
// String INSTANCE_NODE_INDEX_KEY = "pipelineInstanceNodeIndex";
// String INSTANCE_NODE_CODE_KEY = "pipelineInstanceNodeCode";
// String INSTANCE_NODE_NAME_KEY = "pipelineInstanceNodeName";
// String INSTANCE_NODE_TEMPLATE_ARGS_KEY = "pipelineInstanceNodeTemplateArgs";
// String INSTANCE_RETRY_NODE_INDEX_KEY = "pipelineInstanceRetryNodeIndex";
// 以下为标准常量
String INSTANCE_ID = "InstanceId";
String TEMPLATE_ID = "TemplateId";
String ENV = "Env";
String CONTEXT_NAME = "ContextName";
String RETRY_NODE_CODE = "RetryNodeCode";
String CURRENT_NODE_TEMPLATE = "CurrentNodeTemplate";
}
@@ -1,82 +0,0 @@
package cn.odboy.devops.constant.pipeline;
/**
* 流水线节点业务编码
*
* @author odboy
*/
public interface PipelineNodeBizCodeConst {
/**
* 初始化
*/
String INIT = PipelineConst.EXECUTOR_PREFIX + "node_init";
/**
* 合并代码
*/
String MERGE_BRANCH = PipelineConst.EXECUTOR_PREFIX + "node_merge_branch";
/**
* 镜像扫描
*/
String IMAGE_SCAN = PipelineConst.EXECUTOR_PREFIX + "node_image_scan";
/**
* 部署审批
*/
String DEPLOY_APPROVE = PipelineConst.EXECUTOR_PREFIX + "node_deploy_approve";
/**
* 合并确认
*/
String MERGE_CONFIRM = PipelineConst.EXECUTOR_PREFIX + "node_merge_confirm";
/**
* 合并到Master
*/
String MERGE_MASTER = PipelineConst.EXECUTOR_PREFIX + "node_merge_master";
interface AppJava {
/**
* 构建
*/
String BUILD = PipelineConst.EXECUTOR_PREFIX + "node_build_java";
/**
* 部署
*/
String DEPLOY = PipelineConst.EXECUTOR_PREFIX + "node_deploy_java";
}
interface AppPython {
/**
* 构建
*/
String BUILD = PipelineConst.EXECUTOR_PREFIX + "node_build_python";
/**
* 部署
*/
String DEPLOY = PipelineConst.EXECUTOR_PREFIX + "node_deploy_python";
}
interface AppGo {
/**
* 构建
*/
String BUILD = PipelineConst.EXECUTOR_PREFIX + "node_build_go";
/**
* 部署
*/
String DEPLOY = PipelineConst.EXECUTOR_PREFIX + "node_deploy_go";
}
interface AppNodeJs {
/**
* 构建
*/
String BUILD = PipelineConst.EXECUTOR_PREFIX + "node_build_nodejs";
/**
* 部署
*/
String DEPLOY = PipelineConst.EXECUTOR_PREFIX + "node_deploy_nodejs";
}
}
@@ -0,0 +1,43 @@
package cn.odboy.devops.controller;
import cn.odboy.annotation.AnonymousGetMapping;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.PipelineTemplateTb;
import cn.odboy.devops.service.PipelineInstanceService;
import cn.odboy.devops.service.PipelineTemplateService;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/devops/pipeline")
@Api(tags = "系统:验证码管理")
public class DevopsPipelineController {
@Autowired
private PipelineTemplateService pipelineTemplateService;
@Autowired
private PipelineInstanceService pipelineInstanceService;
@AnonymousGetMapping(value = "/start")
public ResponseEntity<?> start() {
// 输入参数
String appName = "cuteops";
String envCode = "daily";
// 获取模板
PipelineTemplateTb pipelineTemplateTb = pipelineTemplateService.getPipelineTemplateById(4L);
// 创建流水线实例
PipelineInstanceTb pipelineInstanceTb = new PipelineInstanceTb();
pipelineInstanceTb.setTemplateId(pipelineTemplateTb.getId());
pipelineInstanceTb.setInstanceName("流水线测试");
pipelineInstanceTb.setTemplateType(pipelineTemplateTb.getType());
pipelineInstanceTb.setContextName(appName);
pipelineInstanceTb.setEnv(envCode);
pipelineInstanceTb.setTemplateContent(pipelineTemplateTb.getTemplate());
pipelineInstanceService.start(pipelineInstanceTb);
return ResponseEntity.ok("流水线启动成功");
}
}
@@ -0,0 +1,76 @@
package cn.odboy.devops.dal.dataobject;
import cn.odboy.base.CsObject;
import com.anwen.mongo.annotation.ID;
import com.anwen.mongo.annotation.collection.CollectionField;
import com.anwen.mongo.annotation.collection.CollectionName;
import com.anwen.mongo.enums.FieldFill;
import com.anwen.mongo.enums.IdTypeEnum;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
/**
* <p>
* 流水线实例节点明细
* </p>
*
* @author codegen
* @since 2025-06-26
*/
@Getter
@Setter
@CollectionName("pipeline_instance_node_detail")
public class PipelineInstanceNodeDetailTb extends CsObject {
/**
* mongoid
*/
@ID(type = IdTypeEnum.ASSIGN_ID)
private Long id;
/**
* 流水线节点Id
*/
@CollectionField("node_id")
private String nodeId;
/**
* 开始时间
*/
@CollectionField(value = "start_time", fill = FieldFill.INSERT)
private Date startTime;
/**
* 结束时间
*/
@CollectionField("finish_time")
private Date finishTime;
/**
* 节点索引
*/
@CollectionField("node_index")
private Integer nodeIndex;
/**
* 节点编码
*/
@CollectionField("node_code")
private String nodeCode;
/**
* 步骤描述
*/
@CollectionField("step_name")
private String stepName;
/**
* 步骤状态
*/
@CollectionField("step_status")
private String stepStatus;
/**
* 异常明细
*/
@CollectionField("step_msg")
private String stepMsg;
}
@@ -0,0 +1,87 @@
package cn.odboy.devops.dal.dataobject;
import cn.odboy.base.CsObject;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeOperateButtonVo;
import com.anwen.mongo.annotation.ID;
import com.anwen.mongo.annotation.collection.CollectionField;
import com.anwen.mongo.annotation.collection.CollectionName;
import com.anwen.mongo.enums.FieldFill;
import com.anwen.mongo.enums.IdTypeEnum;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 流水线实例明细
*
* @author odboy
* @date 2025-07-20
*/
@Getter
@Setter
@CollectionName("pipeline_instance_node")
public class PipelineInstanceNodeTb extends CsObject {
/**
* mongoid
*/
@ID(type = IdTypeEnum.ASSIGN_ID)
private Long id;
/**
* 流水线实例id
*/
@CollectionField("instance_id")
private Long instanceId;
/**
* 节点名称
*/
@CollectionField("name")
private String name;
/**
* 节点编码,也就是流水线模板中的code
*/
@CollectionField("code")
private String code;
/**
* 节点类型:默认为service
*/
@CollectionField("type")
private String type = "service";
/**
* 节点具体服务类型:gitlab、jenkins等
*/
@CollectionField("detail_type")
private String detailType;
/**
* 默认附加参数
*/
@CollectionField("parameters")
private Map<String, Object> parameters;
@CollectionField("click")
private Boolean click = false;
@CollectionField("retry")
private Boolean retry = false;
@CollectionField("buttons")
private List<PipelineNodeOperateButtonVo> buttons;
@CollectionField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
@CollectionField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
@CollectionField("start_time")
private Date startTime;
/**
* 节点状态
*/
@CollectionField("current_node_msg")
private String currentNodeMsg = PipelineStatusEnum.PENDING.getDesc();
@CollectionField("current_node_status")
private String currentNodeStatus = PipelineStatusEnum.PENDING.getCode();
/**
* 节点状态
*/
@CollectionField("status")
private String status = PipelineStatusEnum.PENDING.getCode();
}
@@ -1,7 +1,9 @@
package cn.odboy.devops.dal.dataobject.pipeline;
package cn.odboy.devops.dal.dataobject;
import cn.odboy.base.CsObject;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -23,102 +25,52 @@ import java.util.Date;
@TableName("pipeline_instance")
@ApiModel(value = "PipelineInstance对象", description = "流水线实例")
public class PipelineInstanceTb extends CsObject {
/**
* 流水线模板id
*/
@ApiModelProperty("流水线模板id")
@TableField("pipeline_template_id")
private Long pipelineTemplateId;
/**
* 流水线实例名称
*/
@ApiModelProperty("流水线实例名称")
@TableField("pipeline_instance_name")
private String pipelineInstanceName;
/**
* 流水线实例id
*/
@ApiModelProperty("流水线实例id")
@TableField("pipeline_instance_id")
private Long pipelineInstanceId;
@TableId(value = "instance_id")
private Long instanceId;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
@TableField("create_time")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 创建人
*/
@ApiModelProperty("创建人")
@TableField("create_by")
@TableField(value = "create_by", fill = FieldFill.INSERT)
private String createBy;
/**
* 更新时间
*/
@ApiModelProperty("更新时间")
@TableField("update_time")
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/**
* 流水线模板类型
*/
@TableField("`type`")
@ApiModelProperty("流水线模板类型")
private String type;
@ApiModelProperty("流水线实例名称")
@TableField("instance_name")
private String instanceName;
/**
* 应用名称
*/
@TableField("app_name")
@ApiModelProperty("应用名称")
private String appName;
/**
* 环境编码
*/
@TableField("env")
@ApiModelProperty("环境编码")
private String env;
/**
* 流水线实例状态
*/
@TableField("context_name")
@ApiModelProperty("上下文名称")
private String contextName;
@TableField("context_params")
@ApiModelProperty("上下文参数,这里指QuartzJobDataMap")
private String contextParams;
@TableField("current_node")
@ApiModelProperty("流水线实例当前节点code")
private String currentNode;
@ApiModelProperty("流水线实例当前节点状态")
@TableField("current_node_status")
private String currentNodeStatus;
@TableField("`status`")
@ApiModelProperty("流水线实例状态")
private String status;
/**
* 流水线实例当前节点code
*/
@TableField("current_node")
@ApiModelProperty("流水线实例当前节点code")
private String currentNode;
/**
* 流水线实例当前节点状态
*/
@ApiModelProperty("流水线实例当前节点状态")
@TableField("current_node_status")
private String currentNodeStatus;
/**
* 输入参数
*/
@TableField("`context`")
@ApiModelProperty("输入参数")
private String context;
/**
* 流水线模板
*/
@TableField("pipeline_template")
@ApiModelProperty("流水线模板id")
@TableField("template_id")
private Long templateId;
@TableField("template_type")
@ApiModelProperty("流水线模板类型")
private String templateType;
@TableField("template_content")
@ApiModelProperty("流水线模板")
private String pipelineTemplate;
private String templateContent;
}
@@ -1,4 +1,4 @@
package cn.odboy.devops.dal.dataobject.pipeline;
package cn.odboy.devops.dal.dataobject;
import cn.odboy.base.CsBaseUserTimeLogicTb;
import com.baomidou.mybatisplus.annotation.IdType;
@@ -1,81 +0,0 @@
package cn.odboy.devops.dal.dataobject.pipeline;
import cn.odboy.base.CsObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
/**
* <p>
* 流水线实例节点明细
* </p>
*
* @author codegen
* @since 2025-06-26
*/
@Getter
@Setter
@TableName("pipeline_instance_node_detail")
@ApiModel(value = "PipelineInstanceNodeDetail对象", description = "流水线实例节点明细")
public class PipelineInstanceNodeDetailTb extends CsObject {
/**
* id
*/
@ApiModelProperty("id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 流水线实例id
*/
@ApiModelProperty("流水线实例id")
@TableField("pipeline_instance_id")
private Long pipelineInstanceId;
/**
* 开始时间
*/
@ApiModelProperty("开始时间")
@TableField("start_time")
private Date startTime;
/**
* 节点索引
*/
@ApiModelProperty("节点索引")
@TableField("node_index")
private Integer nodeIndex;
/**
* 节点编码
*/
@ApiModelProperty("节点编码")
@TableField("node_code")
private String nodeCode;
/**
* 步骤描述
*/
@TableField("step_name")
@ApiModelProperty("步骤描述")
private String stepName;
/**
* 步骤状态
*/
@ApiModelProperty("步骤状态")
@TableField("step_status")
private String stepStatus;
/**
* 异常明细
*/
@ApiModelProperty("异常明细")
@TableField("step_msg")
private String stepMsg;
}
@@ -0,0 +1,17 @@
package cn.odboy.devops.dal.mysql;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 流水线实例 Mapper 接口
* </p>
*
* @author codegen
* @since 2025-06-26
*/
@Mapper
public interface PipelineInstanceMapper extends BaseMapper<PipelineInstanceTb> {
}
@@ -1,6 +1,6 @@
package cn.odboy.devops.dal.mysql.pipeline;
package cn.odboy.devops.dal.mysql;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.dal.dataobject.PipelineTemplateTb;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@@ -1,21 +0,0 @@
package cn.odboy.devops.dal.mysql.pipeline;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 流水线实例 Mapper 接口
* </p>
*
* @author codegen
* @since 2025-06-26
*/
@Mapper
public interface PipelineInstanceMapper extends BaseMapper<PipelineInstanceTb> {
void updateStatusByInstanceId(@Param("status") String status, @Param("pipelineInstanceId") long pipelineInstanceId);
void updateCurrentNodeByInstanceId(@Param("code") String code, @Param("status") String status, @Param("pipelineInstanceId") long pipelineInstanceId);
}
@@ -1,18 +0,0 @@
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;
/**
* <p>
* 流水线实例节点明细 Mapper 接口
* </p>
*
* @author codegen
* @since 2025-06-26
*/
@Mapper
public interface PipelineInstanceNodeDetailMapper extends BaseMapper<PipelineInstanceNodeDetailTb> {
}
@@ -0,0 +1,35 @@
package cn.odboy.devops.dal.redis;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
import cn.odboy.framework.redis.RedisHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class PipelineInstanceDAO {
private final RedisHelper redisHelper;
/**
* 全局锁,对应上下文,只能有一次
*/
public boolean lock(PipelineInstanceTb pipelineInstanceTb) {
String redisKey = PipelineConst.INSTANCE_PREFIX + pipelineInstanceTb.getTemplateId() + pipelineInstanceTb.getContextName();
Object o = redisHelper.get(redisKey);
if (o != null) {
return true;
}
// 365天
redisHelper.set(redisKey, true, 60 * 60 * 24 * 365);
return false;
}
public void unLock(PipelineInstanceTb pipelineInstanceTb) {
String redisKey = PipelineConst.INSTANCE_PREFIX + pipelineInstanceTb.getTemplateId() + pipelineInstanceTb.getContextName();
Object o = redisHelper.get(redisKey);
if (o != null) {
redisHelper.del(redisKey);
}
}
}
@@ -0,0 +1,40 @@
package cn.odboy.devops.framework.mongoplus;
import com.anwen.mongo.handlers.MetaObjectHandler;
import com.anwen.mongo.model.AutoFillMetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MongoPlusMetaObjectHandler implements MetaObjectHandler {
// @Override
// public void insertFill(Map<String, Object> insertFillMap, Document document) {
// insertFillMap.keySet().forEach(key -> {
// if (key.equals("createTime")){
// document.put(key, LocalDateTime.now());
// }
// });
// }
//
// @Override
// public void updateFill(Map<String, Object> insertFillMap, Document document) {
// insertFillMap.keySet().forEach(key -> {
// if (key.equals("createTime")){
// document.put(key, LocalDateTime.now());
// }
// });
// }
@Override
public void insertFill(AutoFillMetaObject insertAutoFillMetaObject) {
Date nowTime = new Date();
insertAutoFillMetaObject.fillValue("create_time", nowTime);
insertAutoFillMetaObject.fillValue("update_time", nowTime);
}
@Override
public void updateFill(AutoFillMetaObject updateAutoFillMetaObject) {
updateAutoFillMetaObject.fillValue("update_time", new Date());
}
}
@@ -1,19 +0,0 @@
package cn.odboy.devops.framework.pipeline.core;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.framework.context.SpringBeanHolder;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.QuartzJobBean;
@Slf4j
public class PipelineJobBean extends QuartzJobBean {
private final ThreadPoolTaskExecutor executor = SpringBeanHolder.getBean("pipelineAsync");
private final PipelineInstanceService pipelineInstanceService = SpringBeanHolder.getBean(PipelineInstanceService.class);
@Override
public void executeInternal(JobExecutionContext context) {
pipelineInstanceService.startPipeline(executor, context);
}
}
@@ -1,39 +1,58 @@
package cn.odboy.devops.framework.pipeline.core;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.framework.exception.BadRequestException;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
/**
* 流水线任务管理器
*
* @author odboy
* @date 2025-07-19
*/
@Slf4j
@Component
public class PipelineJobManage {
private static final String JOB_KEY = "PIPELINE_JOB_";
private static final String JOB_KEY = "PIPELINE_JOB_%s_%s";
@Resource
private Scheduler scheduler;
/**
* 启动 job
*/
public void startJob(PipelineInstanceTb pipelineInstance) {
public void startJob(PipelineInstanceTb pipelineInstance, PipelineNodeTemplateVo pipelineNodeTemplate) {
try {
// 流水线Id
Long instanceId = pipelineInstance.getInstanceId();
String jobId = String.format(JOB_KEY, instanceId, pipelineNodeTemplate.getCode());
// 构建 JobDetail
JobKey jobKey = JobKey.jobKey(jobId);
JobDetail jobDetail = JobBuilder
.newJob(PipelineJobBean.class)
.withIdentity(JOB_KEY + pipelineInstance.getPipelineInstanceId())
.newJob(PipelineNodeJobBean.class)
.withIdentity(jobKey)
.build();
// 构建Trigger
TriggerKey triggerKey = TriggerKey.triggerKey(String.format(JOB_KEY, instanceId, pipelineNodeTemplate.getCode()));
Trigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity(JOB_KEY + pipelineInstance.getPipelineInstanceId())
.withIdentity(triggerKey)
.startNow()
.build();
// 添加流水线实例
cronTrigger.getJobDataMap().put(PipelineConst.INSTANCE_ID_KEY, pipelineInstance.getPipelineInstanceId());
// 任务参数
JobDataMap jobDataMap = cronTrigger.getJobDataMap();
jobDataMap.put(PipelineConst.INSTANCE_ID, pipelineInstance.getInstanceId());
jobDataMap.put(PipelineConst.CONTEXT_NAME, pipelineInstance.getContextName());
jobDataMap.put(PipelineConst.ENV, pipelineInstance.getEnv());
jobDataMap.put(PipelineConst.TEMPLATE_ID, pipelineInstance.getTemplateId());
jobDataMap.put(PipelineConst.CURRENT_NODE_TEMPLATE, pipelineNodeTemplate);
try {
// 在quartz的内部线程池中异步执行
scheduler.scheduleJob(jobDetail, cronTrigger);
} catch (ObjectAlreadyExistsException e) {
log.warn("定时任务已存在,跳过加载");
@@ -47,9 +66,9 @@ public class PipelineJobManage {
/**
* 删除job
*/
public void deleteJob(PipelineInstanceTb pipelineInstance) {
public void deleteJob(@NotNull String instanceId, @NotNull String nodeCode) {
try {
JobKey jobKey = JobKey.jobKey(JOB_KEY + pipelineInstance.getPipelineInstanceId());
JobKey jobKey = JobKey.jobKey(String.format(JOB_KEY, instanceId, nodeCode));
scheduler.pauseJob(jobKey);
scheduler.deleteJob(jobKey);
} catch (Exception e) {
@@ -57,4 +76,13 @@ public class PipelineJobManage {
throw new BadRequestException("删除定时任务失败");
}
}
/**
* 中断正在执行的任务<br/>
* 任务终止需要配合响应中断或停止信号
*/
public void interruptJob(@NotNull String instanceId, @NotNull String nodeCode) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(String.format(JOB_KEY, instanceId, nodeCode));
scheduler.interrupt(jobKey);
}
}
@@ -0,0 +1,30 @@
package cn.odboy.devops.framework.pipeline.core;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.framework.context.SpringBeanHolder;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
/**
* 流水线任务载体
*
* @author odboy
* @date 2025-07-19
*/
@Slf4j
public class PipelineNodeJobBean implements InterruptableJob {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();
PipelineNodeTemplateVo currentNodeTemplate = (PipelineNodeTemplateVo) jobDataMap.get(PipelineConst.CURRENT_NODE_TEMPLATE);
String serviceName = PipelineConst.EXECUTOR_PREFIX + currentNodeTemplate.getCode();
PipelineNodeJobExecutor pipelineNodeJobExecutor = SpringBeanHolder.getBean(serviceName);
pipelineNodeJobExecutor.execute(jobDataMap);
}
@Override
public void interrupt() throws UnableToInterruptJobException {
}
}
@@ -1,10 +1,14 @@
package cn.odboy.devops.framework.pipeline.core;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.framework.exception.BadRequestException;
import java.util.Map;
import org.quartz.JobDataMap;
/**
* 流水线节点任务 接口
*
* @author odboy
* @date 2025-07-21
*/
public interface PipelineNodeJobExecutor {
PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException;
PipelineNodeJobExecuteResult execute(JobDataMap contextArgs);
}
@@ -1,26 +0,0 @@
package cn.odboy.devops.framework.pipeline.core;
import cn.odboy.framework.context.SpringBeanHolder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
public class PipelineNodeJobRunnable implements Callable<Object> {
private final PipelineNodeJobExecutor target;
private final Map<String, Object> params;
public PipelineNodeJobRunnable(String beanName, Map<String, Object> params) {
this.target = SpringBeanHolder.getBean(beanName);
this.params = params;
}
@Override
@SuppressWarnings({"unchecked", "all"})
public Object call() throws Exception {
if (this.params == null) {
return this.target.execute(new HashMap<>(1));
}
return this.target.execute(this.params);
}
}
@@ -14,9 +14,9 @@ import java.util.Map;
*/
@Getter
@Setter
public class PipelineNodeTemplateButtonVo extends CsObject {
public class PipelineNodeOperateButtonVo extends CsObject {
/**
* 按钮类型(service:调用某个服务 link:带参跳转)
* 按钮类型(service:调用某个服务并传递参数 link:带参跳转)
*/
private String type;
/**
@@ -28,7 +28,7 @@ public class PipelineNodeTemplateButtonVo extends CsObject {
*/
private String code;
/**
* 按钮样式参数
* 默认附加参数
*/
private Map<String, String> parameters = new HashMap<>();
}
@@ -44,9 +44,9 @@ public class PipelineNodeTemplateVo extends CsObject {
/**
* 默认参数
*/
private Map<String, String> parameters = new HashMap<>();
private Map<String, Object> parameters = new HashMap<>();
/**
* 流水线节点控制按钮
*/
private List<PipelineNodeTemplateButtonVo> buttons = new ArrayList<>();
private List<PipelineNodeOperateButtonVo> buttons = new ArrayList<>();
}
@@ -0,0 +1,34 @@
package cn.odboy.devops.job;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.devops.service.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.PipelineInstanceNodeService;
import cn.odboy.devops.service.PipelineInstanceService;
import cn.odboy.devops.service.PipelineTemplateService;
import lombok.RequiredArgsConstructor;
import org.quartz.JobDataMap;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service(value = PipelineConst.EXECUTOR_PREFIX + "node_build_java")
public class PipelineNodeBuildJava implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeService pipelineInstanceNodeService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
public PipelineNodeJobExecuteResult execute(JobDataMap jobDataMap) {
long instanceId = jobDataMap.getLong(PipelineConst.INSTANCE_ID);
String contextName = jobDataMap.getString(PipelineConst.CONTEXT_NAME);
String env = jobDataMap.getString(PipelineConst.ENV);
long templateId = jobDataMap.getLong(PipelineConst.TEMPLATE_ID);
PipelineNodeTemplateVo currentNodeTemplate = (PipelineNodeTemplateVo) jobDataMap.get(PipelineConst.CURRENT_NODE_TEMPLATE);
pipelineInstanceNodeService.updatePipelineInstanceNodeByArgs(instanceId, currentNodeTemplate.getCode(), PipelineStatusEnum.SUCCESS, PipelineStatusEnum.SUCCESS.getDesc());
return PipelineNodeJobExecuteResult.success();
}
}
@@ -0,0 +1,34 @@
package cn.odboy.devops.job;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.devops.service.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.PipelineInstanceNodeService;
import cn.odboy.devops.service.PipelineInstanceService;
import cn.odboy.devops.service.PipelineTemplateService;
import lombok.RequiredArgsConstructor;
import org.quartz.JobDataMap;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service(value = PipelineConst.EXECUTOR_PREFIX + "node_deploy_java")
public class PipelineNodeDeployJava implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeService pipelineInstanceNodeService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
public PipelineNodeJobExecuteResult execute(JobDataMap jobDataMap) {
long instanceId = jobDataMap.getLong(PipelineConst.INSTANCE_ID);
String contextName = jobDataMap.getString(PipelineConst.CONTEXT_NAME);
String env = jobDataMap.getString(PipelineConst.ENV);
long templateId = jobDataMap.getLong(PipelineConst.TEMPLATE_ID);
PipelineNodeTemplateVo currentNodeTemplate = (PipelineNodeTemplateVo) jobDataMap.get(PipelineConst.CURRENT_NODE_TEMPLATE);
pipelineInstanceNodeService.updatePipelineInstanceNodeByArgs(instanceId, currentNodeTemplate.getCode(), PipelineStatusEnum.SUCCESS, PipelineStatusEnum.SUCCESS.getDesc());
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,64 +1,34 @@
package cn.odboy.devops.job;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.devops.service.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.PipelineInstanceNodeService;
import cn.odboy.devops.service.PipelineInstanceService;
import cn.odboy.devops.service.PipelineTemplateService;
import lombok.RequiredArgsConstructor;
import org.quartz.JobDataMap;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.INIT)
@Service(value = PipelineConst.EXECUTOR_PREFIX + "node_init")
public class PipelineNodeInitJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeService pipelineInstanceNodeService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
pipelineInstanceNodeDetailService.addLog(pipelineInstanceId, contextArgs, "release分支名称: xxxxxx", PipelineStatusEnum.SUCCESS, "");
pipelineInstanceNodeDetailService.addLog(pipelineInstanceId, contextArgs, "master分支合并到release分支成功: xxxxxx", PipelineStatusEnum.SUCCESS, "");
public PipelineNodeJobExecuteResult execute(JobDataMap jobDataMap) {
long instanceId = jobDataMap.getLong(PipelineConst.INSTANCE_ID);
String contextName = jobDataMap.getString(PipelineConst.CONTEXT_NAME);
String env = jobDataMap.getString(PipelineConst.ENV);
long templateId = jobDataMap.getLong(PipelineConst.TEMPLATE_ID);
PipelineNodeTemplateVo currentNodeTemplate = (PipelineNodeTemplateVo) jobDataMap.get(PipelineConst.CURRENT_NODE_TEMPLATE);
pipelineInstanceNodeService.updatePipelineInstanceNodeByArgs(instanceId, currentNodeTemplate.getCode(), PipelineStatusEnum.SUCCESS, PipelineStatusEnum.SUCCESS.getDesc());
return PipelineNodeJobExecuteResult.success();
}
}
@@ -0,0 +1,34 @@
package cn.odboy.devops.job;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.devops.service.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.PipelineInstanceNodeService;
import cn.odboy.devops.service.PipelineInstanceService;
import cn.odboy.devops.service.PipelineTemplateService;
import lombok.RequiredArgsConstructor;
import org.quartz.JobDataMap;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service(value = PipelineConst.EXECUTOR_PREFIX + "node_merge_branch")
public class PipelineNodeMergeBranch implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeService pipelineInstanceNodeService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
public PipelineNodeJobExecuteResult execute(JobDataMap jobDataMap) {
long instanceId = jobDataMap.getLong(PipelineConst.INSTANCE_ID);
String contextName = jobDataMap.getString(PipelineConst.CONTEXT_NAME);
String env = jobDataMap.getString(PipelineConst.ENV);
long templateId = jobDataMap.getLong(PipelineConst.TEMPLATE_ID);
PipelineNodeTemplateVo currentNodeTemplate = (PipelineNodeTemplateVo) jobDataMap.get(PipelineConst.CURRENT_NODE_TEMPLATE);
pipelineInstanceNodeService.updatePipelineInstanceNodeByArgs(instanceId, currentNodeTemplate.getCode(), PipelineStatusEnum.SUCCESS, PipelineStatusEnum.SUCCESS.getDesc());
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.AppGo.BUILD)
public class PipelineNodeBuildGoJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.AppJava.BUILD)
public class PipelineNodeBuildJavaJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.AppPython.BUILD)
public class PipelineNodeBuildPythonJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.DEPLOY_APPROVE)
public class PipelineNodeDeployApproveJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.AppGo.DEPLOY)
public class PipelineNodeDeployGoJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.AppJava.DEPLOY)
public class PipelineNodeDeployJavaJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.AppPython.DEPLOY)
public class PipelineNodeDeployPythonJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.IMAGE_SCAN)
public class PipelineNodeImageScanJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,63 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.MERGE_BRANCH)
public class PipelineNodeMergeBranchJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
pipelineInstanceNodeDetailService.addLog(pipelineInstanceId, contextArgs, "集成区分支 xxxxxx 合并到release分支成功", PipelineStatusEnum.SUCCESS, "");
return PipelineNodeJobExecuteResult.success();
}
}
@@ -1,45 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.MERGE_CONFIRM)
public class PipelineNodeMergeConfirmJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult = new PipelineNodeJobExecuteResult();
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
}
@@ -1,62 +0,0 @@
package cn.odboy.devops.job.app;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineNodeBizCodeConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.constant.pipeline.PipelineTypeEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobExecutor;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.service.pipeline.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import cn.odboy.framework.exception.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
@RequiredArgsConstructor
@Service(value = PipelineNodeBizCodeConst.MERGE_MASTER)
public class PipelineNodeMergeMasterJob implements PipelineNodeJobExecutor {
private final PipelineTemplateService pipelineTemplateService;
private final PipelineInstanceService pipelineInstanceService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
@Override
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult execute(Map<String, Object> contextArgs) throws BadRequestException {
String nodeName = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_NAME_KEY, "");
PipelineInstanceTb pipelineInstance = (PipelineInstanceTb) contextArgs.get(PipelineConst.INSTANCE_KEY);
PipelineNodeJobExecuteResult executeResult;
try {
PipelineTemplateTb pipelineTemplate = pipelineTemplateService.getPipelineTemplateById(pipelineInstance.getPipelineTemplateId());
PipelineTypeEnum pipelineType = PipelineTypeEnum.getByCode(pipelineInstance.getType());
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s开始", nodeName), PipelineStatusEnum.SUCCESS, "");
switch (pipelineType) {
case BACKEND:
executeResult = handleBackend(pipelineTemplate, pipelineInstance, contextArgs);
break;
default:
executeResult = PipelineNodeJobExecuteResult.success();
break;
}
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s成功", nodeName), PipelineStatusEnum.SUCCESS, "");
return executeResult;
} catch (Exception e) {
pipelineInstanceNodeDetailService.addLog(pipelineInstance.getPipelineInstanceId(), contextArgs, String.format("%s失败", nodeName), PipelineStatusEnum.FAIL, e.getMessage());
throw e;
}
}
@Transactional(rollbackFor = Exception.class)
public PipelineNodeJobExecuteResult handleBackend(PipelineTemplateTb pipelineTemplate, PipelineInstanceTb pipelineInstance, Map<String, Object> contextArgs) {
Long pipelineInstanceId = pipelineInstance.getPipelineInstanceId();
String language = pipelineTemplate.getLanguage();
String env = pipelineInstance.getEnv();
String appName = pipelineInstance.getAppName();
return PipelineNodeJobExecuteResult.success();
}
}
@@ -0,0 +1,16 @@
package cn.odboy.devops.service;
import cn.odboy.devops.dal.dataobject.PipelineInstanceNodeDetailTb;
import com.anwen.mongo.service.IService;
/**
* <p>
* 流水线实例节点明细
* </p>
*
* @author codegen
* @since 2025-06-26
*/
public interface PipelineInstanceNodeDetailService extends IService<PipelineInstanceNodeDetailTb> {
}
@@ -0,0 +1,18 @@
package cn.odboy.devops.service;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.dal.dataobject.PipelineInstanceNodeTb;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
import com.anwen.mongo.service.IService;
/**
* 流水线实例节点明细
*
* @author odboy
* @date 2025-07-20
*/
public interface PipelineInstanceNodeService extends IService<PipelineInstanceNodeTb> {
void createPipelineInstanceDetail(PipelineInstanceTb pipelineInstanceTb);
void updatePipelineInstanceNodeByArgs(Long instanceId, String code, PipelineStatusEnum pipelineStatusEnum, String msg);
PipelineInstanceNodeTb getPipelineInstanceNodeByArgs(Long instanceId, String code);
}
@@ -0,0 +1,15 @@
package cn.odboy.devops.service;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
/**
* <p>
* 流水线实例服务
* </p>
*
* @author odboy
* @since 2025-06-26
*/
public interface PipelineInstanceService {
void start(PipelineInstanceTb pipelineInstanceTb);
}
@@ -1,7 +1,7 @@
package cn.odboy.devops.service.pipeline;
package cn.odboy.devops.service;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.dal.mysql.pipeline.PipelineTemplateMapper;
import cn.odboy.devops.dal.dataobject.PipelineTemplateTb;
import cn.odboy.devops.dal.mysql.PipelineTemplateMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -0,0 +1,42 @@
package cn.odboy.devops.service.impl;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.dal.dataobject.PipelineInstanceNodeDetailTb;
import cn.odboy.devops.service.PipelineInstanceNodeDetailService;
import com.anwen.mongo.conditions.query.LambdaQueryChainWrapper;
import com.anwen.mongo.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Date;
@Slf4j
@Service
public class PipelineInstanceNodeDetailServiceImpl extends ServiceImpl<PipelineInstanceNodeDetailTb> implements PipelineInstanceNodeDetailService {
public void addLog(String nodeId, Integer nodeIndex, String nodeCode, String stepName, PipelineStatusEnum status, String stepMsg) {
PipelineInstanceNodeDetailTb record = getPipelineInstanceNodeDetailByArgs(nodeId, nodeCode, stepName);
if (record != null) {
record.setStepStatus(status.getCode());
record.setStepMsg(stepMsg);
updateById(record);
return;
}
record = new PipelineInstanceNodeDetailTb();
record.setNodeId(nodeId);
record.setStartTime(new Date());
record.setNodeIndex(nodeIndex);
record.setNodeCode(nodeCode);
record.setStepName(stepName);
record.setStepStatus(status.getCode());
record.setStepMsg(stepMsg);
save(record);
}
public PipelineInstanceNodeDetailTb getPipelineInstanceNodeDetailByArgs(String nodeId, String nodeCode, String stepName) {
return one(new LambdaQueryChainWrapper<>(getBaseMapper(), PipelineInstanceNodeDetailTb.class)
.eq(PipelineInstanceNodeDetailTb::getNodeId, nodeId).eq(PipelineInstanceNodeDetailTb::getNodeCode, nodeCode)
.eq(PipelineInstanceNodeDetailTb::getStepName, stepName)
);
}
}
@@ -0,0 +1,60 @@
package cn.odboy.devops.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.dal.dataobject.PipelineInstanceNodeTb;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.devops.service.PipelineInstanceNodeService;
import com.alibaba.fastjson2.JSON;
import com.anwen.mongo.conditions.query.LambdaQueryChainWrapper;
import com.anwen.mongo.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class PipelineInstanceNodeServiceImpl extends ServiceImpl<PipelineInstanceNodeTb> implements PipelineInstanceNodeService {
@Override
public void createPipelineInstanceDetail(PipelineInstanceTb pipelineInstanceTb) {
String templateContent = pipelineInstanceTb.getTemplateContent();
List<PipelineNodeTemplateVo> pipelineNodeTemplateVos = JSON.parseArray(templateContent, PipelineNodeTemplateVo.class);
if (CollUtil.isNotEmpty(pipelineNodeTemplateVos)) {
List<PipelineInstanceNodeTb> records = new ArrayList<>();
for (PipelineNodeTemplateVo pipelineNodeTemplateVo : pipelineNodeTemplateVos) {
PipelineInstanceNodeTb record = new PipelineInstanceNodeTb();
record.setInstanceId(pipelineInstanceTb.getInstanceId());
record.setName(pipelineNodeTemplateVo.getName());
record.setCode(pipelineNodeTemplateVo.getCode());
record.setType(pipelineNodeTemplateVo.getType());
record.setDetailType(pipelineNodeTemplateVo.getDetailType());
record.setParameters(pipelineNodeTemplateVo.getParameters());
record.setClick(pipelineNodeTemplateVo.getClick());
record.setRetry(pipelineNodeTemplateVo.getRetry());
record.setButtons(pipelineNodeTemplateVo.getButtons());
records.add(record);
}
saveBatch(records);
}
}
@Override
public void updatePipelineInstanceNodeByArgs(Long instanceId, String code, PipelineStatusEnum pipelineStatusEnum, String msg) {
PipelineInstanceNodeTb pipelineInstanceNode = getPipelineInstanceNodeByArgs(instanceId, code);
pipelineInstanceNode.setStartTime(new Date());
pipelineInstanceNode.setCurrentNodeStatus(pipelineStatusEnum.getCode());
pipelineInstanceNode.setCurrentNodeMsg(msg);
updateById(pipelineInstanceNode);
}
public PipelineInstanceNodeTb getPipelineInstanceNodeByArgs(Long instanceId, String code) {
return one(new LambdaQueryChainWrapper<>(getBaseMapper(), PipelineInstanceNodeTb.class)
.eq(PipelineInstanceNodeTb::getInstanceId, instanceId)
.eq(PipelineInstanceNodeTb::getCode, code)
);
}
}
@@ -0,0 +1,114 @@
package cn.odboy.devops.service.impl;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.dal.dataobject.PipelineInstanceNodeTb;
import cn.odboy.devops.dal.dataobject.PipelineInstanceTb;
import cn.odboy.devops.dal.mysql.PipelineInstanceMapper;
import cn.odboy.devops.dal.redis.PipelineInstanceDAO;
import cn.odboy.devops.framework.pipeline.core.PipelineJobManage;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.devops.service.PipelineInstanceNodeDetailService;
import cn.odboy.devops.service.PipelineInstanceNodeService;
import cn.odboy.devops.service.PipelineInstanceService;
import cn.odboy.framework.exception.BadRequestException;
import com.alibaba.fastjson2.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class PipelineInstanceServiceImpl implements PipelineInstanceService {
private final PipelineJobManage pipelineJobManage;
private final PipelineInstanceMapper pipelineInstanceMapper;
private final PipelineInstanceNodeService pipelineInstanceNodeService;
private final PipelineInstanceNodeDetailService pipelineInstanceNodeDetailService;
private final PipelineInstanceDAO pipelineInstanceDAO;
@Override
public void start(PipelineInstanceTb pipelineInstanceTb) {
if (pipelineInstanceDAO.lock(pipelineInstanceTb)) {
throw new BadRequestException("流水线运行中,无法重复执行");
}
ThreadUtil.execAsync(() -> innerStart(pipelineInstanceTb));
}
public void innerStart(PipelineInstanceTb pipelineInstanceTb) {
// 雪花id
pipelineInstanceTb.setInstanceId(IdUtil.getSnowflakeNextId());
pipelineInstanceTb.setStatus(PipelineStatusEnum.PENDING.getCode());
// 创建实例
pipelineInstanceMapper.insert(pipelineInstanceTb);
// 创建实例明细
pipelineInstanceNodeService.createPipelineInstanceDetail(pipelineInstanceTb);
// 流水线节点模板
String templateContent = pipelineInstanceTb.getTemplateContent();
List<PipelineNodeTemplateVo> pipelineNodeTemplateVos = JSON.parseArray(templateContent, PipelineNodeTemplateVo.class);
Long instanceId = pipelineInstanceTb.getInstanceId();
// 流水线实例状态(默认是成功的)
PipelineStatusEnum pipelineStatusEnum = PipelineStatusEnum.SUCCESS;
try {
pipelineInstanceTb.setStatus(PipelineStatusEnum.RUNNING.getCode());
pipelineInstanceMapper.updateById(pipelineInstanceTb);
// 依次执行流水线节点任务
for (PipelineNodeTemplateVo pipelineNodeTemplateVo : pipelineNodeTemplateVos) {
try {
pipelineJobManage.startJob(pipelineInstanceTb, pipelineNodeTemplateVo);
pipelineInstanceTb.setCurrentNode(pipelineNodeTemplateVo.getCode());
pipelineInstanceTb.setCurrentNodeStatus(PipelineStatusEnum.RUNNING.getCode());
pipelineInstanceMapper.updateById(pipelineInstanceTb);
// 监听节点执行状态
while (true) {
ThreadUtil.safeSleep(2000);
PipelineInstanceNodeTb pipelineInstanceNode = pipelineInstanceNodeService.getPipelineInstanceNodeByArgs(instanceId, pipelineNodeTemplateVo.getCode());
if (PipelineStatusEnum.SUCCESS.getCode().equals(pipelineInstanceNode.getCurrentNodeStatus())) {
pipelineStatusEnum = PipelineStatusEnum.SUCCESS;
pipelineInstanceTb.setCurrentNodeStatus(pipelineStatusEnum.getCode());
pipelineInstanceMapper.updateById(pipelineInstanceTb);
break;
}
if (PipelineStatusEnum.FAIL.getCode().equals(pipelineInstanceNode.getCurrentNodeStatus())) {
pipelineStatusEnum = PipelineStatusEnum.FAIL;
pipelineInstanceTb.setCurrentNodeStatus(pipelineStatusEnum.getCode());
pipelineInstanceMapper.updateById(pipelineInstanceTb);
break;
}
}
if (pipelineStatusEnum.equals(PipelineStatusEnum.FAIL)) {
// 节点失败,全失败
break;
}
ThreadUtil.safeSleep(2000);
} catch (Exception e) {
log.error("流水线节点运行失败", e);
pipelineInstanceTb.setStatus(PipelineStatusEnum.FAIL.getCode());
pipelineInstanceMapper.updateById(pipelineInstanceTb);
}
}
pipelineInstanceTb.setStatus(pipelineStatusEnum.getCode());
pipelineInstanceMapper.updateById(pipelineInstanceTb);
pipelineInstanceDAO.unLock(pipelineInstanceTb);
} catch (Exception e) {
log.error("流水线运行失败", e);
pipelineInstanceTb.setStatus(PipelineStatusEnum.FAIL.getCode());
pipelineInstanceMapper.updateById(pipelineInstanceTb);
pipelineInstanceDAO.unLock(pipelineInstanceTb);
}
}
public void restart(PipelineInstanceTb pipelineInstanceTb) {
boolean exist = pipelineInstanceDAO.lock(pipelineInstanceTb);
if (exist) {
if (!PipelineStatusEnum.FAIL.getCode().equals(pipelineInstanceTb.getCurrentNodeStatus())) {
throw new BadRequestException("流水线执行中,无法重启流水线");
}
log.info("解锁流水线, {}", JSON.toJSONString(pipelineInstanceTb));
pipelineInstanceDAO.unLock(pipelineInstanceTb);
}
}
}
@@ -1,59 +0,0 @@
package cn.odboy.devops.service.pipeline;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceNodeDetailTb;
import cn.odboy.devops.dal.mysql.pipeline.PipelineInstanceNodeDetailMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.Map;
/**
* <p>
* 流水线实例节点明细 服务实现类
* </p>
*
* @author codegen
* @since 2025-06-26
*/
@Service
@RequiredArgsConstructor
public class PipelineInstanceNodeDetailService {
private final PipelineInstanceNodeDetailMapper pipelineInstanceNodeDetailMapper;
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void addLog(Long pipelineInstanceId, Map<String, Object> contextArgs, String stepName, PipelineStatusEnum status, String stepMsg) {
Integer nodeIndex = (Integer) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_INDEX_KEY, null);
String nodeCode = (String) contextArgs.getOrDefault(PipelineConst.INSTANCE_NODE_CODE_KEY, null);
PipelineInstanceNodeDetailTb record = getPipelineInstanceNodeDetailByArgs(pipelineInstanceId, nodeCode, stepName);
if (record == null) {
record = new PipelineInstanceNodeDetailTb();
record.setPipelineInstanceId(pipelineInstanceId);
record.setStartTime(new Date());
record.setNodeIndex(nodeIndex);
record.setNodeCode(nodeCode);
record.setStepName(stepName);
record.setStepStatus(status.getCode());
pipelineInstanceNodeDetailMapper.insert(record);
} else {
PipelineInstanceNodeDetailTb updRecord = new PipelineInstanceNodeDetailTb();
updRecord.setId(record.getId());
updRecord.setStepStatus(status.getCode());
pipelineInstanceNodeDetailMapper.updateById(updRecord);
}
}
private PipelineInstanceNodeDetailTb getPipelineInstanceNodeDetailByArgs(Long pipelineInstanceId, String nodeCode, String stepName) {
return pipelineInstanceNodeDetailMapper.selectOne(new LambdaQueryWrapper<PipelineInstanceNodeDetailTb>()
.eq(PipelineInstanceNodeDetailTb::getPipelineInstanceId, pipelineInstanceId)
.eq(PipelineInstanceNodeDetailTb::getNodeCode, nodeCode)
.eq(PipelineInstanceNodeDetailTb::getStepName, stepName)
);
}
}
@@ -1,121 +0,0 @@
package cn.odboy.devops.service.pipeline;
import cn.odboy.devops.constant.pipeline.PipelineConst;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.mysql.pipeline.PipelineInstanceMapper;
import cn.odboy.devops.framework.pipeline.core.PipelineNodeJobRunnable;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeJobExecuteResult;
import cn.odboy.devops.framework.pipeline.model.PipelineNodeTemplateVo;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.util.CsJsonUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
/**
* <p>
* 流水线实例 服务实现类
* </p>
*
* @author codegen
* @since 2025-06-26
*/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Lazy)
public class PipelineInstanceService {
private final PipelineInstanceMapper pipelineInstanceMapper;
public PipelineInstanceTb getPipelineInstance(long pipelineInstanceId) {
return pipelineInstanceMapper.selectOne(new LambdaQueryWrapper<PipelineInstanceTb>()
.eq(PipelineInstanceTb::getPipelineInstanceId, pipelineInstanceId)
);
}
@Transactional(rollbackFor = Exception.class)
public void createPipelineInstance(PipelineInstanceTb pipelineInstanceTb) {
pipelineInstanceMapper.insert(pipelineInstanceTb);
}
/**
* 新事务中执行,就算抛出异常,也不会丢失执行状态
*/
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void updateStatusByInstanceId(PipelineStatusEnum status, long pipelineInstanceId) {
pipelineInstanceMapper.updateStatusByInstanceId(status.getCode(), pipelineInstanceId);
}
@Transactional(rollbackFor = Exception.class)
public void startPipeline(ThreadPoolTaskExecutor executor, JobExecutionContext context) {
JobDataMap mergedJobDataMap = context.getMergedJobDataMap();
// 获取流水线实例
long pipelineInstanceId = mergedJobDataMap.getLong(PipelineConst.INSTANCE_ID_KEY);
PipelineInstanceTb pipelineInstance = getPipelineInstance(pipelineInstanceId);
if (pipelineInstance == null) {
log.info("流水线实例不存在, instanceId={}", pipelineInstanceId);
return;
}
String pipelineTemplate = pipelineInstance.getPipelineTemplate();
// 流水线节点模板
List<PipelineNodeTemplateVo> pipelineNodeTemplateVos = JSON.parseArray(pipelineTemplate, PipelineNodeTemplateVo.class);
// 流水线上下文参数
Map<String, Object> contextArgs = CsJsonUtil.toMap(pipelineInstance.getContext(), String.class, Object.class);
// 放置额外的参数
contextArgs.put(PipelineConst.INSTANCE_KEY, pipelineInstance);
// 任务重试标记
Object retryNodeIndexObj = mergedJobDataMap.getOrDefault(PipelineConst.INSTANCE_RETRY_NODE_INDEX_KEY, null);
Integer retryNodeIndexValue = null;
if (retryNodeIndexObj != null) {
retryNodeIndexValue = (Integer) retryNodeIndexObj;
}
// 初始化节点明细
boolean isExecuteSuccess = true;
updateStatusByInstanceId(PipelineStatusEnum.RUNNING, pipelineInstanceId);
for (int i = 0; i < pipelineNodeTemplateVos.size(); i++) {
if (retryNodeIndexValue != null && i < retryNodeIndexValue) {
// 跳过非重试节点
continue;
}
try {
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());
// 执行任务
PipelineNodeJobRunnable pipelineNodeJobRunnable = new PipelineNodeJobRunnable(PipelineConst.EXECUTOR_PREFIX + code, contextArgs);
Future<?> future = executor.submit(pipelineNodeJobRunnable);
PipelineNodeJobExecuteResult executeResult = (PipelineNodeJobExecuteResult) future.get();
updateCurrentNodeByInstanceId(code, executeResult.getStatus(), pipelineInstanceId);
if (!PipelineStatusEnum.SUCCESS.equals(executeResult.getStatus())) {
throw new BadRequestException(executeResult.getMessage());
}
} catch (Exception e) {
log.error("流水线节点任务执行失败", e);
isExecuteSuccess = false;
break;
}
}
// 任务执行结果
updateStatusByInstanceId(isExecuteSuccess ? PipelineStatusEnum.SUCCESS : PipelineStatusEnum.FAIL, pipelineInstanceId);
}
@Transactional(rollbackFor = Exception.class)
public void updateCurrentNodeByInstanceId(String code, PipelineStatusEnum status, long pipelineInstanceId) {
pipelineInstanceMapper.updateCurrentNodeByInstanceId(code, status.getCode(), pipelineInstanceId);
}
}
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.odboy.devops.dal.mysql.pipeline.PipelineInstanceMapper">
<update id="updateStatusByInstanceId">
UPDATE pipeline_instance
SET `status` = #{status}
WHERE pipeline_instance_id = #{pipelineInstanceId}
</update>
<update id="updateCurrentNodeByInstanceId">
UPDATE pipeline_instance
SET `current_node` = #{code},
current_node_status=#{status}
WHERE pipeline_instance_id = #{pipelineInstanceId}
</update>
</mapper>
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.odboy.devops.dal.mysql.pipeline.PipelineInstanceNodeDetailMapper">
</mapper>
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.odboy.devops.dal.mysql.pipeline.PipelineTemplateMapper">
</mapper>
@@ -1,14 +1,18 @@
package cn.odboy;
import cn.odboy.framework.context.CsBootApplication;
import com.anwen.mongo.config.MongoPlusAutoConfiguration;
import com.anwen.mongo.config.OverrideMongoConfiguration;
import io.swagger.annotations.Api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import java.net.UnknownHostException;
@Api(hidden = true)
@SpringBootApplication
@SpringBootApplication(exclude = OverrideMongoConfiguration.class)
@Import(MongoPlusAutoConfiguration.class)
public class AppRun extends CsBootApplication {
public static void main(String[] args) throws UnknownHostException {
@@ -49,6 +49,14 @@ spring:
repositories:
# 是否启用Redis存储(关闭防止出现 Multiple Spring Data modules found, entering strict repository configuration mode)
enabled: false
# mongodb:
# auto-index-creation: true
# host: 192.168.100.128 #指定MongoDB服务地址
# port: 27017 #指定端口,默认就为27017
# database: admin #指定使用的数据库(集合)
# authentication-database: admin # 登录认证的逻辑库名
# username: admin #用户名
# password: 123456 #密码
datasource:
druid:
db-type: com.alibaba.druid.pool.DruidDataSource
@@ -140,7 +148,7 @@ mybatis-plus:
check-config-location: true
# MyBatis Mapper 所对应的 XML 文件位置
# Maven 多模块项目的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML 文件)
mapper-locations: classpath*:/mapper/**/*.xml
mapper-locations: classpath*:mapper/**/*.xml
# MyBatis-Plus 全局策略中的 DB 策略配置
global-config:
db-config:
@@ -225,3 +233,21 @@ app:
#logging:
# level:
# root: debug
mongo-plus:
data:
mongodb:
database: cutejava
connectTimeoutMS: 50000
host: 192.168.100.128
port: 27017
retry-writes: false
username: cutejava
password: 123456
authentication-database: cutejava
log: true
pretty: true
configuration:
field:
ignoring-null: false
auto-create-index: true
auto-convert-object-id: true
@@ -1,78 +0,0 @@
package cn.odboy.pipeline;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import cn.odboy.devops.constant.pipeline.PipelineStatusEnum;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineInstanceTb;
import cn.odboy.devops.dal.dataobject.pipeline.PipelineTemplateTb;
import cn.odboy.devops.framework.pipeline.core.PipelineJobManage;
import cn.odboy.devops.service.pipeline.PipelineInstanceService;
import cn.odboy.devops.service.pipeline.PipelineTemplateService;
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 流水线正式测试
*
* @author odboy
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PipelineReleaseTests {
@Autowired
private PipelineJobManage pipelineJobManage;
@Autowired
private PipelineTemplateService pipelineTemplateService;
@Autowired
private PipelineInstanceService pipelineInstanceService;
/**
* 默认模板由人工维护,百分百不会空<br/>
* 介意又不想配置的自行面壁
*/
@Test
public void contextLoads() {
// 输入参数
Date nowTime = new Date();
String createBy = "admin";
String appName = "test";
String envCode = "daily";
Map<String, Object> context = new HashMap<>();
context.put("createBy", createBy);
// 获取模板
PipelineTemplateTb pipelineTemplateTb = pipelineTemplateService.getPipelineTemplateById(4L);
// 创建流水线实例
PipelineInstanceTb pipelineInstanceTb = new PipelineInstanceTb();
pipelineInstanceTb.setPipelineTemplateId(pipelineTemplateTb.getId());
pipelineInstanceTb.setPipelineInstanceName("流水线测试");
pipelineInstanceTb.setPipelineInstanceId(IdUtil.getSnowflakeNextId());
pipelineInstanceTb.setCreateTime(nowTime);
pipelineInstanceTb.setCreateBy(createBy);
pipelineInstanceTb.setUpdateTime(nowTime);
pipelineInstanceTb.setType(pipelineTemplateTb.getType());
pipelineInstanceTb.setAppName(appName);
pipelineInstanceTb.setEnv(envCode);
pipelineInstanceTb.setStatus(PipelineStatusEnum.PENDING.getCode());
pipelineInstanceTb.setCurrentNode(null);
pipelineInstanceTb.setCurrentNodeStatus(null);
pipelineInstanceTb.setContext(JSON.toJSONString(context));
pipelineInstanceTb.setPipelineTemplate(pipelineTemplateTb.getTemplate());
pipelineInstanceService.createPipelineInstance(pipelineInstanceTb);
pipelineJobManage.startJob(pipelineInstanceTb);
ThreadUtil.safeSleep(1000 * 60 * 60 * 24);
}
public static void main(String[] args) {
System.err.println("nanoId=" + IdUtil.nanoId());
System.err.println("objectId=" + IdUtil.objectId());
System.err.println("snowflakeNextId=" + IdUtil.getSnowflakeNextIdStr());
System.err.println("fastUUID=" + IdUtil.fastUUID());
System.err.println("fastSimpleUUID=" + IdUtil.fastSimpleUUID());
}
}
+14
View File
@@ -0,0 +1,14 @@
### 创建数据库和用户
```sql
use
cutejava
db.createUser({
user: "cutejava",
pwd: "123456",
roles: [{
role: "dbOwner",
db: "cutejava"
}]
})
```
@@ -0,0 +1,24 @@
services:
minio:
# MinIO 社区版在 2025 年 5 月 24 日的更新中移除了 Web 管理控制台功能
image: minio/minio:RELEASE.2025-04-22T22-12-26Z # 原镜像`minio/minio:latest`
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./minio/data:/data"
- "./minio/minio:/minio"
- "./minio/config:/root/.minio"
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
#MINIO_PROMETHEUS_AUTH_TYPE: "public"
MINIO_ACCESS_KEY: "root" # 登录账号
MINIO_SECRET_KEY: "lm,101208..,." # 登录密码
command: server /data --console-address ":9001"
logging:
driver: "json-file"
options:
max-size: "50m"
ports: # 映射端口
- "9000:9000" # 文件上传&预览端口
- "9001:9001" # 控制台访问端口
+12
View File
@@ -0,0 +1,12 @@
### MinIO
https://min.io
```shell
docker-compose -f docker-compose-minio.yml -p minio20250422 up -d
```
> tips: 不要用`127.0.0.1`或`localhost`访问,用`ip`
访问地址:[`ip地址:9090/minio`](http://192.168.101.88:9090/minio)
登录账号密码:`admin/password`
@@ -0,0 +1,38 @@
# 网桥mongo -> 方便相互通讯
#networks:
# mongo:
services:
# mongodb
mongodb:
image: registry.cn-hangzhou.aliyuncs.com/zhengqing/mongo:4.4.6 # 原镜像`mongo:4.4.6`
restart: unless-stopped
#container_name: mongodb
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: 123456
MONGO_DATA_DIR: /data/db
MONGO_LOG_DIR: /data/logs
volumes:
- ./mongodb/db:/data/db
- ./mongodb/log:/data/log
ports:
- "27017:27017"
#networks:
# - mongo
# 可视化图形工具
#adminmongo:
# image: registry.cn-hangzhou.aliyuncs.com/zhengqing/adminmongo # 原镜像`mrvautin/adminmongo`
# restart: unless-stopped
# container_name: adminmongo
# environment:
# - HOST=0.0.0.0
#depends_on:
# - 'mongodb'
# links:
# - mongodb
#ports:
# - "1234:1234"
#networks:
# - mongo
+8
View File
@@ -0,0 +1,8 @@
### MongoDB - 基于文档的通用分布式数据库
```shell
docker-compose -f docker-compose-mongodb.yml -p mongodb up -d
```
访问地址:[`http://ip地址:1234`](http://127.0.0.1:1234)
Connection string:`mongodb://admin:123456@ip地址:27017`
@@ -0,0 +1,21 @@
# 可参考: https://hub.docker.com/_/mysql
version: '3'
services:
mysql:
image: registry.cn-hangzhou.aliyuncs.com/zhengqing/mysql:8.0 # 原镜像`mysql:8.0`
container_name: mysql8 # 容器名为'mysql8'
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./mysql/my.cnf:/etc/mysql/my.cnf"
- "./mysql/data:/var/lib/mysql"
# - "./mysql/conf.d:/etc/mysql/conf.d"
- "./mysql/mysql-files:/var/lib/mysql-files"
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
MYSQL_ROOT_PASSWORD: lm,101208..,. # 设置root用户密码
MYSQL_DATABASE: demo # 初始化的数据库名称
privileged: true
user: root
ports: # 映射端口
- "23306:3306"
+18
View File
@@ -0,0 +1,18 @@
# 服务端参数配置
[mysqld]
user=mysql # MySQL启动用户
default-storage-engine=INNODB # 创建新表时将使用的默认存储引擎
character-set-server=utf8mb4 # 设置mysql服务端默认字符集
collation-server=utf8mb4_0900_ai_ci # 数据库字符集对应一些排序等规则,注意要和character-set-server对应
default-authentication-plugin=mysql_native_password
max_connections=1000 # 允许最大连接数
max_connect_errors=100 # 最大错误连接数
[mysql]
default-character-set=utf8mb4
[client]
default-character-set=utf8mb4 # 设置mysql客户端默认字符集
+5
View File
@@ -0,0 +1,5 @@
### MySQL
```shell
docker-compose -f docker-compose.yml -p mysql8 up -d
```
@@ -0,0 +1,14 @@
version: '3'
services:
redis:
image: registry.cn-hangzhou.aliyuncs.com/zhengqing/redis:7.0.5 # 镜像'redis:7.0.5'
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
command: redis-server /etc/redis/redis.conf # 启动redis服务并添加密码为:123456,默认不开启redis-aof方式持久化配置
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./redis/data:/data"
- "./redis/config/redis.conf:/etc/redis/redis.conf" # `redis.conf`文件内容`http://download.redis.io/redis-stable/redis.conf`
ports: # 映射端口
- "26379:6379"
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
### Redis
```shell
# 当前目录下所有文件赋予权限(读、写、执行)
chmod -R 777 ./redis
# 运行 -- 单机模式
docker-compose -f docker-compose-redis.yml -p redis7 up -d
```
###### 连接redis
```shell
# 密码为123456
docker exec -it redis redis-cli -a 123456
```
+12
View File
@@ -350,6 +350,18 @@
<artifactId>c3p0</artifactId>
<version>0.10.1</version>
</dependency>
<!-- mongoplus依赖 -->
<dependency>
<groupId>com.gitee.anwena</groupId>
<artifactId>mongo-plus-boot-starter</artifactId>
<!-- <version>2.0.9.2</version>-->
<version>2.1.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
<build>