From c0b4ddb86e371cde009fb1d7164a1f0bff61ac02 Mon Sep 17 00:00:00 2001 From: liuhuazhong Date: Thu, 28 Nov 2024 14:48:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E6=B5=81=E6=B0=B4=E7=BA=BFjson?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E8=A7=A3=E6=9E=90=E6=88=90yaml=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/PmsCiPipelinesController.java | 8 + .../pms/pipeline/domain/vo/NodeActionVo.java | 120 ++++++++ .../pms/pipeline/domain/vo/PipelineVo.java | 284 ++++++++++++++++++ .../service/IPmsCiPipelinesService.java | 2 + .../impl/PmsCiPipelinesServiceImpl.java | 42 +++ .../com/microservices/pms/utils/YamlUtil.java | 58 ++++ 6 files changed, 514 insertions(+) create mode 100644 microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/NodeActionVo.java create mode 100644 microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/PipelineVo.java create mode 100644 microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/utils/YamlUtil.java diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/controller/PmsCiPipelinesController.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/controller/PmsCiPipelinesController.java index 3aff4746a..284b8c247 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/controller/PmsCiPipelinesController.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/controller/PmsCiPipelinesController.java @@ -204,6 +204,14 @@ public class PmsCiPipelinesController extends BaseController return success(pmsCiPipelinesService.savePipelineYamlByGraphicJson(id, pmsCiPipelineBuildInputVo)); } + @PostMapping(value = "/{id}/savePipelineYamlNew") + @ApiOperation("流水线图形构建声明式yaml并保存") + public AjaxResult savePipelineYamlNew(@ApiParam(name = "id", value = "流水线id")@PathVariable Long id, + @RequestBody @Validated PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo) + { + return success(pmsCiPipelinesService.savePipelineYamlByGraphicJsonNew(id, pmsCiPipelineBuildInputVo)); + } + /** * 启动流水线执行记录任务 */ diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/NodeActionVo.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/NodeActionVo.java new file mode 100644 index 000000000..41cc9c0ad --- /dev/null +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/NodeActionVo.java @@ -0,0 +1,120 @@ +package com.microservices.pms.pipeline.domain.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; +import java.util.stream.Collectors; + +@Getter +@Setter +@NoArgsConstructor +public class NodeActionVo { + + private String name; + private final Map on = new LinkedHashMap<>(); + private final Map jobs = new LinkedHashMap<>(); + @JsonIgnore + private Map params = new LinkedHashMap<>(); + + public void buildName(String name) { + this.name = name; + } + + public void buildOn(PipelineVo.PipelineJson.Nodes node) { +// this.on.put("push", Collections.singletonMap("branches", Collections.singletonList(branchName))); + String fullName = node.getFull_name(); + Map step = new LinkedHashMap<>(); + + if (Objects.equals(fullName, "on-schedule")) { + List inputs = Optional.ofNullable(node.getInputs()).orElse(new ArrayList<>()); + inputs.forEach(e -> { + step.put(e.getName(), e.getValue()); + }); + this.on.put(fullName.split("-")[1], step); + return; + } + + if (fullName.startsWith("on-")) { + List inputs = Optional.ofNullable(node.getInputs()).orElse(new ArrayList<>()).stream().filter(e -> StringUtils.isNotBlank(e.getValue())).collect(Collectors.toList()); + inputs.forEach(e -> { + step.put(e.getName(), e.getValue().replace("\'","").split(",")); + }); + + this.on.put(fullName.split("-")[1], step); + } + } + + public void buildJobs(String jobKey, String jobName, List> steps) { + if (steps.isEmpty()) return; + Map job = new LinkedHashMap<>(); + job.put("runs-on", "ubuntu-latest"); + job.put("name", jobName); + job.put("steps", steps); + this.jobs.put(jobKey, job); + } + + public void buildSetupStep(List> steps, PipelineVo.PipelineJson.Nodes node) { + String name = node.getName(); + Map step = new LinkedHashMap<>(); + if (name.startsWith("setup-java")) { + List inputs = Optional.ofNullable(node.getInputs()).orElse(new ArrayList<>()).stream().filter(e -> StringUtils.isNotBlank(e.getValue())).collect(Collectors.toList()); + + + Map name2Value = inputs.stream().collect(Collectors.toMap(e -> e.getName(), e -> e.getValue(), (o, n) -> n)); + + Map with = new LinkedHashMap<>(); + if (name2Value.containsKey("download_url") && StringUtils.isNotBlank(name2Value.get("download_url"))) { + steps.add(Collections.singletonMap("run", "download_url=" + name2Value.get("download_url") + " && " + "wget -O $RUNNER_TEMP/java_package.tar.gz $download_url")); + with.put("distribution", "jdkfile"); + with.put("jdkFile", "${{ runner.temp }}/java_package.tar.gz"); + } + step.put("name", node.getLabel()); + step.put("uses", node.getFull_name()); + if (!inputs.isEmpty()) { + + inputs.forEach(i -> { + with.put(i.getName(), Optional.ofNullable(i.getValue()).orElse("")); + }); + + step.put("with", with); + } + steps.add(step); + return; + } + + if (name.startsWith("setup-")) { + List inputs = Optional.ofNullable(node.getInputs()).orElse(new ArrayList<>()).stream().filter(e -> StringUtils.isNotBlank(e.getValue())).collect(Collectors.toList()); + + step.put("name", node.getLabel()); + step.put("uses", node.getFull_name()); + if (!inputs.isEmpty()) { + Map with = new LinkedHashMap<>(); + inputs.forEach(i -> { + with.put(i.getName(), Optional.ofNullable(i.getValue()).orElse("")); + }); + + step.put("with", with); + } + steps.add(step); + } + } + + public void buildShellStep(List> steps, PipelineVo.PipelineJson.Nodes node) { + String fullName = node.getFull_name(); + if (Objects.equals(fullName, "shell")) { + Map step = new LinkedHashMap<>(); + step.put("name", node.getLabel()); +// step.put("run",""); + List inputs = Optional.ofNullable(node.getInputs()).orElse(new ArrayList<>()); + inputs.forEach(i -> { + step.put(i.getName(), Optional.ofNullable(i.getValue()).orElse("")); + }); + + steps.add(step); + } + } +} diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/PipelineVo.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/PipelineVo.java new file mode 100644 index 000000000..c7781aba5 --- /dev/null +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/domain/vo/PipelineVo.java @@ -0,0 +1,284 @@ +package com.microservices.pms.pipeline.domain.vo; + +import java.io.Serializable; +import java.util.List; + +public class PipelineVo implements Serializable { + private String pipelineName; + + private PipelineJson pipelineJson; + + public String getPipelineName() { + return this.pipelineName; + } + + public void setPipelineName(String pipelineName) { + this.pipelineName = pipelineName; + } + + public PipelineJson getPipelineJson() { + return this.pipelineJson; + } + + public void setPipelineJson(PipelineJson pipelineJson) { + this.pipelineJson = pipelineJson; + } + + public static class PipelineJson implements Serializable { + private List nodes; + + private List edges; + + public List getNodes() { + return this.nodes; + } + + public void setNodes(List nodes) { + this.nodes = nodes; + } + + public List getEdges() { + return this.edges; + } + + public void setEdges(List edges) { + this.edges = edges; + } + + public static class Nodes implements Serializable { + private Integer action_node_types_id; + + private String img; + + private List inputs; + + private String icon; + + private String description; + + private String label; + + private String type; + + private Integer sort_no; + + private Integer use_count; + + private String full_name; + + private String name; + + private Integer x; + + private Double y; + + private String id; + + private Boolean isCluster; + + private String yaml; + + public Integer getAction_node_types_id() { + return this.action_node_types_id; + } + + public void setAction_node_types_id(Integer action_node_types_id) { + this.action_node_types_id = action_node_types_id; + } + + public String getImg() { + return this.img; + } + + public void setImg(String img) { + this.img = img; + } + + public List getInputs() { + return this.inputs; + } + + public void setInputs(List inputs) { + this.inputs = inputs; + } + + public String getIcon() { + return this.icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getLabel() { + return this.label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getType() { + return this.type; + } + + public void setType(String type) { + this.type = type; + } + + public Integer getSort_no() { + return this.sort_no; + } + + public void setSort_no(Integer sort_no) { + this.sort_no = sort_no; + } + + public Integer getUse_count() { + return this.use_count; + } + + public void setUse_count(Integer use_count) { + this.use_count = use_count; + } + + public String getFull_name() { + return this.full_name; + } + + public void setFull_name(String full_name) { + this.full_name = full_name; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getX() { + return this.x; + } + + public void setX(Integer x) { + this.x = x; + } + + public Double getY() { + return this.y; + } + + public void setY(Double y) { + this.y = y; + } + + public String getId() { + return this.id; + } + + public void setId(String id) { + this.id = id; + } + + public Boolean getIsCluster() { + return this.isCluster; + } + + public void setIsCluster(Boolean isCluster) { + this.isCluster = isCluster; + } + + public String getYaml() { + return this.yaml; + } + + public void setYaml(String yaml) { + this.yaml = yaml; + } + + public static class Inputs implements Serializable { + private Boolean is_required; + + private String name; + + private String value; + + private String input_type; + + private Integer id; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Boolean getIs_required() { + return this.is_required; + } + + public void setIs_required(Boolean is_required) { + this.is_required = is_required; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getInput_type() { + return this.input_type; + } + + public void setInput_type(String input_type) { + this.input_type = input_type; + } + + public Integer getId() { + return this.id; + } + + public void setId(Integer id) { + this.id = id; + } + } + } + + public static class Edges implements Serializable { + private String source; + + private String target; + + public String getSource() { + return this.source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getTarget() { + return this.target; + } + + public void setTarget(String target) { + this.target = target; + } + } + } +} diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/IPmsCiPipelinesService.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/IPmsCiPipelinesService.java index ce3e38f87..210ca4f0e 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/IPmsCiPipelinesService.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/IPmsCiPipelinesService.java @@ -91,6 +91,8 @@ public interface IPmsCiPipelinesService JSONObject savePipelineYamlByGraphicJson(Long id, PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo); + JSONObject savePipelineYamlByGraphicJsonNew(Long id, PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo); + JSONObject reRunPipelineRunsJob(Long id, String run, String job); JSONObject reRunAllJobsInPipelineRun(Long id, String run); diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/impl/PmsCiPipelinesServiceImpl.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/impl/PmsCiPipelinesServiceImpl.java index e7a758018..4f7ada59b 100644 --- a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/impl/PmsCiPipelinesServiceImpl.java +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/pipeline/service/impl/PmsCiPipelinesServiceImpl.java @@ -1,11 +1,16 @@ package com.microservices.pms.pipeline.service.impl; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSONObject; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import com.microservices.common.core.exception.ServiceException; import com.microservices.common.core.utils.DateUtils; import com.microservices.common.core.utils.StringUtils; @@ -23,6 +28,7 @@ import com.microservices.pms.pipeline.domain.vo.*; import com.microservices.pms.pipeline.service.IPmsCiPipelineGraphicsService; import com.microservices.pms.utils.PmsConstants; import com.microservices.pms.utils.PmsGitLinkRequestUrl; +import com.microservices.pms.utils.YamlUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; @@ -363,6 +369,42 @@ public class PmsCiPipelinesServiceImpl implements IPmsCiPipelinesService { return result; } + @Override + public JSONObject savePipelineYamlByGraphicJsonNew(Long id, PmsCiPipelineBuildYamlInputVo pmsCiPipelineBuildInputVo) { + PmsCiPipelines pmsCiPipelines = pmsCiPipelinesMapper.selectPmsCiPipelinesById(id); + if (pmsCiPipelines == null) { + throw new ServiceException("该项目流水线不存在(流水线ID[%s])", id); + } + + try { + PipelineVo vo = JSON.parseObject(JSON.toJSONString(pmsCiPipelineBuildInputVo), PipelineVo.class); + NodeActionVo actionVo = getNodeActionVo(vo); + String yaml = YamlUtil.toYaml(actionVo); + JSONObject result = new JSONObject(); + result.put("pipeline_yaml", yaml); + return result; + } catch (Exception e) { + logger.error("流水线图形Json解析失败)", e); + return null; + } + } + + private NodeActionVo getNodeActionVo(PipelineVo vo) { + List nodes = vo.getPipelineJson().getNodes(); + String pipelineName = vo.getPipelineName(); + NodeActionVo actionVo = new NodeActionVo(); + actionVo.buildName(pipelineName); + AtomicInteger i = new AtomicInteger(); + nodes.forEach(s -> { + List> steps = new ArrayList<>(); + actionVo.buildOn(s); + actionVo.buildSetupStep(steps, s); + actionVo.buildShellStep(steps, s); + actionVo.buildJobs("job" + (i.getAndIncrement()), s.getLabel(), steps); + }); + return actionVo; + } + @Override public JSONObject reRunPipelineRunsJob(Long id, String run, String job) { PmsCiPipelines pmsCiPipelines = pmsCiPipelinesMapper.selectPmsCiPipelinesById(id); diff --git a/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/utils/YamlUtil.java b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/utils/YamlUtil.java new file mode 100644 index 000000000..04e9deb67 --- /dev/null +++ b/microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/utils/YamlUtil.java @@ -0,0 +1,58 @@ +package com.microservices.pms.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; +import com.microservices.common.core.exception.ServiceException; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.StringWriter; + +@Slf4j +public class YamlUtil { + /** + * 将yaml字符串转成类对象 + * + * @param yamlStr 字符串 + * @param clazz 目标类 + * @param 泛型 + * @return 目标类 + */ + public static T toObject(String yamlStr, Class clazz) { + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + mapper.findAndRegisterModules(); + try { + return mapper.readValue(yamlStr, clazz); + } catch (JsonProcessingException e) { + log.error("yaml文本解析成java对象错误:", e); + throw new ServiceException("yaml文本解析成java对象错误!"); + } + } + + /** + * 将类对象转yaml字符串 + * + * @param object 对象 + * @return yaml字符串 + */ + public static String toYaml(Object object) { + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + mapper.findAndRegisterModules(); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + mapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)); + StringWriter stringWriter = new StringWriter(); + try { + mapper.writeValue(stringWriter, object); + return stringWriter.toString(); + } catch (IOException e) { + log.error("Java对象解析成Yaml文本错误", e); + } + return null; + } +} + +