Kaynağa Gözat

refactor: internal

Azure 2 yıl önce
ebeveyn
işleme
198382e001

+ 7 - 2
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/PipelineService.java

@@ -4,6 +4,7 @@ import cn.seecoder.build.model.vo.PipelineVO;
 import cn.seecoder.build.server.util.ServiceException;
 
 import java.util.List;
+import java.util.Map;
 
 public interface PipelineService {
 
@@ -11,7 +12,11 @@ public interface PipelineService {
 
     void delete(Integer id);
 
-    List<PipelineVO> getAll() throws ServiceException;
+    List<PipelineVO> getAll();
 
-    PipelineVO getDetailById(Integer id) throws ServiceException;
+    PipelineVO getDetailById(Integer id);
+
+    String getPipelineScript(Integer id) throws ServiceException;
+
+    Map<String, String> updateParamsWithPipeline(Integer id,Map<String, String> params) throws ServiceException;
 }

+ 6 - 8
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/JenkinsApi.java

@@ -1,9 +1,7 @@
 package cn.seecoder.build.server.service.facade.jenkins;
 
+import cn.seecoder.build.model.vo.BuildDetailsVO;
 import cn.seecoder.build.server.util.ServiceException;
-import com.offbytwo.jenkins.model.BaseModel;
-import com.offbytwo.jenkins.model.BuildWithDetails;
-import com.offbytwo.jenkins.model.QueueItem;
 
 import java.io.InputStream;
 import java.util.Map;
@@ -12,15 +10,15 @@ public interface JenkinsApi {
 
     void createJob(String jobName, String configTemplate) throws ServiceException;
 
-    QueueItem invokeBuild(String jobName, Map<String, String> params) throws ServiceException;
+    Integer invokeBuild(String jobName, Map<String, String> params) throws ServiceException;
 
     void deleteJob(String jobName) throws ServiceException;
 
-    BuildWithDetails fetchBuildDetails(String jobName, int buildNumber, boolean waitFinished) throws ServiceException;
+    BuildDetailsVO getBuildDetailsVO(String jobName, Integer buildId) throws ServiceException;
 
-    <T extends BaseModel> T get(BuildWithDetails build, String path, Class<T> cls) throws ServiceException;
 
-    String get(BuildWithDetails build, String path) throws ServiceException;
+    String getEntity(String jobName, Integer buildId, String path) throws ServiceException;
+
+    InputStream getArtifact(String jobName, Integer buildId, String path) throws ServiceException;
 
-    InputStream downloadArtifact(BuildWithDetails build, String relativePath) throws ServiceException;
 }

+ 27 - 0
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/JenkinsInternalApi.java

@@ -0,0 +1,27 @@
+package cn.seecoder.build.server.service.facade.jenkins;
+
+import cn.seecoder.build.model.vo.CoverageResult;
+import com.offbytwo.jenkins.model.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.util.Map;
+
+public interface JenkinsInternalApi {
+    BuildWithDetails getBuildDetails(Build build) throws IOException;
+
+    QueueReference invokeBuild(JobWithDetails jobWithDetails, Map<String, String> params) throws IOException;
+
+    <T extends BaseModel> T get(BuildWithDetails build, String path, Class<T> cls) throws IOException;
+
+    String getBuildConsoleOutputText(BuildWithDetails buildWithDetails) throws IOException;
+
+    String get(BuildWithDetails build, String path) throws IOException;
+
+    InputStream downloadArtifact(BuildWithDetails build, String relativePath) throws URISyntaxException, IOException;
+
+    TestResult getTestResult(BuildWithDetails buildWithDetails) throws IOException;
+
+    CoverageResult getCoverageResult(BuildWithDetails buildWithDetails) throws IOException;
+}

+ 14 - 0
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/entity/InternalBuild.java

@@ -0,0 +1,14 @@
+package cn.seecoder.build.server.service.facade.jenkins.entity;
+
+import cn.seecoder.build.server.util.ApplicationProperties;
+import com.offbytwo.jenkins.model.Build;
+
+public class InternalBuild extends Build {
+    public InternalBuild(Build build, ApplicationProperties.Jenkins jenkinsProperties){
+        super();
+        this.setNumber(build.getNumber());
+        this.setQueueId(build.getQueueId());
+        this.setUrl(build.getUrl().replace(jenkinsProperties.getExternalHost(), jenkinsProperties.getInternalHost()));
+
+    }
+}

+ 13 - 0
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/entity/InternalBuildWithDetails.java

@@ -0,0 +1,13 @@
+package cn.seecoder.build.server.service.facade.jenkins.entity;
+
+import cn.seecoder.build.server.util.ApplicationProperties;
+import com.offbytwo.jenkins.model.BuildWithDetails;
+
+public class InternalBuildWithDetails extends BuildWithDetails {
+    public InternalBuildWithDetails(BuildWithDetails buildWithDetails, ApplicationProperties.Jenkins jenkinsProperties){
+        super(buildWithDetails);
+        this.setNumber(buildWithDetails.getNumber());
+        this.setQueueId(buildWithDetails.getQueueId());
+        this.setUrl(buildWithDetails.getUrl().replace(jenkinsProperties.getExternalHost(), jenkinsProperties.getInternalHost()));
+    }
+}

+ 14 - 0
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/entity/InternalJob.java

@@ -0,0 +1,14 @@
+package cn.seecoder.build.server.service.facade.jenkins.entity;
+
+import cn.seecoder.build.server.util.ApplicationProperties;
+import com.offbytwo.jenkins.model.Job;
+
+public class InternalJob extends Job {
+    public InternalJob(Job job, ApplicationProperties.Jenkins jenkinsProperties){
+        super(job.getName(),
+                job.getUrl().replace(jenkinsProperties.getExternalHost(), jenkinsProperties.getInternalHost()),
+                job.getFullName());
+
+    }
+
+}

+ 0 - 12
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/impl/InternalJob.java

@@ -1,12 +0,0 @@
-package cn.seecoder.build.server.service.facade.jenkins.impl;
-
-import com.offbytwo.jenkins.client.JenkinsHttpClient;
-import com.offbytwo.jenkins.model.Job;
-
-public class InternalJob extends Job {
-    public InternalJob(JenkinsHttpClient client, String name, String url, String fullName){
-        super(name,url,fullName);
-        this.client=client;
-    }
-
-}

+ 179 - 46
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/impl/JenkinsApiImpl.java

@@ -1,6 +1,11 @@
 package cn.seecoder.build.server.service.facade.jenkins.impl;
 
+import cn.seecoder.build.model.vo.BuildDetailsVO;
+import cn.seecoder.build.model.vo.CoverageResult;
+import cn.seecoder.build.model.vo.MutationResult;
 import cn.seecoder.build.server.service.facade.jenkins.JenkinsApi;
+import cn.seecoder.build.server.service.facade.jenkins.JenkinsInternalApi;
+import cn.seecoder.build.server.service.model.converter.TestResultConvertor;
 import cn.seecoder.build.server.util.ApplicationProperties;
 import cn.seecoder.build.server.util.LoggerUtil;
 import cn.seecoder.build.server.util.ServiceException;
@@ -8,7 +13,10 @@ import com.alibaba.fastjson2.JSON;
 import com.offbytwo.jenkins.JenkinsServer;
 import com.offbytwo.jenkins.client.JenkinsHttpClient;
 import com.offbytwo.jenkins.model.*;
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.dom4j.*;
 import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
@@ -16,6 +24,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.List;
 import java.util.Map;
 
 @Service
@@ -26,19 +35,21 @@ public class JenkinsApiImpl implements JenkinsApi {
     private final ApplicationProperties properties;
 
     private JenkinsServer server;
-    private JenkinsHttpClient client;
+    private JenkinsInternalApi jenkinsInternalApi;
 
-    public JenkinsApiImpl(ApplicationProperties properties) {
+    @Autowired
+    public JenkinsApiImpl(ApplicationProperties properties, JenkinsInternalApi jenkinsInternalApi) {
         this.properties = properties;
+        this.jenkinsInternalApi = jenkinsInternalApi;
     }
 
     @PostConstruct
-    private void initialize() throws URISyntaxException, IOException {
+    private void initialize() throws URISyntaxException {
         ApplicationProperties.Jenkins jenkins = properties.getJenkins();
-        URI uri = new URI(jenkins.getHost());
+        URI internalURI = new URI(jenkins.getInternalHost());
         String username = jenkins.getUsername();
         String token = jenkins.getToken();
-        client = new PoolingJenkinsHttpClient(uri, username, token);
+        JenkinsHttpClient client = new PoolingJenkinsHttpClient(internalURI, username, token);
         server = new JenkinsServer(client);
     }
 
@@ -54,22 +65,18 @@ public class JenkinsApiImpl implements JenkinsApi {
     }
 
     @Override
-    public QueueItem invokeBuild(String jobName, Map<String, String> params) throws ServiceException {
+    public Integer invokeBuild(String jobName, Map<String, String> params) throws ServiceException {
         QueueReference reference;
         try {
-            JobWithDetails externalJob=server.getJob(jobName);
-            InternalJob job = new InternalJob(client,externalJob.getName(),
-                    externalJob.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080"),
-                    externalJob.getFullName());
-            if (params == null) {
-                reference = job.build();
-                logger.info(reference.getQueueItemUrlPart());
-            } else {
-                // 0.3.7版本的Jenkins客户端库中build(Map<String, String> params)方法存在BUG,会触发两次构建
-                reference = job.build(params, false);
-                logger.info(reference.getQueueItemUrlPart());
-            }
-            reference= new QueueReference(reference.getQueueItemUrlPart().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080"));
+//            if (params == null) {
+//                reference = server.getJob(jobName).build();
+//            } else {
+//                // 0.3.7版本的Jenkins客户端库中build(Map<String, String> params)方法存在BUG,会触发两次构建
+//                reference = server.getJob(jobName).build(params, false);
+//            }
+
+            JobWithDetails jobWithDetails = server.getJob(jobName);
+            reference = jenkinsInternalApi.invokeBuild(jobWithDetails,params);
             QueueItem item = server.getQueueItem(reference);
             while (item.getExecutable() == null) {
                 try {
@@ -79,7 +86,8 @@ public class JenkinsApiImpl implements JenkinsApi {
                 }
                 item = server.getQueueItem(reference);
             }
-            return item;
+
+            return item.getExecutable().getNumber().intValue();
         } catch (IOException e) {
             logger.error("invokeBuild exception={}, jobName={}, params={}", e, jobName, params);
             throw new ServiceException("101", e.getMessage());
@@ -96,59 +104,184 @@ public class JenkinsApiImpl implements JenkinsApi {
         }
     }
 
+
+    public <T extends BaseModel> T get(BuildWithDetails build, String path, Class<T> cls) throws ServiceException {
+        try {
+            //return  build.getClient().get(build.getUrl() + path, cls);
+            return jenkinsInternalApi.get(build, path, cls);
+        } catch (IOException e) {
+            logger.error("get exception={}, path={}", e, path);
+            throw new ServiceException("101", e.getMessage());
+        }
+    }
+    public String get(BuildWithDetails build, String path) throws ServiceException {
+        try {
+            //return  build.getClient().get(build.getUrl() + path);
+            return jenkinsInternalApi.get(build, path);
+        } catch (IOException e) {
+            logger.error("get exception={}, path={}", e, path);
+            throw new ServiceException("101", e.getMessage());
+        }
+    }
+
+
+    /**
+     *
+     * @param jobName job名
+     * @param buildId 构建id
+     * @return BuildDetailsVO
+     * @throws ServiceException
+     * 通过jobName和buildID获取BuildDetailsVO
+     *
+     */
     @Override
-    public BuildWithDetails fetchBuildDetails(String jobName, int buildNumber, boolean waitFinished) throws ServiceException {
+    public BuildDetailsVO getBuildDetailsVO(String jobName, Integer buildId) throws ServiceException{
+
+        BuildWithDetails buildWithDetails=getBuildDetails(jobName, buildId, true);
+
+        if(buildWithDetails==null){
+            logger.error("buildWithDetails为空, jobName={}, buildId={}", jobName, buildId);
+            throw new ServiceException("101","buildWithDetails为空");
+        }
+
+        BuildDetailsVO buildDetailsVO = new BuildDetailsVO();
+
+        buildDetailsVO.setBuildId(buildId);
+        buildDetailsVO.setJobName(jobName);
+        buildDetailsVO.setDuration(buildWithDetails.getDuration());
+        buildDetailsVO.setResult(buildWithDetails.getResult());
+        buildDetailsVO.setTimestamps(buildWithDetails.getTimestamp());
+        buildDetailsVO.setArtifacts(buildWithDetails.getArtifacts());
         try {
-            BuildWithDetails buildWithDetails;
-            Build build =server.getJob(jobName).getBuildByNumber(buildNumber);
-            buildWithDetails = build.getClient().get(build.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080"), BuildWithDetails.class);
+            //buildDetailsVO.setConsoleOutput(buildWithDetails.getConsoleOutputText());
+            buildDetailsVO.setConsoleOutput(jenkinsInternalApi.getBuildConsoleOutputText(buildWithDetails));
+
+            setBuildResult(buildWithDetails,buildDetailsVO);
+
+            logger.info(JSON.toJSONString(buildDetailsVO));
+            return buildDetailsVO;
+        }catch (IOException e){
+            logger.error("getBuildDetailsVO exception={}, jobName={}, buildId={}", e, jobName, buildId);
+            throw new ServiceException("101", e.getMessage());
+        }
+    }
+
+    public BuildWithDetails getBuildDetails(String jobName, int buildId, boolean waitFinished) throws ServiceException {
+        try {
+            // BuildWithDetails buildWithDetails=server.getJob(jobName).getBuildByNumber(buildNumber).details();
+            // 上面是Jenkins external地址没有https报错,不用使用k8s内部地址的情况
+            // 下面是需要使用k8s内部地址的情况
+            Build build = server.getJob(jobName).getBuildByNumber(buildId);
+            BuildWithDetails buildWithDetails = jenkinsInternalApi.getBuildDetails(build);
+
             while (waitFinished && (buildWithDetails.getResult() == null || buildWithDetails.getDuration() == 0)) {
                 try {
                     Thread.sleep(500);
                 } catch (InterruptedException e) {
                     Thread.currentThread().interrupt();
                 }
-                buildWithDetails = build.getClient().get(build.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080"), BuildWithDetails.class);
+                buildWithDetails = jenkinsInternalApi.getBuildDetails(build);
             }
             return buildWithDetails;
         } catch (IOException e) {
-            logger.error("fetchBuildDetails exception={}, jobName={}, buildNumber={}, waitFinished", e.getMessage(), jobName, buildNumber, waitFinished);
+            logger.error("getBuildDetails exception={}, jobName={}, buildId={}, waitFinished={}", e, jobName, buildId, waitFinished);
             throw new ServiceException("101", e.getMessage());
         }
     }
 
-    @Override
-    public <T extends BaseModel> T get(BuildWithDetails build, String path, Class<T> cls) throws ServiceException {
+    void setBuildResult(BuildWithDetails buildWithDetails,BuildDetailsVO buildDetailsVO) throws ServiceException {
+
+        TestResult testResult = getTestResult(buildWithDetails);
+
+        if (testResult != null) {
+            buildDetailsVO.setTestResultVO(TestResultConvertor.convertToVO(testResult));
+            return;
+        }
+
+        CoverageResult coverageResult = getCoverageResult(buildWithDetails);
+
+        if (coverageResult != null) {
+            buildDetailsVO.setCoverageResult(coverageResult);
+        } else {
+            try {
+                List<Artifact> artifactList = buildWithDetails.getArtifacts();
+                Artifact artifact = artifactList.stream().filter(a -> a.getFileName().equals("mutations.xml")).findFirst().orElse(null);
+                if (artifact != null) {
+                    MutationResult mutationResult = new MutationResult();
+                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+                    outputStream.write(downloadArtifact(buildWithDetails, artifact.getRelativePath()));
+                    String mutationReport = new String(outputStream.toByteArray());
+                    outputStream.close();
+                    Document document = DocumentHelper.parseText(mutationReport);
+                    Element root = document.getRootElement();
+                    for (Object element : root.elements("mutation")) {
+                        if (element instanceof Element) {
+                            Attribute attribute = ((Element) element).attribute("detected");
+                            if (attribute != null) {
+                                mutationResult.setMutations(mutationResult.getMutations() + 1);
+                                if ("true".equals(attribute.getValue())) {
+                                    mutationResult.setDetectedMutations(mutationResult.getDetectedMutations() + 1);
+                                }
+                            }
+                        }
+                    }
+                    buildDetailsVO.setMutationResult(mutationResult);
+                }
+            } catch (DocumentException e) {
+                logger.error("documentParseText exception="+e);
+                throw new ServiceException("101", e.getMessage());
+            } catch (IOException e) {
+                logger.error("writeArtifact exception="+e);
+                throw new ServiceException("101", e.getMessage());
+
+            }
+        }
+    }
+
+
+    public InputStream downloadArtifact(BuildWithDetails build, String relativePath) throws ServiceException {
         try {
-            return  build.getClient().get(build.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080") + path, cls);
-        } catch (IOException e) {
-            logger.error("get exception={}, path={}", e, path);
+            //Artifact artifact = new Artifact();
+            //artifact.setRelativePath(relativePath);
+            //return build.downloadArtifact(artifact);
+            return jenkinsInternalApi.downloadArtifact(build,relativePath);
+        } catch (IOException | URISyntaxException e) {
+            logger.error("downloadArtifact exception={}, relativePath={}", e, relativePath);
             throw new ServiceException("101", e.getMessage());
         }
     }
 
-    @Override
-    public String get(BuildWithDetails build, String path) throws ServiceException {
+    public TestResult getTestResult(BuildWithDetails buildWithDetails) throws ServiceException {
         try {
-            return  build.getClient().get(build.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080") + path);
-        } catch (IOException e) {
-            logger.error("get exception={}, path={}", e, path);
+            //return buildWithDetails.getTestResult();
+            return jenkinsInternalApi.getTestResult(buildWithDetails);
+        }catch (IOException e){
+            logger.error("getTestResult exception="+e);
             throw new ServiceException("101", e.getMessage());
         }
     }
 
-    @Override
-    public InputStream downloadArtifact(BuildWithDetails build, String relativePath) throws ServiceException {
+    public CoverageResult getCoverageResult(BuildWithDetails buildWithDetails) throws ServiceException {
         try {
-            Artifact artifact = new Artifact();
-            artifact.setRelativePath(relativePath);
-            URI uri = new URI(build.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080"));
-            String artifactPath = uri.getPath() + "artifact/" + artifact.getRelativePath();
-            URI artifactUri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), artifactPath, "", "");
-            return  build.getClient().getFile(artifactUri);
-        } catch (IOException | URISyntaxException e) {
-            logger.error("get exception={}, relativePath={}", e, relativePath);
+            //return buildWithDetails.getClient().get(buildWithDetails.getUrl() + "/cobertura/?depth=2", CoverageResult.class);
+            return jenkinsInternalApi.getCoverageResult(buildWithDetails);
+        }catch (IOException e){
+            logger.error("getCoverageResult exception="+e);
             throw new ServiceException("101", e.getMessage());
         }
     }
+
+
+
+    @Override
+    public String getEntity(String jobName, Integer buildId, String path) throws ServiceException {
+        BuildWithDetails buildWithDetails = getBuildDetails(jobName, buildId, true);
+        return get(buildWithDetails, path);
+    }
+
+    @Override
+    public InputStream getArtifact(String jobName, Integer buildId, String path) throws ServiceException {
+        BuildWithDetails buildWithDetails = getBuildDetails(jobName, buildId, true);
+        return downloadArtifact(buildWithDetails, path);
+    }
 }

+ 94 - 0
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/facade/jenkins/impl/JenkinsInternalApiImpl.java

@@ -0,0 +1,94 @@
+package cn.seecoder.build.server.service.facade.jenkins.impl;
+
+import cn.seecoder.build.model.vo.CoverageResult;
+import cn.seecoder.build.server.service.facade.jenkins.JenkinsInternalApi;
+import cn.seecoder.build.server.service.facade.jenkins.entity.InternalBuild;
+import cn.seecoder.build.server.service.facade.jenkins.entity.InternalBuildWithDetails;
+import cn.seecoder.build.server.service.facade.jenkins.entity.InternalJob;
+import cn.seecoder.build.server.util.ApplicationProperties;
+import cn.seecoder.build.server.util.LoggerUtil;
+
+import com.offbytwo.jenkins.model.*;
+import org.slf4j.Logger;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.util.Map;
+
+@Service
+public class JenkinsInternalApiImpl implements JenkinsInternalApi {
+    private static final Logger logger = LoggerUtil.getLogger(JenkinsApiImpl.class);
+
+    private final ApplicationProperties.Jenkins jenkinsProperties;
+
+    private static final String COVERAGE_PATH = "/cobertura/?depth=2";
+
+    public JenkinsInternalApiImpl(ApplicationProperties properties) {
+        this.jenkinsProperties = properties.getJenkins();
+    }
+
+
+    @Override
+    public BuildWithDetails getBuildDetails(Build build) throws IOException {
+        InternalBuild internalBuild = new InternalBuild(build, jenkinsProperties);
+        return internalBuild.details();
+
+    }
+
+    @Override
+    public QueueReference invokeBuild(JobWithDetails jobWithDetails, Map<String, String> params) throws IOException {
+        QueueReference reference;
+        InternalJob internalJob = new InternalJob(jobWithDetails, jenkinsProperties);
+        if (params == null) {
+            reference = internalJob.build();
+            logger.info("reference url part:" + reference.getQueueItemUrlPart());
+        } else {
+            // 0.3.7版本的Jenkins客户端库中build(Map<String, String> params)方法存在BUG,会触发两次构建
+            //reference = server.getJob(jobName).build(params, false);
+            reference = internalJob.build(params, false);
+            logger.info("reference url part:" + reference.getQueueItemUrlPart());
+        }
+        return reference;
+    }
+
+    @Override
+    public <T extends BaseModel> T get(BuildWithDetails buildWithDetails, String path, Class<T> cls) throws IOException {
+        InternalBuild internalBuild = new InternalBuild(buildWithDetails, jenkinsProperties);
+        return internalBuild.getClient().get(internalBuild.getUrl() + path, cls);
+    }
+
+    @Override
+    public String getBuildConsoleOutputText(BuildWithDetails buildWithDetails) throws IOException {
+        InternalBuildWithDetails internalBuildWithDetails=new InternalBuildWithDetails(buildWithDetails,jenkinsProperties);
+        return internalBuildWithDetails.getConsoleOutputText();
+    }
+
+    @Override
+    public String get(BuildWithDetails buildWithDetails, String path) throws IOException {
+        InternalBuild internalBuild = new InternalBuild(buildWithDetails, jenkinsProperties);
+        return internalBuild.getClient().get(internalBuild.getUrl() + path);
+    }
+
+    @Override
+    public InputStream downloadArtifact(BuildWithDetails buildWithDetails, String relativePath) throws URISyntaxException, IOException {
+        InternalBuildWithDetails internalBuildWithDetails = new InternalBuildWithDetails(buildWithDetails, jenkinsProperties);
+        Artifact artifact = new Artifact();
+        artifact.setRelativePath(relativePath);
+        return internalBuildWithDetails.downloadArtifact(artifact);
+
+    }
+
+    @Override
+    public TestResult getTestResult(BuildWithDetails buildWithDetails) throws IOException {
+        InternalBuildWithDetails internalBuildWithDetails = new InternalBuildWithDetails(buildWithDetails, jenkinsProperties);
+        return internalBuildWithDetails.getTestResult();
+    }
+
+    @Override
+    public CoverageResult getCoverageResult(BuildWithDetails buildWithDetails) throws IOException {
+        return get(buildWithDetails, COVERAGE_PATH, CoverageResult.class);
+    }
+}

+ 19 - 103
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/impl/JobServiceImpl.java

@@ -1,37 +1,24 @@
 package cn.seecoder.build.server.service.impl;
 
 import cn.seecoder.build.model.vo.BuildDetailsVO;
-import cn.seecoder.build.model.vo.CoverageResult;
-import cn.seecoder.build.model.vo.MutationResult;
-import cn.seecoder.build.model.vo.PipelineVO;
-import cn.seecoder.build.server.data.dao.PipelineDAO;
-import cn.seecoder.build.server.data.entity.Pipeline;
 import cn.seecoder.build.server.service.JobService;
+import cn.seecoder.build.server.service.PipelineService;
 import cn.seecoder.build.server.service.facade.jenkins.JenkinsApi;
-import cn.seecoder.build.server.service.facade.jenkins.impl.JenkinsApiImpl;
-import cn.seecoder.build.server.service.model.converter.PipelineConverter;
-import cn.seecoder.build.server.service.model.converter.TestResultConvertor;
+
 import cn.seecoder.build.server.util.LoggerUtil;
 import cn.seecoder.build.server.util.ServiceException;
-import com.alibaba.fastjson2.JSON;
-import com.offbytwo.jenkins.model.Artifact;
-import com.offbytwo.jenkins.model.BuildWithDetails;
-import com.offbytwo.jenkins.model.QueueItem;
-import com.offbytwo.jenkins.model.TestResult;
-import org.apache.commons.io.output.ByteArrayOutputStream;
+
+
 import org.apache.commons.lang3.RandomStringUtils;
-import org.dom4j.*;
+
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
-import java.io.IOException;
+
 import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.List;
+
 import java.util.Map;
 
 @Service
@@ -40,24 +27,21 @@ public class JobServiceImpl implements JobService {
 
     private final JenkinsApi jenkinsApi;
 
-    private final PipelineDAO pipelineDAO;
+    private final PipelineService pipelineService;
 
     @Autowired
-    public JobServiceImpl(JenkinsApi jenkinsApi, PipelineDAO pipelineDAO) {
+    public JobServiceImpl(JenkinsApi jenkinsApi, PipelineService pipelineService) {
         this.jenkinsApi = jenkinsApi;
-        this.pipelineDAO = pipelineDAO;
+        this.pipelineService = pipelineService;
     }
 
     @Override
     public String createJob(Integer pipelineId, String jobName) throws ServiceException {
-        Pipeline pipeline = pipelineDAO.findById(pipelineId).orElse(null);
-        if (pipeline == null) {
-            throw ServiceException.BAD_REQUEST;
-        }
         if (StringUtils.isEmpty(jobName)) {
             jobName = RandomStringUtils.random(8, true, true);
         }
-        jenkinsApi.createJob(jobName, pipeline.getScript());
+        String pipelineScript = pipelineService.getPipelineScript(pipelineId);
+        jenkinsApi.createJob(jobName, pipelineScript);
         return jobName;
     }
 
@@ -68,96 +52,28 @@ public class JobServiceImpl implements JobService {
 
     @Override
     public BuildDetailsVO getBuildDetails(String jobName, Integer buildId) throws ServiceException {
-        BuildWithDetails buildWithDetails  = jenkinsApi.fetchBuildDetails(jobName, buildId, true);
-        if (buildWithDetails != null) {
-            try {
-                BuildDetailsVO buildDetailsVO = new BuildDetailsVO();
-                buildDetailsVO.setBuildId(buildId);
-                buildDetailsVO.setJobName(jobName);
-                buildDetailsVO.setConsoleOutput(buildWithDetails.getConsoleOutputText());
-                buildDetailsVO.setDuration(buildWithDetails.getDuration());
-                buildDetailsVO.setResult(buildWithDetails.getResult());
-                buildDetailsVO.setTimestamps(buildWithDetails.getTimestamp());
-                buildDetailsVO.setArtifacts(buildWithDetails.getArtifacts());
-                logger.info(JSON.toJSONString(buildDetailsVO));
-                fetchBuildResult(buildWithDetails, buildDetailsVO);
-                return buildDetailsVO;
-            } catch (IOException  | DocumentException | URISyntaxException e) {
-                logger.info(e.getMessage());
-                throw ServiceException.BAD_REQUEST;
-            }
-        }
-        return null;
+        return jenkinsApi.getBuildDetailsVO(jobName, buildId);
+
     }
 
     @Override
     public String getEntity(String jobName, Integer buildId, String path) throws ServiceException {
-        BuildWithDetails buildWithDetails  = jenkinsApi.fetchBuildDetails(jobName, buildId, true);
-        return jenkinsApi.get(buildWithDetails, path);
+        return jenkinsApi.getEntity(jobName, buildId, path);
     }
 
     @Override
     public InputStream getArtifact(String jobName, Integer buildId, String path) throws ServiceException {
-        BuildWithDetails buildWithDetails  = jenkinsApi.fetchBuildDetails(jobName, buildId, true);
-        return jenkinsApi.downloadArtifact(buildWithDetails, path);
+        return jenkinsApi.getArtifact(jobName, buildId, path);
     }
 
     @Override
     public Integer invokeBuild(Integer pipelineId, String jobName, Map<String, String> params) throws ServiceException {
-        Pipeline pipeline = pipelineDAO.findById(pipelineId).orElse(null);
-        if (pipeline == null) {
-            throw ServiceException.BAD_REQUEST;
-        }
         if (StringUtils.isEmpty(jobName)) {
+            logger.error("jobName为空");
             throw ServiceException.BAD_REQUEST;
         }
-        PipelineVO vo = PipelineConverter.convertToVO(pipeline);
-        if (!CollectionUtils.isEmpty(vo.getParams())) {
-            vo.getParams().forEach(entry -> {
-                if (!params.containsKey(entry.getName())) {
-                    params.put(entry.getName(), entry.getDefaultValue() == null ? null : entry.getDefaultValue());
-                }
-            });
-        }
-        QueueItem item = jenkinsApi.invokeBuild(jobName, params);
-        return item.getExecutable().getNumber().intValue();
+        params = pipelineService.updateParamsWithPipeline(pipelineId, params);
+        return jenkinsApi.invokeBuild(jobName, params);
     }
 
-    private void fetchBuildResult(BuildWithDetails buildWithDetails, BuildDetailsVO buildDetailsVO) throws IOException, URISyntaxException, DocumentException {
-        TestResult testResult = buildWithDetails.getClient().get(buildWithDetails.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080") + "/testReport/?depth=1", TestResult.class);;
-        if (testResult != null) {
-            buildDetailsVO.setTestResultVO(TestResultConvertor.convertToVO(testResult));
-            return;
-        }
-        CoverageResult coverageResult = buildWithDetails.getClient().get(buildWithDetails.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080") + "/cobertura/?depth=2", CoverageResult.class);
-        if (coverageResult != null) {
-            buildDetailsVO.setCoverageResult(coverageResult);
-        } else {
-            List<Artifact> artifactList = buildWithDetails.getArtifacts();
-            Artifact artifact = artifactList.stream().filter(a -> a.getFileName().equals("mutations.xml")).findFirst().orElse(null);
-            if (artifact != null) {
-                MutationResult mutationResult = new MutationResult();
-                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-                URI uri = new URI(buildWithDetails.getUrl().replace("build-jenkins.internal-paas.seec.seecoder.cn","environment-9-12.seec.svc.cluster.local:8080"));
-                String artifactPath = uri.getPath() + "artifact/" + artifact.getRelativePath();
-                URI artifactUri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), artifactPath, "", "");
-                outputStream.write(buildWithDetails.getClient().getFile(artifactUri));
-                String mutationReport = new String(outputStream.toByteArray());
-                Document document = DocumentHelper.parseText(mutationReport);
-                Element root = document.getRootElement();
-                for (Object element : root.elements("mutation")) {
-                    if (element instanceof Element) {
-                        Attribute attribute = ((Element) element).attribute("detected");
-                        if (attribute != null) {
-                            mutationResult.setMutations(mutationResult.getMutations() + 1);
-                            if ("true".equals(attribute.getValue())) {
-                                mutationResult.setDetectedMutations(mutationResult.getDetectedMutations() + 1);
-                            }
-                        }
-                    }
-                }
-                buildDetailsVO.setMutationResult(mutationResult);
-            }
-        }
-    }
 }

+ 34 - 3
seecoder-build-server/src/main/java/cn/seecoder/build/server/service/impl/PipelineServiceImpl.java

@@ -14,6 +14,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -22,6 +23,7 @@ import org.w3c.dom.NodeList;
 import javax.transaction.Transactional;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @Service
@@ -56,7 +58,7 @@ public class PipelineServiceImpl implements PipelineService {
             PipelineVO result = PipelineConverter.convertToVO(pipelineDAO.save(pipeline));
             return result;
         } catch (JsonProcessingException e) {
-            logger.error("json write error, params={}, vo={}", e, paramVOS, vo);
+            logger.error("json write error, exception={}, params={}, vo={}", e, paramVOS, vo);
             throw new ServiceException("103", e.getMessage());
         }
     }
@@ -68,7 +70,7 @@ public class PipelineServiceImpl implements PipelineService {
     }
 
     @Override
-    public List<PipelineVO> getAll() throws ServiceException {
+    public List<PipelineVO> getAll() {
         return pipelineDAO.findAll().stream().map(PipelineConverter::convertToVO).collect(Collectors.toList());
     }
 
@@ -76,10 +78,39 @@ public class PipelineServiceImpl implements PipelineService {
     public PipelineVO getDetailById(Integer id) throws ServiceException {
         Pipeline pipeline = pipelineDAO.findById(id).orElse(null);
         if (pipeline == null) {
-            return null;
+            logger.error("pipeline为空, id={}",id);
+            throw ServiceException.BAD_REQUEST;
         }
         PipelineVO vo = PipelineConverter.convertToVO(pipeline);
         return vo;
     }
 
+    @Override
+    public String getPipelineScript(Integer id) throws ServiceException {
+        Pipeline pipeline = pipelineDAO.findById(id).orElse(null);
+        if (pipeline == null) {
+            logger.error("pipeline为空, id={}",id);
+            throw ServiceException.BAD_REQUEST;
+        }
+        return pipeline.getScript();
+    }
+
+    @Override
+    public Map<String, String> updateParamsWithPipeline(Integer id, Map<String, String> params) throws ServiceException {
+        Pipeline pipeline = pipelineDAO.findById(id).orElse(null);
+        if (pipeline == null) {
+            logger.error("pipeline为空, id={}",id);
+            throw ServiceException.BAD_REQUEST;
+        }
+        PipelineVO vo = PipelineConverter.convertToVO(pipeline);
+        if (!CollectionUtils.isEmpty(vo.getParams())) {
+            vo.getParams().forEach(entry -> {
+                if (!params.containsKey(entry.getName())) {
+                    params.put(entry.getName(), entry.getDefaultValue() == null ? null : entry.getDefaultValue());
+                }
+            });
+        }
+        return params;
+    }
+
 }

+ 4 - 1
seecoder-build-server/src/main/java/cn/seecoder/build/server/util/ApplicationProperties.java

@@ -21,7 +21,10 @@ public class ApplicationProperties {
     public static class Jenkins {
         @URL
         @NotEmpty
-        private String host;
+        private String externalHost;
+        @URL
+        @NotEmpty
+        private String internalHost;
         @NotEmpty
         private String username = "root";
         @NotEmpty