com.liferay.jenkins.results.parser.BatchBuild Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.jenkins.results.parser
Show all versions of com.liferay.jenkins.results.parser
Liferay Jenkins Results Parser
The newest version!
/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
package com.liferay.jenkins.results.parser;
import com.liferay.jenkins.results.parser.failure.message.generator.ClosedChannelExceptionFailureMessageGenerator;
import com.liferay.jenkins.results.parser.failure.message.generator.FailureMessageGenerator;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.dom4j.Element;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* @author Kevin Yen
*/
public class BatchBuild extends BaseParentBuild {
@Override
public void addTimelineData(TimelineData timelineData) {
addDownstreamBuildsTimelineData(timelineData);
}
@Override
public URL getArtifactsBaseURL() {
TopLevelBuild topLevelBuild = getTopLevelBuild();
StringBuilder sb = new StringBuilder();
sb.append(topLevelBuild.getArtifactsBaseURL());
sb.append("/");
sb.append(getParameterValue("JOB_VARIANT"));
try {
return new URL(sb.toString());
}
catch (MalformedURLException malformedURLException) {
return null;
}
}
public String getBatchName() {
return batchName;
}
@Override
public String getBuildName() {
String buildName = getJobVariant();
if (JenkinsResultsParserUtil.isNullOrEmpty(buildName)) {
buildName = getJobName();
}
return buildName;
}
public List getDownstreamAxisBuilds() {
List downstreamAxisBuilds = new ArrayList<>();
List downstreamBuilds = getDownstreamBuilds(null);
for (Build downstreamBuild : downstreamBuilds) {
if (!(downstreamBuild instanceof AxisBuild)) {
continue;
}
downstreamAxisBuilds.add((AxisBuild)downstreamBuild);
}
Collections.sort(
downstreamAxisBuilds, new BaseBuild.BuildDisplayNameComparator());
return downstreamAxisBuilds;
}
@Override
public Element getGitHubMessageElement() {
sortDownstreamBuilds();
Element messageElement = super.getGitHubMessageElement();
if (messageElement == null) {
return null;
}
String result = getResult();
if (result.equals("ABORTED") && (getDownstreamBuildCount(null) == 0)) {
_gitHubMessageElement = messageElement;
return _gitHubMessageElement;
}
List failedDownstreamBuilds = getFailedDownstreamBuilds();
List downstreamBuildMessageElements =
getDownstreamBuildMessageElements(failedDownstreamBuilds);
if (result.equals("FAILURE") &&
downstreamBuildMessageElements.isEmpty()) {
_gitHubMessageElement = messageElement;
return _gitHubMessageElement;
}
List failureElements = new ArrayList<>();
List upstreamJobFailureElements = new ArrayList<>();
for (Build failedDownstreamBuild : failedDownstreamBuilds) {
Element gitHubMessageElement =
failedDownstreamBuild.getGitHubMessageElement();
if (gitHubMessageElement != null) {
failureElements.add(gitHubMessageElement);
}
Element gitHubMessageUpstreamJobFailureElement =
failedDownstreamBuild.
getGitHubMessageUpstreamJobFailureElement();
if (gitHubMessageUpstreamJobFailureElement != null) {
upstreamJobFailureElements.add(
gitHubMessageUpstreamJobFailureElement);
}
}
if (!upstreamJobFailureElements.isEmpty()) {
upstreamJobFailureMessageElement = getGitHubMessageElement(true);
Dom4JUtil.getOrderedListElement(
upstreamJobFailureElements, upstreamJobFailureMessageElement,
4);
}
Dom4JUtil.getOrderedListElement(failureElements, messageElement, 4);
if (failureElements.size() >= 4) {
Dom4JUtil.getNewElement(
"strong", messageElement, "Click ",
Dom4JUtil.getNewAnchorElement(
getBuildURL() + "testReport", "here"),
" for more failures.");
}
if (failureElements.isEmpty()) {
return null;
}
_gitHubMessageElement = messageElement;
return _gitHubMessageElement;
}
@Override
public Long getInvokedTime() {
if (invokedTime != null) {
return invokedTime;
}
StringBuilder sb = new StringBuilder();
sb.append("\\s*\\[echo\\]\\s*");
sb.append(Pattern.quote(getJobName()));
String jobVariant = getJobVariant();
if ((jobVariant != null) && !jobVariant.isEmpty()) {
sb.append("/");
sb.append(Pattern.quote(jobVariant));
}
sb.append("\\s*invoked time: (?[^\\n]*)");
Pattern pattern = Pattern.compile(sb.toString());
Build parentBuild = getParentBuild();
String parentConsoleText = parentBuild.getConsoleText();
for (String line : parentConsoleText.split("\n")) {
Matcher matcher = pattern.matcher(line);
if (!matcher.find()) {
continue;
}
Properties buildProperties = null;
try {
buildProperties = JenkinsResultsParserUtil.getBuildProperties();
}
catch (IOException ioException) {
throw new RuntimeException(
"Unable to get build properties", ioException);
}
SimpleDateFormat sdf = new SimpleDateFormat(
buildProperties.getProperty("jenkins.report.date.format"));
Date date = null;
try {
date = sdf.parse(matcher.group("invokedTime"));
}
catch (ParseException parseException) {
throw new RuntimeException(
"Unable to get invoked time", parseException);
}
invokedTime = date.getTime();
return invokedTime;
}
return getStartTime();
}
@Override
public Map getMetricLabels() {
Map metricLabels = super.getMetricLabels();
metricLabels.put("job_type", batchName);
return metricLabels;
}
@Override
public synchronized List getTestClassResults() {
List testClassResults = new ArrayList<>();
for (AxisBuild axisBuild : getDownstreamAxisBuilds()) {
testClassResults.addAll(axisBuild.getTestClassResults());
}
return testClassResults;
}
@Override
public synchronized List getTestResults() {
List testResults = new ArrayList<>();
for (AxisBuild axisBuild : getDownstreamAxisBuilds()) {
testResults.addAll(axisBuild.getTestResults());
}
return testResults;
}
@Override
public long getTotalDuration() {
long totalDuration = super.getTotalDuration();
return totalDuration - getDuration();
}
@Override
public int getTotalSlavesUsedCount() {
return getTotalSlavesUsedCount(null, false);
}
@Override
public int getTotalSlavesUsedCount(
String status, boolean modifiedBuildsOnly) {
return getTotalSlavesUsedCount(status, modifiedBuildsOnly, true);
}
@Override
public void saveBuildURLInBuildDatabase() {
BuildDatabase buildDatabase = getBuildDatabase();
buildDatabase.putProperty(
BUILD_URLS_PROPERTIES_KEY, getBatchName(), getBuildURL(), false);
}
protected BatchBuild(String url) {
this(url, null);
}
protected BatchBuild(String url, TopLevelBuild topLevelBuild) {
super(url, topLevelBuild);
String jobVariant = getJobVariant();
if ((jobVariant != null) && !jobVariant.isEmpty()) {
Matcher matcher = _jobVariantPattern.matcher(jobVariant);
if (!matcher.matches()) {
throw new RuntimeException(
JenkinsResultsParserUtil.combine(
"Unable to find batch name of batch build from ",
"job variant '", jobVariant,
"'. Job variant must match pattern '",
_jobVariantPattern.pattern(), "'."));
}
batchName = matcher.group("batchName");
}
else {
batchName = null;
}
}
@Override
protected void findDownstreamBuilds() {
List downstreamBuildURLs = new ArrayList<>();
JSONObject buildJSONObject = getBuildJSONObject("runs[number,url]");
if ((buildJSONObject != null) && buildJSONObject.has("runs")) {
JSONArray runsJSONArray = buildJSONObject.getJSONArray("runs");
if (runsJSONArray != null) {
for (int i = 0; i < runsJSONArray.length(); i++) {
JSONObject runJSONObject = runsJSONArray.getJSONObject(i);
if (runJSONObject.getInt("number") != getBuildNumber()) {
continue;
}
String url = runJSONObject.getString("url");
if (hasBuildURL(url) || downstreamBuildURLs.contains(url)) {
continue;
}
downstreamBuildURLs.add(url);
}
}
}
addDownstreamBuilds(downstreamBuildURLs.toArray(new String[0]));
}
protected AxisBuild getAxisBuild(String axisVariable) {
for (AxisBuild downstreamAxisBuild : getDownstreamAxisBuilds()) {
if (axisVariable.equals(downstreamAxisBuild.getAxisVariable())) {
return downstreamAxisBuild;
}
}
return null;
}
@Override
protected ExecutorService getExecutorService() {
return _executorService;
}
@Override
protected Element getFailureMessageElement() {
for (FailureMessageGenerator failureMessageGenerator :
getFailureMessageGenerators()) {
Element failureMessage = failureMessageGenerator.getMessageElement(
this);
if (failureMessage != null) {
return failureMessage;
}
}
return null;
}
@Override
protected FailureMessageGenerator[] getFailureMessageGenerators() {
return _FAILURE_MESSAGE_GENERATORS;
}
@Override
protected Element getGitHubMessageJobResultsElement() {
return getGitHubMessageJobResultsElement(false);
}
@Override
protected Element getGitHubMessageJobResultsElement(
boolean showCommonFailuresCount) {
String result = getResult();
int failCount = getDownstreamBuildCountByResult("FAILURE");
int successCount = getDownstreamBuildCountByResult("SUCCESS");
if (result.equals("UNSTABLE")) {
failCount = getTestCountByStatus("FAILURE");
successCount = getTestCountByStatus("SUCCESS");
if (isCompareToUpstream()) {
List upstreamJobFailureTestResults =
getUpstreamJobFailureTestResults();
int upstreamFailCount = upstreamJobFailureTestResults.size();
if (showCommonFailuresCount) {
failCount = upstreamFailCount;
}
else {
failCount = failCount - upstreamFailCount;
}
}
}
return Dom4JUtil.getNewElement(
"div", null, Dom4JUtil.getNewElement("h6", null, "Job Results:"),
Dom4JUtil.getNewElement(
"p", null, String.valueOf(successCount),
JenkinsResultsParserUtil.getNounForm(
successCount, " Tests", " Test"),
" Passed.", Dom4JUtil.getNewElement("br"),
String.valueOf(failCount),
JenkinsResultsParserUtil.getNounForm(
failCount, " Tests", " Test"),
" Failed."));
}
@Override
protected String getJenkinsReportBuildInfoCellElementTagName() {
return "th";
}
@Override
protected List getJenkinsReportTableRowElements(
String result, String status) {
List tableRowElements = new ArrayList<>();
tableRowElements.add(getJenkinsReportTableRowElement());
for (AxisBuild downstreamAxisBuild : getDownstreamAxisBuilds()) {
tableRowElements.addAll(
downstreamAxisBuild.getJenkinsReportTableRowElements(
downstreamAxisBuild.getResult(),
downstreamAxisBuild.getStatus()));
}
return tableRowElements;
}
@Override
protected int getTestCountByStatus(String status) {
JSONObject testReportJSONObject = getTestReportJSONObject(false);
int failCount = testReportJSONObject.getInt("failCount");
if (status.equals("SUCCESS")) {
int totalCount = testReportJSONObject.getInt("totalCount");
int skipCount = testReportJSONObject.getInt("skipCount");
return totalCount - skipCount - failCount;
}
if (status.equals("FAILURE")) {
return failCount;
}
throw new IllegalArgumentException("Invalid status: " + status);
}
protected final String batchName;
private static final FailureMessageGenerator[] _FAILURE_MESSAGE_GENERATORS =
{new ClosedChannelExceptionFailureMessageGenerator()};
private static final ExecutorService _executorService =
JenkinsResultsParserUtil.getNewThreadPoolExecutor(10, true);
private static final Pattern _jobVariantPattern = Pattern.compile(
"(?[^/]+)(/.*)?");
private Element _gitHubMessageElement;
}