通用解析
This commit is contained in:
parent
205c87dc5a
commit
631c048c95
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener.ListenerConfig;
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
@ -13,25 +14,47 @@ public class BaseNodeConfig {
|
||||
/**
|
||||
* 监听器配置列表
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器配置",
|
||||
description = "工作流节点的事件监听器配置列表"
|
||||
)
|
||||
private List<ListenerConfig> listeners;
|
||||
|
||||
/**
|
||||
* 是否异步
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "是否异步",
|
||||
description = "节点是否以异步方式执行",
|
||||
defaultValue = "false"
|
||||
)
|
||||
private Boolean async;
|
||||
|
||||
/**
|
||||
* 是否独占
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "是否独占",
|
||||
description = "节点是否以独占方式执行",
|
||||
defaultValue = "true"
|
||||
)
|
||||
private Boolean exclusive;
|
||||
|
||||
/**
|
||||
* 自定义属性
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "自定义属性",
|
||||
description = "节点的自定义属性配置"
|
||||
)
|
||||
private Map<String, Object> customProperties;
|
||||
|
||||
/**
|
||||
* 文档说明
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "文档说明",
|
||||
description = "节点的详细文档说明"
|
||||
)
|
||||
private String documentation;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.util.Map;
|
||||
@ -13,25 +14,54 @@ public class EndEventConfig extends EventNodeConfig {
|
||||
/**
|
||||
* 结束类型(normal, terminate, error, etc.)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "结束类型",
|
||||
description = "工作流的结束类型",
|
||||
required = true,
|
||||
enumValues = {"NORMAL", "TERMINATE", "ERROR"},
|
||||
enumNames = {"正常结束", "强制终止", "错误结束"},
|
||||
defaultValue = "NORMAL"
|
||||
)
|
||||
private String terminateType;
|
||||
|
||||
/**
|
||||
* 错误代码(当terminateType为error时使用)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "错误代码",
|
||||
description = "当结束类型为错误结束时的错误代码",
|
||||
required = false
|
||||
)
|
||||
private String errorCode;
|
||||
|
||||
/**
|
||||
* 错误消息(当terminateType为error时使用)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "错误消息",
|
||||
description = "当结束类型为错误结束时的错误描述信息",
|
||||
required = false
|
||||
)
|
||||
private String errorMessage;
|
||||
|
||||
/**
|
||||
* 结束时的输出变量
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "输出变量",
|
||||
description = "工作流结束时的输出变量",
|
||||
required = false
|
||||
)
|
||||
private Map<String, Object> outputVariables;
|
||||
|
||||
/**
|
||||
* 是否终止所有活动分支
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "终止所有分支",
|
||||
description = "是否终止所有正在运行的并行分支",
|
||||
defaultValue = "false",
|
||||
required = false
|
||||
)
|
||||
private Boolean terminateAll;
|
||||
}
|
||||
|
||||
@ -1,16 +1,36 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 事件节点(如START、END)的基础配置
|
||||
*/
|
||||
@Data
|
||||
public class EventConfig {
|
||||
@SchemaProperty(
|
||||
title = "节点名称",
|
||||
description = "工作流节点的显示名称",
|
||||
required = true
|
||||
)
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@SchemaProperty(
|
||||
title = "节点描述",
|
||||
description = "工作流节点的详细描述"
|
||||
)
|
||||
private String description;
|
||||
|
||||
@SchemaProperty(
|
||||
title = "事件类型",
|
||||
description = "工作流事件的类型",
|
||||
enumValues = {"message", "signal", "timer", "error"},
|
||||
enumNames = {"消息事件", "信号事件", "定时事件", "错误事件"}
|
||||
)
|
||||
private String eventType;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ public class EventNodeConfig {
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "节点名称",
|
||||
description = "工作流节点的显示名称",
|
||||
required = true
|
||||
)
|
||||
private String name;
|
||||
@ -21,7 +22,8 @@ public class EventNodeConfig {
|
||||
* 节点描述
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "节点描述"
|
||||
title = "节点描述",
|
||||
description = "工作流节点的详细描述"
|
||||
)
|
||||
private String description;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import java.util.Map;
|
||||
|
||||
@ -11,20 +12,38 @@ public class FormConfig {
|
||||
/**
|
||||
* 表单Key
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "表单Key",
|
||||
description = "表单的唯一标识",
|
||||
required = true
|
||||
)
|
||||
private String formKey;
|
||||
|
||||
/**
|
||||
* 表单属性
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "表单属性",
|
||||
description = "表单的配置属性"
|
||||
)
|
||||
private Map<String, Object> properties;
|
||||
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "是否必填",
|
||||
description = "表单是否必须填写",
|
||||
defaultValue = "true"
|
||||
)
|
||||
private Boolean required;
|
||||
|
||||
/**
|
||||
* 表单验证规则
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "验证规则",
|
||||
description = "表单字段的验证规则"
|
||||
)
|
||||
private Map<String, Object> validations;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.util.Map;
|
||||
@ -14,53 +15,104 @@ public class GitCloneConfig extends TaskConfig {
|
||||
/**
|
||||
* 仓库URL
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "仓库URL",
|
||||
description = "Git仓库的URL地址",
|
||||
required = true
|
||||
)
|
||||
private String repositoryUrl;
|
||||
|
||||
/**
|
||||
* 分支或标签
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "分支或标签",
|
||||
description = "要克隆的分支、标签或提交ID",
|
||||
defaultValue = "main"
|
||||
)
|
||||
private String ref;
|
||||
|
||||
/**
|
||||
* 目标目录
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "目标目录",
|
||||
description = "代码克隆到的目标目录",
|
||||
required = true
|
||||
)
|
||||
private String targetDirectory;
|
||||
|
||||
/**
|
||||
* 是否递归克隆子模块
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "递归克隆子模块",
|
||||
description = "是否递归克隆Git子模块",
|
||||
defaultValue = "false"
|
||||
)
|
||||
private Boolean recursive;
|
||||
|
||||
/**
|
||||
* 克隆深度(0表示完整克隆)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "克隆深度",
|
||||
description = "克隆的历史深度,0表示完整克隆",
|
||||
defaultValue = "1",
|
||||
minimum = 0
|
||||
)
|
||||
private Integer depth;
|
||||
|
||||
/**
|
||||
* 身份验证类型(NONE, SSH_KEY, USERNAME_PASSWORD)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "身份验证类型",
|
||||
description = "Git仓库的身份验证方式",
|
||||
enumValues = {"NONE", "SSH_KEY", "USERNAME_PASSWORD"},
|
||||
enumNames = {"无验证", "SSH密钥", "用户名密码"},
|
||||
defaultValue = "NONE"
|
||||
)
|
||||
private String authenticationType;
|
||||
|
||||
/**
|
||||
* SSH私钥(当authenticationType为SSH_KEY时使用)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "SSH私钥",
|
||||
description = "SSH私钥内容(当身份验证类型为SSH密钥时使用)",
|
||||
format = "textarea"
|
||||
)
|
||||
private String sshPrivateKey;
|
||||
|
||||
/**
|
||||
* 用户名(当authenticationType为USERNAME_PASSWORD时使用)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "用户名",
|
||||
description = "Git仓库的用户名(当身份验证类型为用户名密码时使用)"
|
||||
)
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码或令牌(当authenticationType为USERNAME_PASSWORD时使用)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "密码或令牌",
|
||||
description = "Git仓库的密码或访问令牌(当身份验证类型为用户名密码时使用)"
|
||||
)
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Git配置
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "Git配置",
|
||||
description = "额外的Git配置选项"
|
||||
)
|
||||
private Map<String, String> gitConfig;
|
||||
|
||||
public GitCloneConfig() {
|
||||
setTaskType("gitCloneTask");
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,5 +41,9 @@ public class NodeTypeConfig {
|
||||
/**
|
||||
* 节点配置Schema
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "配置Schema",
|
||||
description = "节点类型的配置Schema定义"
|
||||
)
|
||||
private JsonNode configSchema;
|
||||
}
|
||||
|
||||
@ -15,7 +15,9 @@ public class StartEventConfig extends EventNodeConfig {
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "触发器类型",
|
||||
description = "工作流的触发方式"
|
||||
description = "工作流的触发方式",
|
||||
enumValues = {"manual", "timer", "signal", "message"},
|
||||
enumNames = {"手动触发", "定时触发", "信号触发", "消息触发"}
|
||||
)
|
||||
private String triggerType;
|
||||
|
||||
@ -29,7 +31,11 @@ public class StartEventConfig extends EventNodeConfig {
|
||||
private String formKey;
|
||||
|
||||
/**
|
||||
* 初始化变量
|
||||
* 发起人
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "发起人",
|
||||
description = "工作流的发起人"
|
||||
)
|
||||
private String initiator;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import java.util.Map;
|
||||
|
||||
@ -11,11 +12,23 @@ public class TaskListener {
|
||||
/**
|
||||
* 监听器类型(如:class, expression, delegateExpression)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器类型",
|
||||
description = "监听器的实现类型",
|
||||
required = true,
|
||||
enumValues = {"class", "expression", "delegateExpression"},
|
||||
enumNames = {"Java类", "表达式", "代理表达式"}
|
||||
)
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 监听器实现(类名、表达式或代理表达式)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器实现",
|
||||
description = "监听器的具体实现(类名、表达式或代理表达式)",
|
||||
required = true
|
||||
)
|
||||
private String implementation;
|
||||
|
||||
/**
|
||||
@ -26,5 +39,9 @@ public class TaskListener {
|
||||
/**
|
||||
* 监听器字段
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器字段",
|
||||
description = "监听器的配置字段"
|
||||
)
|
||||
private Map<String, Object> fields;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import java.util.Map;
|
||||
|
||||
@ -11,15 +12,31 @@ public class BaseListener {
|
||||
/**
|
||||
* 监听器类型(class, expression, delegateExpression)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器类型",
|
||||
description = "监听器的实现类型",
|
||||
required = true,
|
||||
enumValues = {"class", "expression", "delegateExpression"},
|
||||
enumNames = {"Java类", "表达式", "代理表达式"}
|
||||
)
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 监听器实现(类名、表达式或代理表达式)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器实现",
|
||||
description = "监听器的具体实现(类名、表达式或代理表达式)",
|
||||
required = true
|
||||
)
|
||||
private String implementation;
|
||||
|
||||
/**
|
||||
* 监听器字段
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器字段",
|
||||
description = "监听器的配置字段"
|
||||
)
|
||||
private Map<String, Object> fields;
|
||||
}
|
||||
|
||||
@ -1,28 +1,45 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 事件监听器配置
|
||||
* 事件监听器
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EventListener extends BaseListener {
|
||||
public class EventListener extends TaskListener {
|
||||
/**
|
||||
* 事件类型
|
||||
* start: 事件开始
|
||||
* end: 事件结束
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "事件类型",
|
||||
description = "监听器的触发事件类型",
|
||||
required = true,
|
||||
enumValues = {"start", "end"},
|
||||
enumNames = {"事件开始", "事件结束"}
|
||||
)
|
||||
private String event;
|
||||
|
||||
/**
|
||||
* 是否中断事件
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "是否中断事件",
|
||||
description = "事件触发后是否中断当前活动",
|
||||
defaultValue = "false"
|
||||
)
|
||||
private Boolean cancelActivity;
|
||||
|
||||
/**
|
||||
* 事件抛出的变量
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "事件变量",
|
||||
description = "事件触发时抛出的变量名"
|
||||
)
|
||||
private String eventVariable;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ -14,15 +15,31 @@ public class EventListenerConfig extends ListenerConfig {
|
||||
* start: 事件开始
|
||||
* end: 事件结束
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "事件类型",
|
||||
description = "监听器的触发事件类型",
|
||||
required = true,
|
||||
enumValues = {"start", "end"},
|
||||
enumNames = {"事件开始", "事件结束"}
|
||||
)
|
||||
private String event;
|
||||
|
||||
/**
|
||||
* 是否中断事件
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "是否中断事件",
|
||||
description = "事件触发后是否中断当前活动",
|
||||
defaultValue = "false"
|
||||
)
|
||||
private Boolean cancelActivity;
|
||||
|
||||
/**
|
||||
* 事件抛出的变量
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "事件变量",
|
||||
description = "事件触发时抛出的变量名"
|
||||
)
|
||||
private String eventVariable;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import java.util.Map;
|
||||
|
||||
@ -11,15 +12,31 @@ public class ListenerConfig {
|
||||
/**
|
||||
* 监听器类型(class, expression, delegateExpression)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器类型",
|
||||
description = "监听器的实现类型",
|
||||
required = true,
|
||||
enumValues = {"class", "expression", "delegateExpression"},
|
||||
enumNames = {"Java类", "表达式", "代理表达式"}
|
||||
)
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 监听器实现(类名、表达式或代理表达式)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器实现",
|
||||
description = "监听器的具体实现(类名、表达式或代理表达式)",
|
||||
required = true
|
||||
)
|
||||
private String implementation;
|
||||
|
||||
/**
|
||||
* 监听器字段
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "监听器字段",
|
||||
description = "监听器的配置字段"
|
||||
)
|
||||
private Map<String, Object> fields;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ -18,15 +19,32 @@ public class TaskListener extends BaseListener {
|
||||
* update: 任务更新
|
||||
* timeout: 任务超时
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "事件类型",
|
||||
description = "任务监听器的触发事件类型",
|
||||
required = true,
|
||||
enumValues = {"create", "assignment", "complete", "delete", "update", "timeout"},
|
||||
enumNames = {"任务创建", "任务分配", "任务完成", "任务删除", "任务更新", "任务超时"}
|
||||
)
|
||||
private String event;
|
||||
|
||||
/**
|
||||
* 任务相关的用户或组
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "执行人",
|
||||
description = "任务相关的用户或组标识"
|
||||
)
|
||||
private String assignee;
|
||||
|
||||
/**
|
||||
* 任务优先级
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "优先级",
|
||||
description = "任务的优先级",
|
||||
minimum = 0,
|
||||
maximum = 100
|
||||
)
|
||||
private Integer priority;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.listener;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ -18,15 +19,32 @@ public class TaskListenerConfig extends ListenerConfig {
|
||||
* update: 任务更新
|
||||
* timeout: 任务超时
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "事件类型",
|
||||
description = "任务监听器的触发事件类型",
|
||||
required = true,
|
||||
enumValues = {"create", "assignment", "complete", "delete", "update", "timeout"},
|
||||
enumNames = {"任务创建", "任务分配", "任务完成", "任务删除", "任务更新", "任务超时"}
|
||||
)
|
||||
private String event;
|
||||
|
||||
/**
|
||||
* 任务相关的用户或组
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "执行人",
|
||||
description = "任务相关的用户或组标识"
|
||||
)
|
||||
private String assignee;
|
||||
|
||||
/**
|
||||
* 任务优先级
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "优先级",
|
||||
description = "任务的优先级",
|
||||
minimum = 0,
|
||||
maximum = 100
|
||||
)
|
||||
private Integer priority;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.script;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import java.util.Map;
|
||||
|
||||
@ -11,25 +12,52 @@ public class ScriptExecutionConfig {
|
||||
/**
|
||||
* 脚本内容
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "脚本内容",
|
||||
description = "需要执行的脚本内容",
|
||||
required = true,
|
||||
format = "textarea"
|
||||
)
|
||||
private String script;
|
||||
|
||||
/**
|
||||
* 工作目录
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "工作目录",
|
||||
description = "脚本执行的工作目录",
|
||||
defaultValue = "/tmp"
|
||||
)
|
||||
private String workingDirectory;
|
||||
|
||||
/**
|
||||
* 超时时间(秒)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "超时时间",
|
||||
description = "脚本执行的最大时间(秒)",
|
||||
minimum = 1,
|
||||
maximum = 3600,
|
||||
defaultValue = "300"
|
||||
)
|
||||
private Integer timeout;
|
||||
|
||||
/**
|
||||
* 环境变量
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "环境变量",
|
||||
description = "脚本执行时的环境变量"
|
||||
)
|
||||
private Map<String, String> environment;
|
||||
|
||||
/**
|
||||
* 成功退出码
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "成功退出码",
|
||||
description = "脚本执行成功时的退出码",
|
||||
defaultValue = "0"
|
||||
)
|
||||
private Integer successExitCode;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.script;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
@ -11,15 +12,33 @@ public class ScriptLanguageConfig {
|
||||
/**
|
||||
* 脚本语言类型
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "脚本语言",
|
||||
description = "脚本的语言类型",
|
||||
required = true,
|
||||
enumValues = {"shell", "python", "javascript", "groovy"},
|
||||
enumNames = {"Shell脚本 (已支持)", "Python脚本 (开发中)", "JavaScript脚本 (开发中)", "Groovy脚本 (开发中)"},
|
||||
defaultValue = "shell"
|
||||
)
|
||||
private String language;
|
||||
|
||||
/**
|
||||
* 解释器路径
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "解释器路径",
|
||||
description = "脚本解释器的路径,例如:/bin/bash, /usr/bin/python3",
|
||||
required = true
|
||||
)
|
||||
private String interpreter;
|
||||
|
||||
/**
|
||||
* 支持的脚本语言列表
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "支持的语言",
|
||||
description = "系统支持的脚本语言列表",
|
||||
enumValues = {"shell", "python", "javascript", "groovy"}
|
||||
)
|
||||
private List<String> supportedLanguages;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.qqchen.deploy.backend.workflow.dto.nodeConfig.script;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@ -10,10 +11,24 @@ public class ScriptRetryConfig {
|
||||
/**
|
||||
* 重试次数
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "重试次数",
|
||||
description = "脚本执行失败后的重试次数",
|
||||
minimum = 0,
|
||||
maximum = 10,
|
||||
defaultValue = "0"
|
||||
)
|
||||
private Integer retryTimes;
|
||||
|
||||
/**
|
||||
* 重试间隔(秒)
|
||||
*/
|
||||
@SchemaProperty(
|
||||
title = "重试间隔",
|
||||
description = "两次重试之间的等待时间(秒)",
|
||||
minimum = 1,
|
||||
maximum = 3600,
|
||||
defaultValue = "60"
|
||||
)
|
||||
private Integer retryInterval;
|
||||
}
|
||||
|
||||
@ -9,95 +9,92 @@ import com.qqchen.deploy.backend.workflow.dto.nodeConfig.*;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Schema生成器工具类
|
||||
* Schema生成器
|
||||
*/
|
||||
public class SchemaGenerator {
|
||||
private static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
private SchemaGenerator() {
|
||||
// 私有构造函数防止实例化
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成所有节点类型的配置Schema
|
||||
* 生成所有节点类型的schema
|
||||
*/
|
||||
public static JsonNode generateAllNodeTypeSchemas() {
|
||||
ObjectNode schemas = mapper.createObjectNode();
|
||||
|
||||
// START节点
|
||||
schemas.set("START", generateNodeTypeSchema("START", "开始", "开始节点", StartEventConfig.class));
|
||||
|
||||
// SCRIPT节点
|
||||
schemas.set("SCRIPT", generateNodeTypeSchema("SCRIPT", "脚本执行", "执行脚本", ScriptExecutorConfig.class));
|
||||
|
||||
// GIT_CLONE节点
|
||||
schemas.set("GIT_CLONE", generateNodeTypeSchema("GIT_CLONE", "Git克隆", "克隆Git仓库到指定目录", GitCloneConfig.class));
|
||||
|
||||
// END节点
|
||||
schemas.set("END", generateNodeTypeSchema("END", "结束", "结束节点", EndEventConfig.class));
|
||||
|
||||
|
||||
// 生成开始节点schema
|
||||
ObjectNode startNode = generateNodeSchema("START", "开始", "开始节点", StartEventConfig.class);
|
||||
schemas.set("START", startNode);
|
||||
|
||||
// 生成脚本节点schema
|
||||
ObjectNode scriptNode = generateNodeSchema("SCRIPT", "脚本执行", "执行脚本任务", ScriptExecutorConfig.class);
|
||||
schemas.set("SCRIPT", scriptNode);
|
||||
|
||||
// 生成Git克隆节点schema
|
||||
ObjectNode gitNode = generateNodeSchema("GIT_CLONE", "Git克隆", "克隆Git仓库", GitCloneConfig.class);
|
||||
schemas.set("GIT_CLONE", gitNode);
|
||||
|
||||
// 生成任务节点schema
|
||||
ObjectNode taskNode = generateNodeSchema("TASK", "任务", "执行任务", TaskConfig.class);
|
||||
schemas.set("TASK", taskNode);
|
||||
|
||||
// 生成事件节点schema
|
||||
ObjectNode eventNode = generateNodeSchema("EVENT", "事件", "事件节点", EventNodeConfig.class);
|
||||
schemas.set("EVENT", eventNode);
|
||||
|
||||
// 生成结束节点schema
|
||||
ObjectNode endNode = generateNodeSchema("END", "结束", "结束节点", EndEventConfig.class);
|
||||
schemas.set("END", endNode);
|
||||
|
||||
return schemas;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成节点类型的配置Schema
|
||||
* 生成节点schema
|
||||
*/
|
||||
private static JsonNode generateNodeTypeSchema(String code, String name, String description, Class<?> configClass) {
|
||||
ObjectNode schema = mapper.createObjectNode();
|
||||
schema.put("code", code);
|
||||
schema.put("name", name);
|
||||
schema.put("description", description);
|
||||
schema.set("configSchema", generateNodeConfigSchema(configClass));
|
||||
return schema;
|
||||
private static ObjectNode generateNodeSchema(String code, String name, String description, Class<?> configClass) {
|
||||
ObjectNode node = mapper.createObjectNode();
|
||||
node.put("code", code);
|
||||
node.put("name", name);
|
||||
node.put("description", description);
|
||||
|
||||
ObjectNode schema = generateConfigSchema(configClass);
|
||||
node.set("configSchema", schema);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成节点配置的JSON Schema
|
||||
* 根据配置类生成schema
|
||||
*/
|
||||
public static JsonNode generateNodeConfigSchema(Class<?> configClass) {
|
||||
private static ObjectNode generateConfigSchema(Class<?> configClass) {
|
||||
ObjectNode schema = mapper.createObjectNode();
|
||||
schema.put("type", "object");
|
||||
ObjectNode properties = schema.putObject("properties");
|
||||
|
||||
ObjectNode properties = mapper.createObjectNode();
|
||||
List<String> required = new ArrayList<>();
|
||||
|
||||
// 只有TaskConfig的子类才添加任务相关字段
|
||||
if (TaskConfig.class.isAssignableFrom(configClass)) {
|
||||
processTaskConfigFields(properties, required);
|
||||
}
|
||||
|
||||
// 处理特定配置类的字段
|
||||
// 处理所有字段
|
||||
for (Field field : configClass.getDeclaredFields()) {
|
||||
SchemaProperty annotation = field.getAnnotation(SchemaProperty.class);
|
||||
if (annotation != null) {
|
||||
ObjectNode property = properties.putObject(field.getName());
|
||||
generateFieldSchema(property, field, annotation);
|
||||
if (annotation.required()) {
|
||||
required.add(field.getName());
|
||||
}
|
||||
processField(properties, required, field, annotation);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理父类的字段(除了TaskConfig)
|
||||
// 处理父类字段
|
||||
Class<?> superClass = configClass.getSuperclass();
|
||||
while (superClass != null && superClass != TaskConfig.class && superClass != Object.class) {
|
||||
if (superClass != null && !superClass.equals(Object.class)) {
|
||||
for (Field field : superClass.getDeclaredFields()) {
|
||||
SchemaProperty annotation = field.getAnnotation(SchemaProperty.class);
|
||||
if (annotation != null) {
|
||||
ObjectNode property = properties.putObject(field.getName());
|
||||
generateFieldSchema(property, field, annotation);
|
||||
if (annotation.required()) {
|
||||
required.add(field.getName());
|
||||
}
|
||||
processField(properties, required, field, annotation);
|
||||
}
|
||||
}
|
||||
superClass = superClass.getSuperclass();
|
||||
}
|
||||
|
||||
schema.set("properties", properties);
|
||||
if (!required.isEmpty()) {
|
||||
ArrayNode requiredArray = schema.putArray("required");
|
||||
required.forEach(requiredArray::add);
|
||||
@ -107,103 +104,40 @@ public class SchemaGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理TaskConfig中的基础字段
|
||||
* 处理字段
|
||||
*/
|
||||
private static void processTaskConfigFields(ObjectNode properties, List<String> required) {
|
||||
// 添加name字段
|
||||
ObjectNode nameProperty = properties.putObject("name");
|
||||
nameProperty.put("type", "string");
|
||||
nameProperty.put("title", "节点名称");
|
||||
required.add("name");
|
||||
private static void processField(ObjectNode properties, List<String> required, Field field, SchemaProperty annotation) {
|
||||
ObjectNode property = properties.putObject(field.getName());
|
||||
|
||||
// 添加description字段
|
||||
ObjectNode descProperty = properties.putObject("description");
|
||||
descProperty.put("type", "string");
|
||||
descProperty.put("title", "节点描述");
|
||||
// 设置类型
|
||||
String type = getJsonSchemaType(field.getType());
|
||||
property.put("type", type);
|
||||
|
||||
// 添加timeout字段
|
||||
ObjectNode timeoutProperty = properties.putObject("timeout");
|
||||
timeoutProperty.put("type", "object");
|
||||
timeoutProperty.put("title", "超时配置");
|
||||
|
||||
ObjectNode timeoutProperties = timeoutProperty.putObject("properties");
|
||||
|
||||
ObjectNode durationProperty = timeoutProperties.putObject("duration");
|
||||
durationProperty.put("type", "integer");
|
||||
durationProperty.put("title", "超时时间");
|
||||
durationProperty.put("description", "任务执行的最大时间(秒)");
|
||||
durationProperty.put("minimum", 1);
|
||||
durationProperty.put("maximum", 3600);
|
||||
durationProperty.put("default", 300);
|
||||
|
||||
ObjectNode strategyProperty = timeoutProperties.putObject("strategy");
|
||||
strategyProperty.put("type", "string");
|
||||
strategyProperty.put("title", "超时处理策略");
|
||||
strategyProperty.put("description", "任务超时后的处理策略");
|
||||
ArrayNode strategyEnum = strategyProperty.putArray("enum");
|
||||
strategyEnum.add("FAIL").add("CONTINUE").add("RETRY");
|
||||
ArrayNode strategyEnumNames = strategyProperty.putArray("enumNames");
|
||||
strategyEnumNames.add("失败").add("继续").add("重试");
|
||||
strategyProperty.put("default", "FAIL");
|
||||
|
||||
// 添加retry字段
|
||||
ObjectNode retryProperty = properties.putObject("retry");
|
||||
retryProperty.put("type", "object");
|
||||
retryProperty.put("title", "重试配置");
|
||||
|
||||
ObjectNode retryProperties = retryProperty.putObject("properties");
|
||||
|
||||
ObjectNode timesProperty = retryProperties.putObject("times");
|
||||
timesProperty.put("type", "integer");
|
||||
timesProperty.put("title", "重试次数");
|
||||
timesProperty.put("description", "任务失败后的重试次数");
|
||||
timesProperty.put("minimum", 0);
|
||||
timesProperty.put("maximum", 10);
|
||||
timesProperty.put("default", 0);
|
||||
|
||||
ObjectNode intervalProperty = retryProperties.putObject("interval");
|
||||
intervalProperty.put("type", "integer");
|
||||
intervalProperty.put("title", "重试间隔");
|
||||
intervalProperty.put("description", "两次重试之间的等待时间(秒)");
|
||||
intervalProperty.put("minimum", 1);
|
||||
intervalProperty.put("maximum", 3600);
|
||||
intervalProperty.put("default", 60);
|
||||
|
||||
ObjectNode retryStrategyProperty = retryProperties.putObject("strategy");
|
||||
retryStrategyProperty.put("type", "string");
|
||||
retryStrategyProperty.put("title", "重试策略");
|
||||
retryStrategyProperty.put("description", "任务重试的策略");
|
||||
ArrayNode retryStrategyEnum = retryStrategyProperty.putArray("enum");
|
||||
retryStrategyEnum.add("FIXED").add("EXPONENTIAL");
|
||||
ArrayNode retryStrategyEnumNames = retryStrategyProperty.putArray("enumNames");
|
||||
retryStrategyEnumNames.add("固定间隔").add("指数退避");
|
||||
retryStrategyProperty.put("default", "FIXED");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成字段的Schema
|
||||
*/
|
||||
private static void generateFieldSchema(ObjectNode property, Field field, SchemaProperty annotation) {
|
||||
// 设置基本属性
|
||||
// 设置标题和描述
|
||||
if (!annotation.title().isEmpty()) {
|
||||
property.put("title", annotation.title());
|
||||
}
|
||||
if (!annotation.description().isEmpty()) {
|
||||
property.put("description", annotation.description());
|
||||
}
|
||||
|
||||
// 设置必填
|
||||
if (annotation.required()) {
|
||||
required.add(field.getName());
|
||||
}
|
||||
|
||||
// 设置格式
|
||||
if (!annotation.format().isEmpty()) {
|
||||
property.put("format", annotation.format());
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (!annotation.defaultValue().isEmpty()) {
|
||||
setDefaultValue(property, field, annotation.defaultValue());
|
||||
setDefaultValue(property, type, annotation.defaultValue());
|
||||
}
|
||||
|
||||
// 设置字段类型
|
||||
setFieldType(property, field);
|
||||
|
||||
// 设置数值范围
|
||||
if (isNumericType(field.getType()) &&
|
||||
(annotation.minimum() != Integer.MIN_VALUE || annotation.maximum() != Integer.MAX_VALUE)) {
|
||||
if ("integer".equals(type) || "number".equals(type)) {
|
||||
if (annotation.minimum() != Integer.MIN_VALUE) {
|
||||
property.put("minimum", annotation.minimum());
|
||||
}
|
||||
@ -214,79 +148,64 @@ public class SchemaGenerator {
|
||||
|
||||
// 设置枚举值
|
||||
if (annotation.enumValues().length > 0) {
|
||||
ArrayNode enumNode = property.putArray("enum");
|
||||
Arrays.stream(annotation.enumValues()).forEach(enumNode::add);
|
||||
ArrayNode enumArray = property.putArray("enum");
|
||||
for (String value : annotation.enumValues()) {
|
||||
enumArray.add(value);
|
||||
}
|
||||
|
||||
if (annotation.enumNames().length > 0) {
|
||||
ArrayNode enumNamesNode = property.putArray("enumNames");
|
||||
Arrays.stream(annotation.enumNames()).forEach(enumNamesNode::add);
|
||||
|
||||
// 生成oneOf结构
|
||||
ArrayNode oneOf = property.putArray("oneOf");
|
||||
for (int i = 0; i < annotation.enumValues().length; i++) {
|
||||
ObjectNode oneOfItem = oneOf.addObject();
|
||||
oneOfItem.put("const", annotation.enumValues()[i]);
|
||||
oneOfItem.put("title", annotation.enumNames()[i]);
|
||||
|
||||
// 对于非shell的选项,设置为只读
|
||||
if (!"shell".equals(annotation.enumValues()[i])) {
|
||||
oneOfItem.put("readOnly", true);
|
||||
}
|
||||
ArrayNode enumNamesArray = property.putArray("enumNames");
|
||||
for (String name : annotation.enumNames()) {
|
||||
enumNamesArray.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置字段类型
|
||||
* 获取JSON Schema类型
|
||||
*/
|
||||
private static void setFieldType(ObjectNode property, Field field) {
|
||||
Class<?> type = field.getType();
|
||||
if (String.class.isAssignableFrom(type)) {
|
||||
property.put("type", "string");
|
||||
} else if (Integer.class.isAssignableFrom(type) || int.class.isAssignableFrom(type)) {
|
||||
property.put("type", "integer");
|
||||
} else if (Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type)) {
|
||||
property.put("type", "boolean");
|
||||
} else if (List.class.isAssignableFrom(type)) {
|
||||
property.put("type", "array");
|
||||
// 如果需要,可以在这里添加items的schema
|
||||
} else if (Map.class.isAssignableFrom(type)) {
|
||||
property.put("type", "object");
|
||||
ObjectNode additionalProperties = property.putObject("additionalProperties");
|
||||
additionalProperties.put("type", "string");
|
||||
private static String getJsonSchemaType(Class<?> type) {
|
||||
if (type == String.class) {
|
||||
return "string";
|
||||
} else if (type == Integer.class || type == int.class) {
|
||||
return "integer";
|
||||
} else if (type == Double.class || type == double.class || type == Float.class || type == float.class) {
|
||||
return "number";
|
||||
} else if (type == Boolean.class || type == boolean.class) {
|
||||
return "boolean";
|
||||
} else if (type.isArray() || List.class.isAssignableFrom(type)) {
|
||||
return "array";
|
||||
} else {
|
||||
return "object";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认值
|
||||
*/
|
||||
private static void setDefaultValue(ObjectNode property, Field field, String defaultValue) {
|
||||
Class<?> type = field.getType();
|
||||
if (String.class.isAssignableFrom(type)) {
|
||||
property.put("default", defaultValue);
|
||||
} else if (Integer.class.isAssignableFrom(type) || int.class.isAssignableFrom(type)) {
|
||||
try {
|
||||
property.put("default", Integer.parseInt(defaultValue));
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略无效的默认值
|
||||
}
|
||||
} else if (Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type)) {
|
||||
property.put("default", Boolean.parseBoolean(defaultValue));
|
||||
private static void setDefaultValue(ObjectNode property, String type, String defaultValue) {
|
||||
switch (type) {
|
||||
case "string":
|
||||
property.put("default", defaultValue);
|
||||
break;
|
||||
case "integer":
|
||||
try {
|
||||
property.put("default", Integer.parseInt(defaultValue));
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略无效的默认值
|
||||
}
|
||||
break;
|
||||
case "number":
|
||||
try {
|
||||
property.put("default", Double.parseDouble(defaultValue));
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略无效的默认值
|
||||
}
|
||||
break;
|
||||
case "boolean":
|
||||
property.put("default", Boolean.parseBoolean(defaultValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为数值类型
|
||||
*/
|
||||
private static boolean isNumericType(Class<?> type) {
|
||||
return Integer.class.isAssignableFrom(type) ||
|
||||
int.class.isAssignableFrom(type) ||
|
||||
Long.class.isAssignableFrom(type) ||
|
||||
long.class.isAssignableFrom(type) ||
|
||||
Double.class.isAssignableFrom(type) ||
|
||||
double.class.isAssignableFrom(type) ||
|
||||
Float.class.isAssignableFrom(type) ||
|
||||
float.class.isAssignableFrom(type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,47 +6,138 @@ import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class SchemaGeneratorTest {
|
||||
private final SchemaGenerator generator = new SchemaGenerator();
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void testGenerateNodeTypeSchema() throws Exception {
|
||||
JsonNode schema = generator.generateNodeTypeSchema();
|
||||
void testGenerateAllNodeTypeSchemas() throws Exception {
|
||||
JsonNode schemas = SchemaGenerator.generateAllNodeTypeSchemas();
|
||||
|
||||
// 将生成的schema打印出来以便查看
|
||||
String prettySchema = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
|
||||
System.out.println(prettySchema);
|
||||
System.out.println("Generated Schemas:");
|
||||
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schemas));
|
||||
|
||||
// 基本验证
|
||||
assertTrue(schema.isArray());
|
||||
assertEquals(1, schema.size());
|
||||
// 验证基本结构
|
||||
assertTrue(schemas.isObject());
|
||||
assertTrue(schemas.has("START"));
|
||||
assertTrue(schemas.has("SCRIPT"));
|
||||
assertTrue(schemas.has("GIT_CLONE"));
|
||||
assertTrue(schemas.has("TASK"));
|
||||
assertTrue(schemas.has("EVENT"));
|
||||
assertTrue(schemas.has("END"));
|
||||
|
||||
JsonNode firstNode = schema.get(0);
|
||||
assertEquals("SCRIPT", firstNode.get("code").asText());
|
||||
assertEquals("脚本执行器", firstNode.get("name").asText());
|
||||
// 验证START节点
|
||||
JsonNode startNode = schemas.get("START");
|
||||
assertEquals("START", startNode.get("code").asText());
|
||||
assertEquals("开始", startNode.get("name").asText());
|
||||
assertEquals("开始节点", startNode.get("description").asText());
|
||||
|
||||
JsonNode configSchema = firstNode.get("configSchema");
|
||||
assertTrue(configSchema.has("properties"));
|
||||
assertTrue(configSchema.has("required"));
|
||||
JsonNode startSchema = startNode.get("configSchema");
|
||||
assertTrue(startSchema.has("properties"));
|
||||
JsonNode startProps = startSchema.get("properties");
|
||||
assertTrue(startProps.has("name"));
|
||||
assertTrue(startProps.has("description"));
|
||||
assertTrue(startProps.has("triggerType"));
|
||||
assertTrue(startProps.has("formKey"));
|
||||
assertTrue(startProps.has("initiator"));
|
||||
|
||||
// 验证必填字段
|
||||
JsonNode required = configSchema.get("required");
|
||||
assertTrue(required.isArray());
|
||||
assertTrue(required.toString().contains("script"));
|
||||
assertTrue(required.toString().contains("language"));
|
||||
assertTrue(required.toString().contains("interpreter"));
|
||||
// 验证SCRIPT节点
|
||||
JsonNode scriptNode = schemas.get("SCRIPT");
|
||||
assertEquals("SCRIPT", scriptNode.get("code").asText());
|
||||
assertEquals("脚本执行", scriptNode.get("name").asText());
|
||||
assertEquals("执行脚本任务", scriptNode.get("description").asText());
|
||||
|
||||
// 验证属性
|
||||
JsonNode properties = configSchema.get("properties");
|
||||
assertTrue(properties.has("script"));
|
||||
assertTrue(properties.has("language"));
|
||||
assertTrue(properties.has("interpreter"));
|
||||
assertTrue(properties.has("workingDirectory"));
|
||||
assertTrue(properties.has("timeout"));
|
||||
assertTrue(properties.has("retryTimes"));
|
||||
assertTrue(properties.has("retryInterval"));
|
||||
assertTrue(properties.has("environment"));
|
||||
assertTrue(properties.has("successExitCode"));
|
||||
assertTrue(properties.has("supportedLanguages"));
|
||||
JsonNode scriptSchema = scriptNode.get("configSchema");
|
||||
JsonNode scriptProps = scriptSchema.get("properties");
|
||||
// 验证基本属性
|
||||
assertTrue(scriptProps.has("taskType"));
|
||||
assertTrue(scriptProps.has("taskName"));
|
||||
assertTrue(scriptProps.has("description"));
|
||||
// 验证任务相关属性
|
||||
assertTrue(scriptProps.has("timeoutDuration"));
|
||||
assertTrue(scriptProps.has("timeoutStrategy"));
|
||||
assertTrue(scriptProps.has("retryTimes"));
|
||||
assertTrue(scriptProps.has("retryInterval"));
|
||||
assertTrue(scriptProps.has("retryStrategy"));
|
||||
// 验证脚本特有属性
|
||||
assertTrue(scriptProps.has("script"));
|
||||
assertTrue(scriptProps.has("language"));
|
||||
assertTrue(scriptProps.has("interpreter"));
|
||||
assertTrue(scriptProps.has("workingDirectory"));
|
||||
|
||||
// 验证GIT_CLONE节点
|
||||
JsonNode gitNode = schemas.get("GIT_CLONE");
|
||||
assertEquals("GIT_CLONE", gitNode.get("code").asText());
|
||||
assertEquals("Git克隆", gitNode.get("name").asText());
|
||||
assertEquals("克隆Git仓库", gitNode.get("description").asText());
|
||||
|
||||
JsonNode gitSchema = gitNode.get("configSchema");
|
||||
JsonNode gitProps = gitSchema.get("properties");
|
||||
assertTrue(gitProps.has("taskType"));
|
||||
assertTrue(gitProps.has("taskName"));
|
||||
assertTrue(gitProps.has("description"));
|
||||
assertTrue(gitProps.has("repositoryUrl"));
|
||||
assertTrue(gitProps.has("ref"));
|
||||
assertTrue(gitProps.has("targetDirectory"));
|
||||
|
||||
// 验证TASK节点
|
||||
JsonNode taskNode = schemas.get("TASK");
|
||||
assertEquals("TASK", taskNode.get("code").asText());
|
||||
assertEquals("任务", taskNode.get("name").asText());
|
||||
assertEquals("执行任务", taskNode.get("description").asText());
|
||||
|
||||
JsonNode taskSchema = taskNode.get("configSchema");
|
||||
JsonNode taskProps = taskSchema.get("properties");
|
||||
assertTrue(taskProps.has("taskType"));
|
||||
assertTrue(taskProps.has("taskName"));
|
||||
assertTrue(taskProps.has("description"));
|
||||
assertTrue(taskProps.has("enabled"));
|
||||
assertTrue(taskProps.has("priority"));
|
||||
assertTrue(taskProps.has("timeoutDuration"));
|
||||
assertTrue(taskProps.has("timeoutStrategy"));
|
||||
assertTrue(taskProps.has("retryTimes"));
|
||||
assertTrue(taskProps.has("retryInterval"));
|
||||
assertTrue(taskProps.has("retryStrategy"));
|
||||
assertTrue(taskProps.has("assignee"));
|
||||
assertTrue(taskProps.has("form"));
|
||||
assertTrue(taskProps.has("inputVariables"));
|
||||
assertTrue(taskProps.has("outputVariables"));
|
||||
assertTrue(taskProps.has("taskListeners"));
|
||||
|
||||
// 验证EVENT节点
|
||||
JsonNode eventNode = schemas.get("EVENT");
|
||||
assertEquals("EVENT", eventNode.get("code").asText());
|
||||
assertEquals("事件", eventNode.get("name").asText());
|
||||
assertEquals("事件节点", eventNode.get("description").asText());
|
||||
|
||||
JsonNode eventSchema = eventNode.get("configSchema");
|
||||
JsonNode eventProps = eventSchema.get("properties");
|
||||
assertTrue(eventProps.has("name"));
|
||||
assertTrue(eventProps.has("description"));
|
||||
assertTrue(eventProps.has("eventType"));
|
||||
|
||||
// 验证required字段
|
||||
JsonNode eventRequired = eventSchema.get("required");
|
||||
assertTrue(eventRequired.isArray());
|
||||
assertTrue(eventRequired.toString().contains("name"));
|
||||
assertTrue(eventRequired.toString().contains("eventType"));
|
||||
|
||||
// 验证END节点
|
||||
JsonNode endNode = schemas.get("END");
|
||||
assertEquals("END", endNode.get("code").asText());
|
||||
assertEquals("结束", endNode.get("name").asText());
|
||||
assertEquals("结束节点", endNode.get("description").asText());
|
||||
|
||||
JsonNode endSchema = endNode.get("configSchema");
|
||||
JsonNode endProps = endSchema.get("properties");
|
||||
assertTrue(endProps.has("name"));
|
||||
assertTrue(endProps.has("description"));
|
||||
assertTrue(endProps.has("status"));
|
||||
assertTrue(endProps.has("reason"));
|
||||
|
||||
// 验证required字段
|
||||
JsonNode endRequired = endSchema.get("required");
|
||||
assertTrue(endRequired.isArray());
|
||||
assertTrue(endRequired.toString().contains("name"));
|
||||
assertTrue(endRequired.toString().contains("status"));
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user