大声道撒旦
This commit is contained in:
parent
a23e7237a2
commit
ec79cfa018
@ -66,7 +66,6 @@ public class JenkinsBaseBuildVariables {
|
|||||||
private String jobId;
|
private String jobId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@SchemaProperty(
|
@SchemaProperty(
|
||||||
title = "Pipeline script",
|
title = "Pipeline script",
|
||||||
description = "流水线脚本",
|
description = "流水线脚本",
|
||||||
@ -84,8 +83,59 @@ public class JenkinsBaseBuildVariables {
|
|||||||
autoComplete = true,
|
autoComplete = true,
|
||||||
folding = true
|
folding = true
|
||||||
),
|
),
|
||||||
order = 6
|
order = 5
|
||||||
)
|
)
|
||||||
private String script;
|
private String script;
|
||||||
|
//
|
||||||
|
// @SchemaProperty(
|
||||||
|
// title = "绑定三方Git系统",
|
||||||
|
// description = "请选择三方Git系统",
|
||||||
|
// required = true,
|
||||||
|
// dataSource = @SchemaPropertyDataSource(
|
||||||
|
// type = "api",
|
||||||
|
// url = "/api/v1/external-system/list?type=GIT",
|
||||||
|
// valueField = "id",
|
||||||
|
// labelField = "name"
|
||||||
|
// ),
|
||||||
|
// order = 6
|
||||||
|
// )
|
||||||
|
// private String gitExternalSystemId;
|
||||||
|
//
|
||||||
|
// @SchemaProperty(
|
||||||
|
// title = "绑定Git项目",
|
||||||
|
// description = "绑定Git项目",
|
||||||
|
// required = true,
|
||||||
|
// dataSource = @SchemaPropertyDataSource(
|
||||||
|
// type = "api",
|
||||||
|
// url = "/api/v1/repository-project/list",
|
||||||
|
// valueField = "repoProjectId",
|
||||||
|
// labelField = "name",
|
||||||
|
// dependsOn = {"gitExternalSystemId"},
|
||||||
|
// params = {
|
||||||
|
// @SchemaPropertyDataSourceParam(name = "externalSystemId", value = "${gitExternalSystemId}")
|
||||||
|
// }
|
||||||
|
// ),
|
||||||
|
// order = 7
|
||||||
|
// )
|
||||||
|
// private String repoProjectId;
|
||||||
|
//
|
||||||
|
// @SchemaProperty(
|
||||||
|
// title = "绑定代码分支",
|
||||||
|
// description = "请选择代码分支",
|
||||||
|
// required = true,
|
||||||
|
// dataSource = @SchemaPropertyDataSource(
|
||||||
|
// type = "api",
|
||||||
|
// url = "/api/v1/repository-branch/list",
|
||||||
|
// valueField = "name",
|
||||||
|
// labelField = "name",
|
||||||
|
// dependsOn = {"gitExternalSystemId", "repoProjectId"},
|
||||||
|
// params = {
|
||||||
|
// @SchemaPropertyDataSourceParam(name = "externalSystemId", value = "${gitExternalSystemId}"),
|
||||||
|
// @SchemaPropertyDataSourceParam(name = "repoProjectId", value = "${repoProjectId}")
|
||||||
|
// }
|
||||||
|
// ),
|
||||||
|
// order = 8
|
||||||
|
// )
|
||||||
|
// private String branch;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -21,8 +21,8 @@ import org.hibernate.annotations.Type;
|
|||||||
@Table(name = "deploy_app_config")
|
@Table(name = "deploy_app_config")
|
||||||
public class DeployAppConfig extends Entity<Long> {
|
public class DeployAppConfig extends Entity<Long> {
|
||||||
|
|
||||||
@Column(name = "branch", nullable = false)
|
// @Column(name = "branch", nullable = false)
|
||||||
private String branch;
|
// private String branch;
|
||||||
|
|
||||||
@Column(name = "build_type", nullable = false)
|
@Column(name = "build_type", nullable = false)
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
|
|||||||
@ -28,6 +28,19 @@ import org.springframework.util.MultiValueMap;
|
|||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -103,10 +116,6 @@ public class JenkinsServiceIntegrationImpl implements IJenkinsServiceIntegration
|
|||||||
return new HttpEntity<>(headers);
|
return new HttpEntity<>(headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ExternalSystemTypeEnum getSystemType() {
|
|
||||||
return ExternalSystemTypeEnum.JENKINS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JenkinsCrumbIssuerResponse getJenkinsCrumbIssue() {
|
public JenkinsCrumbIssuerResponse getJenkinsCrumbIssue() {
|
||||||
@ -120,6 +129,11 @@ public class JenkinsServiceIntegrationImpl implements IJenkinsServiceIntegration
|
|||||||
@Override
|
@Override
|
||||||
public String buildWithParameters(ExternalSystem externalSystem, String jobName, Map<String, String> parameters) {
|
public String buildWithParameters(ExternalSystem externalSystem, String jobName, Map<String, String> parameters) {
|
||||||
try {
|
try {
|
||||||
|
// 如果参数中包含PIPELINE_SCRIPT,确保Job配置中有该参数
|
||||||
|
if (parameters.containsKey("PIPELINE_SCRIPT")) {
|
||||||
|
ensurePipelineScriptParameter(externalSystem, jobName);
|
||||||
|
}
|
||||||
|
|
||||||
// 1. 获取Crumb
|
// 1. 获取Crumb
|
||||||
JenkinsCrumbIssuerResponse jenkinsCrumbIssue = getJenkinsCrumbIssue();
|
JenkinsCrumbIssuerResponse jenkinsCrumbIssue = getJenkinsCrumbIssue();
|
||||||
|
|
||||||
@ -162,6 +176,177 @@ public class JenkinsServiceIntegrationImpl implements IJenkinsServiceIntegration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确保Jenkins Job配置中包含PIPELINE_SCRIPT参数
|
||||||
|
*/
|
||||||
|
private void ensurePipelineScriptParameter(ExternalSystem externalSystem, String jobName) {
|
||||||
|
try {
|
||||||
|
// 获取 Crumb
|
||||||
|
JenkinsCrumbIssuerResponse jenkinsCrumbIssue = getJenkinsCrumbIssue();
|
||||||
|
|
||||||
|
// 获取Job配置
|
||||||
|
String configUrl = String.format("%s/job/%s/config.xml", externalSystem.getUrl(), jobName);
|
||||||
|
HttpHeaders headers = createHeaders(externalSystem);
|
||||||
|
headers.set(HttpHeaders.ACCEPT_CHARSET, "UTF-8");
|
||||||
|
headers.set("Jenkins-Crumb", jenkinsCrumbIssue.getCrumb());
|
||||||
|
headers.set("Cookie", jenkinsCrumbIssue.getCookie());
|
||||||
|
HttpEntity<String> entity = new HttpEntity<>(headers);
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
|
configUrl,
|
||||||
|
HttpMethod.GET,
|
||||||
|
entity,
|
||||||
|
String.class
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.getBody() == null) {
|
||||||
|
throw new RuntimeException("无法获取Jenkins Job配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析XML
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||||
|
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||||
|
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||||
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
|
||||||
|
// 使用UTF-8编码解析XML
|
||||||
|
InputSource is = new InputSource(new StringReader(response.getBody()));
|
||||||
|
is.setEncoding("UTF-8");
|
||||||
|
Document doc = builder.parse(is);
|
||||||
|
|
||||||
|
// 检查是否已存在PIPELINE_SCRIPT参数
|
||||||
|
NodeList parameterDefinitions = doc.getElementsByTagName("parameterDefinitions");
|
||||||
|
if (parameterDefinitions.getLength() > 0) {
|
||||||
|
NodeList parameters = parameterDefinitions.item(0).getChildNodes();
|
||||||
|
for (int i = 0; i < parameters.getLength(); i++) {
|
||||||
|
Node parameter = parameters.item(i);
|
||||||
|
if (parameter.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
NodeList parameterChildren = parameter.getChildNodes();
|
||||||
|
for (int j = 0; j < parameterChildren.getLength(); j++) {
|
||||||
|
Node child = parameterChildren.item(j);
|
||||||
|
if ("name".equals(child.getNodeName()) && "PIPELINE_SCRIPT".equals(child.getTextContent())) {
|
||||||
|
// 参数已存在,无需添加
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要添加PIPELINE_SCRIPT参数
|
||||||
|
Element root = doc.getDocumentElement();
|
||||||
|
|
||||||
|
// 获取或创建properties元素
|
||||||
|
NodeList propertiesList = doc.getElementsByTagName("properties");
|
||||||
|
Element properties;
|
||||||
|
if (propertiesList.getLength() == 0) {
|
||||||
|
properties = doc.createElement("properties");
|
||||||
|
root.appendChild(properties);
|
||||||
|
} else {
|
||||||
|
properties = (Element) propertiesList.item(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取或创建ParametersDefinitionProperty元素
|
||||||
|
NodeList paramDefProps = properties.getElementsByTagName("hudson.model.ParametersDefinitionProperty");
|
||||||
|
Element paramDefProp;
|
||||||
|
if (paramDefProps.getLength() == 0) {
|
||||||
|
paramDefProp = doc.createElement("hudson.model.ParametersDefinitionProperty");
|
||||||
|
properties.appendChild(paramDefProp);
|
||||||
|
} else {
|
||||||
|
paramDefProp = (Element) paramDefProps.item(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取或创建parameterDefinitions元素
|
||||||
|
NodeList paramDefs = paramDefProp.getElementsByTagName("parameterDefinitions");
|
||||||
|
Element parameterDefs;
|
||||||
|
if (paramDefs.getLength() == 0) {
|
||||||
|
parameterDefs = doc.createElement("parameterDefinitions");
|
||||||
|
paramDefProp.appendChild(parameterDefs);
|
||||||
|
} else {
|
||||||
|
parameterDefs = (Element) paramDefs.item(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建PIPELINE_SCRIPT参数定义
|
||||||
|
Element stringParam = doc.createElement("hudson.model.StringParameterDefinition");
|
||||||
|
|
||||||
|
Element name = doc.createElement("name");
|
||||||
|
name.setTextContent("PIPELINE_SCRIPT");
|
||||||
|
stringParam.appendChild(name);
|
||||||
|
|
||||||
|
Element description = doc.createElement("description");
|
||||||
|
description.setTextContent("Pipeline脚本内容");
|
||||||
|
stringParam.appendChild(description);
|
||||||
|
|
||||||
|
Element defaultValue = doc.createElement("defaultValue");
|
||||||
|
defaultValue.setTextContent("");
|
||||||
|
stringParam.appendChild(defaultValue);
|
||||||
|
|
||||||
|
Element trim = doc.createElement("trim");
|
||||||
|
trim.setTextContent("false");
|
||||||
|
stringParam.appendChild(trim);
|
||||||
|
|
||||||
|
parameterDefs.appendChild(stringParam);
|
||||||
|
|
||||||
|
// 更新Job配置时设置正确的编码
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
Transformer transformer = transformerFactory.newTransformer();
|
||||||
|
transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "UTF-8");
|
||||||
|
transformer.setOutputProperty(javax.xml.transform.OutputKeys.VERSION, "1.1");
|
||||||
|
transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
|
||||||
|
transformer.setOutputProperty(javax.xml.transform.OutputKeys.STANDALONE, "no");
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
transformer.transform(new DOMSource(doc), new StreamResult(writer));
|
||||||
|
String updatedConfig = writer.toString();
|
||||||
|
|
||||||
|
// 更新Job配置
|
||||||
|
HttpHeaders updateHeaders = createHeaders(externalSystem);
|
||||||
|
updateHeaders.setContentType(MediaType.APPLICATION_XML);
|
||||||
|
updateHeaders.set(HttpHeaders.ACCEPT_CHARSET, "UTF-8");
|
||||||
|
updateHeaders.set("Content-Type", "application/xml; charset=utf-8");
|
||||||
|
updateHeaders.set("Jenkins-Crumb", jenkinsCrumbIssue.getCrumb());
|
||||||
|
updateHeaders.set("Cookie", jenkinsCrumbIssue.getCookie());
|
||||||
|
HttpEntity<String> updateEntity = new HttpEntity<>(updatedConfig, updateHeaders);
|
||||||
|
restTemplate.exchange(
|
||||||
|
configUrl,
|
||||||
|
HttpMethod.POST,
|
||||||
|
updateEntity,
|
||||||
|
String.class
|
||||||
|
);
|
||||||
|
|
||||||
|
log.info("Successfully added PIPELINE_SCRIPT parameter to Jenkins job: {}", jobName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to ensure PIPELINE_SCRIPT parameter for Jenkins job: {}, error: {}", jobName, e.getMessage(), e);
|
||||||
|
throw new RuntimeException("确保Jenkins Job PIPELINE_SCRIPT参数失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理XML内容,移除无效字符
|
||||||
|
*/
|
||||||
|
private String cleanXmlContent(String xml) {
|
||||||
|
if (xml == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除XML中的无效字符
|
||||||
|
StringBuilder cleanXml = new StringBuilder();
|
||||||
|
for (int i = 0; i < xml.length(); i++) {
|
||||||
|
char c = xml.charAt(i);
|
||||||
|
// XML 1.1规范允许的字符范围(比1.0更宽松)
|
||||||
|
if ((c == 0x9) ||
|
||||||
|
(c == 0xA) ||
|
||||||
|
(c == 0xD) ||
|
||||||
|
((c >= 0x20) && (c <= 0xD7FF)) ||
|
||||||
|
((c >= 0xE000) && (c <= 0xFFFD)) ||
|
||||||
|
((c >= 0x10000) && (c <= 0x10FFFF)) ||
|
||||||
|
// 允许一些常见的控制字符
|
||||||
|
(c >= 0x1) && (c <= 0x1F)) {
|
||||||
|
cleanXml.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cleanXml.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JenkinsQueueBuildInfoResponse getQueuedBuildInfo(String queueId) {
|
public JenkinsQueueBuildInfoResponse getQueuedBuildInfo(String queueId) {
|
||||||
ExternalSystem externalSystem = systemRepository.findById(1L).orElseThrow(() -> new RuntimeException("没有找到三方系统"));
|
ExternalSystem externalSystem = systemRepository.findById(1L).orElseThrow(() -> new RuntimeException("没有找到三方系统"));
|
||||||
|
|||||||
@ -16,12 +16,6 @@ public class RepositoryBranchQuery extends BaseQuery {
|
|||||||
@QueryField(field = "name", type = QueryType.LIKE)
|
@QueryField(field = "name", type = QueryType.LIKE)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@QueryField(field = "project_id")
|
|
||||||
private Long projectId;
|
|
||||||
|
|
||||||
@QueryField(field = "external_system_id")
|
|
||||||
private Long externalSystemId;
|
|
||||||
|
|
||||||
@QueryField(field = "is_default_branch")
|
@QueryField(field = "is_default_branch")
|
||||||
private Boolean isDefaultBranch;
|
private Boolean isDefaultBranch;
|
||||||
|
|
||||||
@ -30,4 +24,13 @@ public class RepositoryBranchQuery extends BaseQuery {
|
|||||||
|
|
||||||
@QueryField(field = "commit_author", type = QueryType.LIKE)
|
@QueryField(field = "commit_author", type = QueryType.LIKE)
|
||||||
private String commitAuthor;
|
private String commitAuthor;
|
||||||
|
|
||||||
|
@QueryField(field = "externalSystemId", type = QueryType.EQUAL)
|
||||||
|
private Long externalSystemId;
|
||||||
|
|
||||||
|
@QueryField(field = "projectId", type = QueryType.EQUAL)
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
|
@QueryField(field = "repoProjectId", type = QueryType.EQUAL)
|
||||||
|
private Long repoProjectId;
|
||||||
}
|
}
|
||||||
@ -22,15 +22,15 @@ public class RepositoryProjectQuery extends BaseQuery {
|
|||||||
@QueryField(field = "visibility")
|
@QueryField(field = "visibility")
|
||||||
private String visibility;
|
private String visibility;
|
||||||
|
|
||||||
@QueryField(field = "externalSystemId")
|
@QueryField(field = "externalSystemId", type = QueryType.EQUAL)
|
||||||
private Long externalSystemId;
|
private Long externalSystemId;
|
||||||
|
|
||||||
@QueryField(field = "projectId")
|
@QueryField(field = "projectId", type = QueryType.EQUAL)
|
||||||
private Long projectId;
|
private Long projectId;
|
||||||
|
|
||||||
@QueryField(field = "repoGroupId")
|
@QueryField(field = "repoGroupId", type = QueryType.EQUAL)
|
||||||
private Long repoGroupId;
|
private Long repoGroupId;
|
||||||
|
|
||||||
@QueryField(field = "repoProjectId")
|
@QueryField(field = "repoProjectId", type = QueryType.EQUAL)
|
||||||
private Long repoProjectId;
|
private Long repoProjectId;
|
||||||
}
|
}
|
||||||
@ -62,6 +62,7 @@ public class DeployNodeDelegate extends BaseNodeDelegate<DeployNodePanelVariable
|
|||||||
protected void executeInternal(DelegateExecution execution, DeployNodePanelVariables panelVariables, DeployNodeLocalVariables localVariables) {
|
protected void executeInternal(DelegateExecution execution, DeployNodePanelVariables panelVariables, DeployNodeLocalVariables localVariables) {
|
||||||
ExternalSystem externalSystem = externalSystemRepository.findById(localVariables.getExternalSystemId()).orElseThrow(() -> new RuntimeException("ExternalSystem not found!!!"));
|
ExternalSystem externalSystem = externalSystemRepository.findById(localVariables.getExternalSystemId()).orElseThrow(() -> new RuntimeException("ExternalSystem not found!!!"));
|
||||||
JenkinsJob jenkinsJob = jenkinsJobRepository.findById(localVariables.getJobId()).orElseThrow(() -> new RuntimeException("Jenkins job not found!!!"));
|
JenkinsJob jenkinsJob = jenkinsJobRepository.findById(localVariables.getJobId()).orElseThrow(() -> new RuntimeException("Jenkins job not found!!!"));
|
||||||
|
// Pipeline脚本模板
|
||||||
Map<String, String> parameters = new HashMap<>();
|
Map<String, String> parameters = new HashMap<>();
|
||||||
parameters.put("PIPELINE_SCRIPT", localVariables.getScript());
|
parameters.put("PIPELINE_SCRIPT", localVariables.getScript());
|
||||||
String queueId = jenkinsServiceIntegration.buildWithParameters(externalSystem, jenkinsJob.getJobName(), parameters);
|
String queueId = jenkinsServiceIntegration.buildWithParameters(externalSystem, jenkinsJob.getJobName(), parameters);
|
||||||
|
|||||||
@ -652,7 +652,6 @@ CREATE TABLE deploy_app_config
|
|||||||
form_variables_schema TEXT NULL,
|
form_variables_schema TEXT NULL,
|
||||||
language_type VARCHAR(50) NOT NULL,
|
language_type VARCHAR(50) NOT NULL,
|
||||||
workflow_definition_id BIGINT NOT NULL,
|
workflow_definition_id BIGINT NOT NULL,
|
||||||
branch VARCHAR(50) NOT NULL,
|
|
||||||
|
|
||||||
environment_id BIGINT NOT NULL,
|
environment_id BIGINT NOT NULL,
|
||||||
application_id BIGINT NOT NULL,
|
application_id BIGINT NOT NULL,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user