package org.jenkinsci.plugins.ghprb.manager.impl; import hudson.model.Job; import hudson.model.Result; import hudson.model.Run; import hudson.tasks.junit.CaseResult; import hudson.tasks.junit.TestResult; import hudson.tasks.test.AbstractTestResultAction; import hudson.tasks.test.AggregatedTestResultAction; import hudson.tasks.test.AggregatedTestResultAction.ChildReport; import jenkins.model.Jenkins; import org.jenkinsci.plugins.ghprb.manager.GhprbBuildManager; import org.jenkinsci.plugins.ghprb.manager.configuration.JobConfiguration; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * @author mdelapenya (Manuel de la Peña) */ public abstract class GhprbBaseBuildManager implements GhprbBuildManager { public GhprbBaseBuildManager(Run<?, ?> build) { this.build = build; this.jobConfiguration = buildDefaultConfiguration(); } public GhprbBaseBuildManager(Run<?, ?> build, JobConfiguration jobConfiguration) { this.build = build; this.jobConfiguration = jobConfiguration; } private JobConfiguration buildDefaultConfiguration() { return JobConfiguration.builder().printStackTrace(false).build(); } /** * Calculate the build URL of a build of default type. This will be overriden by specific build types. * * @return the build URL of a build of default type */ public String calculateBuildUrl(String publishedURL) { return publishedURL + "/" + build.getUrl(); } /** * Return a downstream iterator of a build of default type. This will be overriden by specific build types. * * If the receiver of the call has no child projects, it will return an iterator over itself * * @return the downstream builds as an iterator */ public Iterator<?> downstreamProjects() { List<Run<?, ?>> downstreamList = new ArrayList<Run<?, ?>>(); downstreamList.add(build); return downstreamList.iterator(); } public JobConfiguration getJobConfiguration() { return this.jobConfiguration; } /** * Return the tests results of a build of default type. This will be overriden by specific build types. * * @return the tests result of a build of default type */ public String getTestResults() { return getAggregatedTestResults(build); } protected String getAggregatedTestResults(Run<?, ?> build) { AggregatedTestResultAction testResultAction = build.getAction(AggregatedTestResultAction.class); if (testResultAction == null) { return ""; } StringBuilder sb = new StringBuilder(); if (build.getResult() != Result.UNSTABLE) { sb.append("<h2>Build result: "); sb.append(build.getResult().toString()); sb.append("</span></h2>"); try { List<String> buildLog = build.getLog(_MAX_LINES_COUNT); for (String buildLogLine : buildLog) { sb.append(buildLogLine); } } catch (IOException ioe) { LOGGER.log(Level.WARNING, ioe.getMessage()); } return sb.toString(); } sb.append("<h2>Failed Tests: "); sb.append("<span class='status-failure'>"); sb.append(testResultAction.getFailCount()); sb.append("</span></h2>"); List<ChildReport> childReports = testResultAction.getChildReports(); for (ChildReport report : childReports) { TestResult result = (TestResult) report.result; if (result.getFailCount() < 1) { continue; } Job<?, ?> project = (Job<?, ?>) report.child.getProject(); String baseUrl = Jenkins.getInstance().getRootUrl() + build.getUrl() + project.getShortUrl() + "testReport"; sb.append("<h3>"); sb.append("<a name='"); sb.append(project.getFullName()); sb.append("' />"); sb.append("<a href='"); sb.append(baseUrl); sb.append("'>"); sb.append(project.getFullName()); sb.append("</a>"); sb.append(": "); sb.append("<span class='status-failure'>"); sb.append(result.getFailCount()); sb.append("</span></h3>"); sb.append("<ul>"); List<CaseResult> failedTests = result.getFailedTests(); for (CaseResult failedTest : failedTests) { sb.append("<li>"); sb.append("<a href='"); sb.append(baseUrl); sb.append("/"); sb.append(failedTest.getRelativePathFrom(result)); sb.append("'>"); sb.append("<strong>"); sb.append(failedTest.getFullDisplayName()); sb.append("</strong>"); sb.append("</a>"); if (getJobConfiguration().printStackTrace()) { sb.append("\n```\n"); sb.append(failedTest.getErrorStackTrace()); sb.append("\n```\n"); } sb.append("</li>"); } sb.append("</ul>"); } return sb.toString(); } protected static final Logger LOGGER = Logger.getLogger(GhprbBaseBuildManager.class.getName()); public String getOneLineTestResults() { AbstractTestResultAction testResultAction = build.getAction(AbstractTestResultAction.class); if (testResultAction == null) { return "No test results found."; } return String.format("%d tests run, %d skipped, %d failed.", testResultAction.getTotalCount(), testResultAction.getSkipCount(), testResultAction.getFailCount()); } protected Run<?, ?> build; private static final int _MAX_LINES_COUNT = 25; private JobConfiguration jobConfiguration; }