Merge pull request '将流水线json文本解析成yaml格式' (#737) from liuhuazhong/microservices:dev-lhz into dev

This commit is contained in:
otto 2024-11-28 15:12:25 +08:00
commit 57c4e62daa
6 changed files with 514 additions and 0 deletions

View File

@ -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));
}
/**
* 启动流水线执行记录任务
*/

View File

@ -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<String, Object> on = new LinkedHashMap<>();
private final Map<String, Object> jobs = new LinkedHashMap<>();
@JsonIgnore
private Map<String, Object> 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<String, Object> step = new LinkedHashMap<>();
if (Objects.equals(fullName, "on-schedule")) {
List<PipelineVo.PipelineJson.Nodes.Inputs> 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<PipelineVo.PipelineJson.Nodes.Inputs> 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<Map<String, Object>> steps) {
if (steps.isEmpty()) return;
Map<String, Object> 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<Map<String, Object>> steps, PipelineVo.PipelineJson.Nodes node) {
String name = node.getName();
Map<String, Object> step = new LinkedHashMap<>();
if (name.startsWith("setup-java")) {
List<PipelineVo.PipelineJson.Nodes.Inputs> inputs = Optional.ofNullable(node.getInputs()).orElse(new ArrayList<>()).stream().filter(e -> StringUtils.isNotBlank(e.getValue())).collect(Collectors.toList());
Map<String, String> name2Value = inputs.stream().collect(Collectors.toMap(e -> e.getName(), e -> e.getValue(), (o, n) -> n));
Map<String, Object> 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<PipelineVo.PipelineJson.Nodes.Inputs> 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<String, Object> 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<Map<String, Object>> steps, PipelineVo.PipelineJson.Nodes node) {
String fullName = node.getFull_name();
if (Objects.equals(fullName, "shell")) {
Map<String, Object> step = new LinkedHashMap<>();
step.put("name", node.getLabel());
// step.put("run","");
List<PipelineVo.PipelineJson.Nodes.Inputs> inputs = Optional.ofNullable(node.getInputs()).orElse(new ArrayList<>());
inputs.forEach(i -> {
step.put(i.getName(), Optional.ofNullable(i.getValue()).orElse(""));
});
steps.add(step);
}
}
}

View File

@ -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> nodes;
private List<Edges> edges;
public List<Nodes> getNodes() {
return this.nodes;
}
public void setNodes(List<Nodes> nodes) {
this.nodes = nodes;
}
public List<Edges> getEdges() {
return this.edges;
}
public void setEdges(List<Edges> edges) {
this.edges = edges;
}
public static class Nodes implements Serializable {
private Integer action_node_types_id;
private String img;
private List<Inputs> 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<Inputs> getInputs() {
return this.inputs;
}
public void setInputs(List<Inputs> 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;
}
}
}
}

View File

@ -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);

View File

@ -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<PipelineVo.PipelineJson.Nodes> nodes = vo.getPipelineJson().getNodes();
String pipelineName = vo.getPipelineName();
NodeActionVo actionVo = new NodeActionVo();
actionVo.buildName(pipelineName);
AtomicInteger i = new AtomicInteger();
nodes.forEach(s -> {
List<Map<String, Object>> 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);

View File

@ -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 <T> 泛型
* @return 目标类
*/
public static <T> T toObject(String yamlStr, Class<T> 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;
}
}