All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.jenkins.results.parser.PullRequest Maven / Gradle / Ivy

There is a newer version: 1.0.1492
Show 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.atlassian.jira.rest.client.api.domain.Issue;

import com.liferay.jenkins.results.parser.JenkinsResultsParserUtil.HttpRequestMethod;

import java.io.File;
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.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import org.json.JSONArray;
import org.json.JSONObject;

/**
 * @author Michael Hashimoto
 */
public class PullRequest {

	public static String getURL(
		String username, String repositoryName, String pullRequestNumber) {

		StringBuilder sb = new StringBuilder();

		sb.append("https://github.com/");
		sb.append(username);
		sb.append("/");
		sb.append(repositoryName);
		sb.append("/pull/");
		sb.append(pullRequestNumber);

		return sb.toString();
	}

	public static boolean isValidGitHubPullRequestURL(String gitHubURL) {
		Matcher matcher = _gitHubPullRequestURLPattern.matcher(gitHubURL);

		if (matcher.find()) {
			return true;
		}

		return false;
	}

	public Comment addComment(String body) {
		body = body.replaceAll("(\\>)\\s+(\\<)", "$1$2");
		body = body.replace(""", "\\"");

		JSONObject dataJSONObject = new JSONObject();

		dataJSONObject.put("body", body);

		try {
			JSONObject responseJSONObject =
				JenkinsResultsParserUtil.toJSONObject(
					JenkinsResultsParserUtil.combine(
						_jsonObject.getString("issue_url"), "/comments"),
					dataJSONObject.toString());

			return new Comment(responseJSONObject);
		}
		catch (GitHubSecondaryRateLimitRuntimeException
					gitHubSecondaryRateLimitRuntimeException) {

			StringBuilder sb = new StringBuilder();

			sb.append("Unable to post comment in GitHub pull request\n");
			sb.append("URL: ");
			sb.append(getURL());
			sb.append("\nMessage:\n");
			sb.append(body);
			sb.append("\n");

			NotificationUtil.sendSlackNotification(
				sb.toString(), "#ci-notifications", ":liferay-ci:",
				"Secondary Rate Limit exceeded", "Liferay CI");

			throw new GitHubSecondaryRateLimitRuntimeException(
				gitHubSecondaryRateLimitRuntimeException.getGitHubApiUrl(),
				gitHubSecondaryRateLimitRuntimeException.getRetryAfterSeconds(),
				sb.toString(), gitHubSecondaryRateLimitRuntimeException);
		}
		catch (IOException ioException) {
			throw new RuntimeException(
				"Unable to post comment in GitHub pull request " + getURL(),
				ioException);
		}
	}

	public boolean addLabel(GitHubRemoteGitRepository.Label label) {
		if ((label == null) || hasLabel(label.getName())) {
			return true;
		}

		GitHubRemoteGitRepository gitHubRemoteGitRepository =
			getGitHubRemoteGitRepository();

		GitHubRemoteGitRepository.Label gitRepositoryLabel =
			gitHubRemoteGitRepository.getLabel(label.getName());

		if (gitRepositoryLabel == null) {
			System.out.println(
				JenkinsResultsParserUtil.combine(
					"GitHubRemoteGitRepository.Label ", label.getName(),
					" does not exist in ", getGitHubRemoteGitRepositoryName()));

			return false;
		}

		JSONArray jsonArray = new JSONArray();

		jsonArray.put(label.getName());

		String gitHubApiUrl = JenkinsResultsParserUtil.getGitHubApiUrl(
			getGitHubRemoteGitRepositoryName(), getOwnerUsername(),
			"issues/" + getNumber() + "/labels");

		try {
			JenkinsResultsParserUtil.toString(
				gitHubApiUrl, false, HttpRequestMethod.POST,
				jsonArray.toString());
		}
		catch (IOException ioException) {
			System.out.println("Unable to add label " + label.getName());

			ioException.printStackTrace();

			return false;
		}

		return true;
	}

	public void close() {
		if (Objects.equals(getState(), "open")) {
			JSONObject postContentJSONObject = new JSONObject();

			postContentJSONObject.put("state", "closed");

			try {
				JenkinsResultsParserUtil.toString(
					_jsonObject.getString("url"), false, HttpRequestMethod.POST,
					postContentJSONObject.toString());
			}
			catch (IOException ioException) {
				throw new RuntimeException(
					"Unable to close pull request " + getHtmlURL(),
					ioException);
			}
		}

		_jsonObject.put("state", "closed");
	}

	public String forward(
		String commentBody, String consoleURL, String forwardReceiverUsername,
		String forwardBranchName, String forwardSenderUsername,
		File gitRepositoryDir) {

		GitWorkingDirectory gitWorkingDirectory =
			GitWorkingDirectoryFactory.newGitWorkingDirectory(
				getUpstreamRemoteGitBranchName(),
				gitRepositoryDir.getAbsolutePath(), getGitRepositoryName());

		LocalGitBranch forwardLocalGitBranch =
			gitWorkingDirectory.getRebasedLocalGitBranch(
				forwardBranchName, getSenderBranchName(), getSenderRemoteURL(),
				getSenderSHA(), getUpstreamRemoteGitBranchName(),
				getUpstreamBranchSHA());

		RemoteGitBranch forwardRemoteGitBranch =
			gitWorkingDirectory.pushToRemoteGitRepository(
				true, forwardLocalGitBranch, forwardLocalGitBranch.getName(),
				GitUtil.getUserRemoteURL(
					getGitRepositoryName(), forwardSenderUsername));

		if (forwardRemoteGitBranch == null) {
			throw new RuntimeException("Unable to push branch to GitHub");
		}

		return gitWorkingDirectory.createPullRequest(
			commentBody, forwardBranchName, forwardReceiverUsername,
			forwardSenderUsername, getTitle());
	}

	public URL getBaseURL() {
		try {
			return new URL(
				JenkinsResultsParserUtil.combine(
					"https://github.com/", getReceiverUsername(), "/",
					getGitRepositoryName(), "/tree/",
					getUpstreamRemoteGitBranchName()));
		}
		catch (MalformedURLException malformedURLException) {
			throw new RuntimeException(malformedURLException);
		}
	}

	public String getBody() {
		return _jsonObject.optString("body");
	}

	public String getCIMergeSHA() {
		getFileNames();

		return _ciMergeSHA;
	}

	public String getCIMergeSubrepo() {
		for (String fileName : getFileNames()) {
			if (fileName.endsWith("/ci-merge")) {
				return fileName.replace("/ci-merge", "");
			}
		}

		throw new IllegalStateException("Unable to find ci-merge file");
	}

	public List getComments() {
		if (_comments != null) {
			return _comments;
		}

		_comments = new ArrayList<>();

		String gitHubApiUrl = JenkinsResultsParserUtil.getGitHubApiUrl(
			getGitHubRemoteGitRepositoryName(), getOwnerUsername(),
			"issues/" + getNumber() + "/comments?per_page=100&page=");

		for (int pageNumber = 1;
			 pageNumber <=
				 JenkinsResultsParserUtil.PAGES_GITHUB_API_PAGES_SIZE_MAX;
			 pageNumber++) {

			try {
				JSONArray commentJSONArray =
					JenkinsResultsParserUtil.toJSONArray(
						gitHubApiUrl + pageNumber, false);

				if (commentJSONArray.length() == 0) {
					break;
				}

				for (int i = 0; i < commentJSONArray.length(); i++) {
					_comments.add(
						new Comment(commentJSONArray.getJSONObject(i)));
				}

				if (commentJSONArray.length() < JenkinsResultsParserUtil.
						PER_PAGE_GITHUB_API_PAGES_SIZE_MAX) {

					break;
				}

				if (pageNumber ==
						JenkinsResultsParserUtil.
							PAGES_GITHUB_API_PAGES_SIZE_MAX) {

					throw new RuntimeException(
						JenkinsResultsParserUtil.combine(
							"Too many comments (>",
							String.valueOf(_gitHubRemoteGitCommits.size()),
							") found for ", "pull request ", getHtmlURL()));
				}
			}
			catch (IOException ioException) {
				_comments = null;

				throw new RuntimeException(
					"Unable to get pull request comments", ioException);
			}
		}

		Collections.sort(_comments);

		return _comments;
	}

	public String getCommonParentSHA() {
		if (_commonParentSHA == null) {
			_initCommits();
		}

		return _commonParentSHA;
	}

	public List getCompletedTestSuiteNames() {
		List testSuiteNames = new ArrayList<>();

		JSONArray statusesJSONArray = getSenderSHAStatusesJSONArray();

		for (int i = 0; i < statusesJSONArray.length(); i++) {
			JSONObject jsonObject = statusesJSONArray.getJSONObject(i);

			Matcher matcher = _liferayContextPattern.matcher(
				jsonObject.getString("context"));

			if (!matcher.find()) {
				continue;
			}

			String testSuiteName = matcher.group("testSuiteName");

			if (testSuiteNames.contains(testSuiteName)) {
				continue;
			}

			String state = jsonObject.getString("state");

			if (!Objects.equals(state, "failure") &&
				!Objects.equals(state, "success")) {

				continue;
			}

			testSuiteNames.add(testSuiteName);
		}

		return testSuiteNames;
	}

	public List getFileNames() {
		if (!_fileNames.isEmpty()) {
			return _fileNames;
		}

		_ciMergeSHA = "";

		String filesURL = JenkinsResultsParserUtil.combine(
			"https://api.github.com/repos/", getReceiverUsername(), "/",
			getGitHubRemoteGitRepositoryName(), "/pulls/", getNumber(),
			"/files");

		try {
			JSONArray filesJSONArray = JenkinsResultsParserUtil.toJSONArray(
				filesURL, false);

			for (int j = 0; j < filesJSONArray.length(); j++) {
				JSONObject fileJSONObject = filesJSONArray.getJSONObject(j);

				String fileName = fileJSONObject.getString("filename");

				_fileNames.add(fileName);

				if (fileName.endsWith("/ci-merge")) {
					String patch = fileJSONObject.getString("patch");

					Matcher matcher = _ciMergeSHAPattern.matcher(patch);

					if (matcher.find()) {
						String sha = matcher.group(1);

						if (!matcher.find()) {
							_ciMergeSHA = sha;
						}
					}
				}
			}

			return _fileNames;
		}
		catch (IOException ioException) {
			throw new RuntimeException(
				"Unable to get pull request file names", ioException);
		}
	}

	public List getGitHubRemoteCommits() {
		if (_gitHubRemoteGitCommits == null) {
			_initCommits();
		}

		return _gitHubRemoteGitCommits;
	}

	public GitHubRemoteGitCommit getGitHubRemoteGitCommit() {
		if (_gitHubRemoteGitCommits == null) {
			_initCommits();
		}

		return _gitHubRemoteGitCommits.get(_gitHubRemoteGitCommits.size() - 1);
	}

	public GitHubRemoteGitRepository getGitHubRemoteGitRepository() {
		if (_gitHubRemoteGitRepository == null) {
			_gitHubRemoteGitRepository =
				(GitHubRemoteGitRepository)
					GitRepositoryFactory.getRemoteGitRepository(
						"github.com", _gitHubRemoteGitRepositoryName,
						getOwnerUsername());
		}

		return _gitHubRemoteGitRepository;
	}

	public String getGitHubRemoteGitRepositoryName() {
		return _gitHubRemoteGitRepositoryName;
	}

	public String getGitRepositoryName() {
		return getGitHubRemoteGitRepositoryName();
	}

	public URL getHeadURL() {
		try {
			return new URL(
				JenkinsResultsParserUtil.combine(
					"https://github.com/", getSenderUsername(), "/",
					getGitRepositoryName(), "/tree/", getSenderBranchName()));
		}
		catch (MalformedURLException malformedURLException) {
			throw new RuntimeException(malformedURLException);
		}
	}

	public String getHtmlURL() {
		return _jsonObject.getString("html_url");
	}

	public Set getJIRAIssues() {
		if (_jiraIssues == null) {
			_initJIRAIssues();
		}

		return _jiraIssues;
	}

	public String getJSON() {
		return _jsonObject.toString(4);
	}

	public JSONObject getJSONObject() {
		return _jsonObject;
	}

	public List getLabels() {
		if (_labels == null) {
			_refreshJSONObject();

			JSONArray labelJSONArray = _jsonObject.getJSONArray("labels");

			_labels = new ArrayList<>(labelJSONArray.length());

			for (int i = 0; i < labelJSONArray.length(); i++) {
				JSONObject labelJSONObject = labelJSONArray.getJSONObject(i);

				_labels.add(
					new GitHubRemoteGitRepository.Label(
						labelJSONObject, getGitHubRemoteGitRepository()));
			}
		}

		return _labels;
	}

	public String getLocalSenderBranchName() {
		return JenkinsResultsParserUtil.combine(
			getSenderUsername(), "-", getNumber(), "-", getSenderBranchName());
	}

	public String getNumber() {
		return String.valueOf(_number);
	}

	public String getOwnerUsername() {
		return _ownerUsername;
	}

	public List getPassingTestSuiteNames() {
		List testSuiteNames = new ArrayList<>();

		JSONArray statusesJSONArray = getSenderSHAStatusesJSONArray();

		for (int i = 0; i < statusesJSONArray.length(); i++) {
			JSONObject jsonObject = statusesJSONArray.getJSONObject(i);

			Matcher matcher = _liferayContextPattern.matcher(
				jsonObject.getString("context"));

			if (!matcher.find()) {
				continue;
			}

			String testSuiteName = matcher.group("testSuiteName");

			if (testSuiteNames.contains(testSuiteName) ||
				!Objects.equals(jsonObject.getString("state"), "success")) {

				continue;
			}

			testSuiteNames.add(testSuiteName);
		}

		return testSuiteNames;
	}

	public String getReceiverUsername() {
		JSONObject baseJSONObject = _jsonObject.getJSONObject("base");

		JSONObject userJSONObject = baseJSONObject.getJSONObject("user");

		return userJSONObject.getString("login");
	}

	public String getSenderBranchName() {
		JSONObject headJSONObject = _jsonObject.getJSONObject("head");

		return headJSONObject.getString("ref");
	}

	public RemoteGitBranch getSenderRemoteGitBranch() {
		if (_senderRemoteGitBranch == null) {
			_senderRemoteGitBranch = GitUtil.getRemoteGitBranch(
				getSenderBranchName(), new File(""), getSenderRemoteURL());
		}

		return _senderRemoteGitBranch;
	}

	public String getSenderRemoteURL() {
		return JenkinsResultsParserUtil.combine(
			"[email protected]:", getSenderUsername(), "/",
			getGitHubRemoteGitRepositoryName());
	}

	public String getSenderSHA() {
		JSONObject headJSONObject = _jsonObject.getJSONObject("head");

		return headJSONObject.getString("sha");
	}

	public JSONArray getSenderSHAStatusesJSONArray() {
		JSONArray statusesJSONArray = null;

		try {
			statusesJSONArray = JenkinsResultsParserUtil.toJSONArray(
				_jsonObject.getString("statuses_url"));
		}
		catch (IOException ioException) {
			throw new RuntimeException(ioException);
		}

		return statusesJSONArray;
	}

	public JSONObject getSenderSHAStatusJSONObject() {
		JSONObject statusJSONObject = null;

		try {
			String statusURL = _jsonObject.getString("statuses_url");

			statusURL = statusURL.replace("statuses", "status");

			statusJSONObject = JenkinsResultsParserUtil.toJSONObject(statusURL);
		}
		catch (IOException ioException) {
			throw new RuntimeException(ioException);
		}

		return statusJSONObject;
	}

	public String getSenderUsername() {
		JSONObject headJSONObject = _jsonObject.getJSONObject("head");

		JSONObject userJSONObject = headJSONObject.getJSONObject("user");

		return userJSONObject.getString("login");
	}

	public String getState() {
		return _jsonObject.getString("state");
	}

	public List getStatusDescriptions() {
		GitHubRemoteGitCommit gitHubRemoteGitCommit =
			getGitHubRemoteGitCommit();

		return gitHubRemoteGitCommit.getStatusDescriptions();
	}

	public String getTitle() {
		return _jsonObject.getString("title");
	}

	public String getUpstreamBranchSHA() {
		RemoteGitBranch upstreamRemoteGitBranch = getUpstreamRemoteGitBranch();

		return upstreamRemoteGitBranch.getSHA();
	}

	public RemoteGitBranch getUpstreamRemoteGitBranch() {
		if (_liferayRemoteGitBranch == null) {
			String gitRepositoryName = getGitRepositoryName();

			_liferayRemoteGitBranch = GitUtil.getRemoteGitBranch(
				getUpstreamRemoteGitBranchName(), new File("."),
				JenkinsResultsParserUtil.combine(
					"[email protected]:",
					JenkinsResultsParserUtil.getUpstreamUserName(
						gitRepositoryName, getUpstreamRemoteGitBranchName()),
					"/", gitRepositoryName, ".git"));
		}

		return _liferayRemoteGitBranch;
	}

	public String getUpstreamRemoteGitBranchName() {
		JSONObject baseJSONObject = _jsonObject.getJSONObject("base");

		return baseJSONObject.getString("ref");
	}

	public String getURL() {
		return getURL(
			getReceiverUsername(), getGitRepositoryName(), getNumber());
	}

	public boolean hasLabel(String labelName) {
		for (GitHubRemoteGitRepository.Label label : getLabels()) {
			if (labelName.equals(label.getName())) {
				return true;
			}
		}

		return false;
	}

	public boolean hasRequiredCompletedTestSuites() {
		return hasRequiredCompletedTestSuites(false);
	}

	public boolean hasRequiredCompletedTestSuites(boolean force) {
		Properties buildProperties = null;

		try {
			buildProperties = JenkinsResultsParserUtil.getBuildProperties();
		}
		catch (IOException ioException) {
			throw new RuntimeException(ioException);
		}

		String propertyName = JenkinsResultsParserUtil.combine(
			"ci.forward", force ? ".force" : "", ".required.completed.suites");

		String requiredCompletedTestSuiteNames =
			JenkinsResultsParserUtil.getProperty(
				buildProperties, propertyName, getGitRepositoryName());

		if (JenkinsResultsParserUtil.isNullOrEmpty(
				requiredCompletedTestSuiteNames)) {

			return true;
		}

		List completedTestSuiteNames = getCompletedTestSuiteNames();

		for (String requiredCompletedSuiteName :
				requiredCompletedTestSuiteNames.split("\\s*,\\s*")) {

			if (!completedTestSuiteNames.contains(requiredCompletedSuiteName)) {
				return false;
			}
		}

		return true;
	}

	public boolean hasRequiredPassingTestSuites() {
		return hasRequiredPassingTestSuites(false);
	}

	public boolean hasRequiredPassingTestSuites(boolean force) {
		Properties buildProperties = null;

		try {
			buildProperties = JenkinsResultsParserUtil.getBuildProperties();
		}
		catch (IOException ioException) {
			throw new RuntimeException(ioException);
		}

		String propertyName = JenkinsResultsParserUtil.combine(
			"ci.forward", force ? ".force" : "", ".required.passing.suites");

		String requiredPassingTestSuiteNames =
			JenkinsResultsParserUtil.getProperty(
				buildProperties, propertyName, getGitRepositoryName());

		if (JenkinsResultsParserUtil.isNullOrEmpty(
				requiredPassingTestSuiteNames)) {

			return true;
		}

		List passingTestSuiteNames = getPassingTestSuiteNames();

		for (String requiredPassingTestSuiteName :
				requiredPassingTestSuiteNames.split("\\s*,\\s*")) {

			if (!passingTestSuiteNames.contains(requiredPassingTestSuiteName)) {
				return false;
			}
		}

		return true;
	}

	public boolean isAutoCloseCommentAvailable() {
		if (_autoCloseCommentAvailable != null) {
			return _autoCloseCommentAvailable;
		}

		List comments = getComments();

		for (Comment comment : comments) {
			String commentBody = comment.getBody();

			if (commentBody.contains("auto-close=\"false\"")) {
				_autoCloseCommentAvailable = true;

				return _autoCloseCommentAvailable;
			}
		}

		_autoCloseCommentAvailable = false;

		return _autoCloseCommentAvailable;
	}

	public boolean isMergeSubrepoRequest() {
		for (String filename : getFileNames()) {
			if (filename.endsWith("/ci-merge")) {
				return true;
			}
		}

		return false;
	}

	public boolean isValidCIMergeFile() {
		List fileNames = getFileNames();

		if ((fileNames.size() == 1) && isMergeSubrepoRequest()) {
			return true;
		}

		return false;
	}

	public void lock() {
		try {
			JenkinsResultsParserUtil.toString(
				getIssueURL() + "/lock", false, HttpRequestMethod.PUT);
		}
		catch (IOException ioException) {
			throw new RuntimeException(
				"Unable to lock pull request " + getHtmlURL(), ioException);
		}
	}

	public void refresh() {
		_comments = null;
		_commonParentSHA = null;
		_gitHubRemoteGitCommits = null;
		_labels = null;

		getLabels();
	}

	public void removeComment(Comment comment) {
		removeComment(comment.getId());
	}

	public void removeComment(String id) {
		String editCommentURL = _jsonObject.getString("issue_url");

		editCommentURL = editCommentURL.replaceFirst("issues/\\d+", "issues");

		try {
			JenkinsResultsParserUtil.toString(
				JenkinsResultsParserUtil.combine(
					editCommentURL, "/comments/", id),
				false, HttpRequestMethod.DELETE);
		}
		catch (IOException ioException) {
			throw new RuntimeException(
				"Unable to delete comment in GitHub pull request " + getURL(),
				ioException);
		}
	}

	public void removeLabel(String labelName) {
		if (!hasLabel(labelName)) {
			return;
		}

		String path = JenkinsResultsParserUtil.combine(
			"issues/", getNumber(), "/labels/",
			JenkinsResultsParserUtil.fixURL(labelName));

		String gitHubApiUrl = JenkinsResultsParserUtil.getGitHubApiUrl(
			getGitHubRemoteGitRepositoryName(), getOwnerUsername(), path);

		try {
			JenkinsResultsParserUtil.toString(
				gitHubApiUrl, false, HttpRequestMethod.DELETE);

			_labels = null;
		}
		catch (IOException ioException) {
			System.out.println("Unable to remove label " + labelName);

			ioException.printStackTrace();
		}
	}

	public void resetAutoCloseCommentAvailable() {
		_autoCloseCommentAvailable = null;
	}

	public void setTestSuiteStatus(
		String testSuiteName, TestSuiteStatus testSuiteStatus) {

		setTestSuiteStatus(testSuiteName, testSuiteStatus, null);
	}

	public void setTestSuiteStatus(
		String testSuiteName, TestSuiteStatus testSuiteStatus,
		String targetURL) {

		setTestSuiteStatus(testSuiteName, testSuiteStatus, targetURL, null);
	}

	public void setTestSuiteStatus(
		String testSuiteName, TestSuiteStatus testSuiteStatus, String targetURL,
		String senderSHA) {

		StringBuilder sb = new StringBuilder();

		sb.append("ci:test");

		if (!testSuiteName.equals(_NAME_TEST_SUITE_DEFAULT)) {
			sb.append(":");
			sb.append(testSuiteName);
		}

		sb.append(" ");

		String testSuiteLabelPrefix = sb.toString();

		List oldLabelNames = new ArrayList<>();

		for (GitHubRemoteGitRepository.Label label : getLabels()) {
			String name = label.getName();

			if (name.startsWith(testSuiteLabelPrefix)) {
				oldLabelNames.add(label.getName());
			}
		}

		for (String oldLabelName : oldLabelNames) {
			removeLabel(oldLabelName);
		}

		sb.append(" - ");
		sb.append(StringUtils.lowerCase(testSuiteStatus.toString()));

		GitHubRemoteGitRepository gitHubRemoteGitRepository =
			getGitHubRemoteGitRepository();

		GitHubRemoteGitRepository.Label testSuiteLabel =
			gitHubRemoteGitRepository.getLabel(sb.toString());

		if ((testSuiteLabel == null) &&
			gitHubRemoteGitRepository.addLabel(
				testSuiteStatus.getColor(), "", sb.toString())) {

			testSuiteLabel = gitHubRemoteGitRepository.getLabel(sb.toString());
		}

		addLabel(testSuiteLabel);

		if ((targetURL == null) ||
			(testSuiteStatus == TestSuiteStatus.MISSING)) {

			return;
		}

		GitHubRemoteGitCommit gitHubRemoteGitCommit =
			getGitHubRemoteGitCommit();

		if ((senderSHA != null) && senderSHA.matches("[0-9a-f]{7,40}")) {
			gitHubRemoteGitCommit = GitCommitFactory.newGitHubRemoteGitCommit(
				getOwnerUsername(), getGitHubRemoteGitRepositoryName(),
				senderSHA);
		}

		GitHubRemoteGitCommit.Status status =
			GitHubRemoteGitCommit.Status.valueOf(testSuiteStatus.toString());

		String context = _NAME_TEST_SUITE_DEFAULT;

		if (!testSuiteName.equals(_NAME_TEST_SUITE_DEFAULT)) {
			context = "liferay/ci:test:" + testSuiteName;
		}

		sb = new StringBuilder();

		sb.append("\"ci:test");

		if (!testSuiteName.equals(_NAME_TEST_SUITE_DEFAULT)) {
			sb.append(":");
			sb.append(testSuiteName);
		}

		sb.append("\"");

		if ((testSuiteStatus == TestSuiteStatus.ERROR) ||
			(testSuiteStatus == TestSuiteStatus.FAILURE)) {

			sb.append(" has FAILED.");
		}
		else if (testSuiteStatus == TestSuiteStatus.PENDING) {
			sb.append(" is running.");
		}
		else if (testSuiteStatus == TestSuiteStatus.SUCCESS) {
			sb.append(" has PASSED.");
		}

		gitHubRemoteGitCommit.setStatus(
			status, context, sb.toString(), targetURL);
	}

	public Comment updateComment(Comment comment) {
		return updateComment(comment.getBody(), comment.getId());
	}

	public Comment updateComment(String body, String id) {
		JSONObject jsonObject = new JSONObject();

		body = body.replaceAll("(\\>)\\s+(\\<)", "$1$2");
		body = body.replace(""", "\\"");

		jsonObject.put("body", body);

		try {
			String editCommentURL = _jsonObject.getString("issue_url");

			editCommentURL = editCommentURL.replaceFirst(
				"issues/\\d+", "issues");

			return new Comment(
				JenkinsResultsParserUtil.toJSONObject(
					JenkinsResultsParserUtil.combine(
						editCommentURL, "/comments/", id),
					false, HttpRequestMethod.PATCH, jsonObject.toString()));
		}
		catch (IOException ioException) {
			throw new RuntimeException(
				"Unable to update comment in GitHub pull request " + getURL(),
				ioException);
		}
	}

	public static class Comment implements Comparable {

		public Comment(JSONObject commentJSONObject) {
			_commentJSONObject = commentJSONObject;
		}

		@Override
		public int compareTo(Comment comment) {
			Date createdDate = getCreatedDate();

			return createdDate.compareTo(comment.getCreatedDate());
		}

		public String getBody() {
			return _commentJSONObject.getString("body");
		}

		public Date getCreatedDate() {
			try {
				return _UtcIso8601SimpleDateFormat.parse(
					_commentJSONObject.getString("created_at"));
			}
			catch (ParseException parseException) {
				throw new RuntimeException(
					"Unable to parse created date " +
						_commentJSONObject.getString("created_at"),
					parseException);
			}
		}

		public String getId() {
			return String.valueOf(_commentJSONObject.getLong("id"));
		}

		public Date getModifiedDate() {
			try {
				return _UtcIso8601SimpleDateFormat.parse(
					_commentJSONObject.getString("modified_at"));
			}
			catch (ParseException parseException) {
				throw new RuntimeException(
					"Unable to parse modified date " +
						_commentJSONObject.getString("modified_at"),
					parseException);
			}
		}

		public URL getURL() {
			try {
				return new URL(_commentJSONObject.getString("html_url"));
			}
			catch (MalformedURLException malformedURLException) {
				throw new RuntimeException(malformedURLException);
			}
		}

		public String getUserLogin() {
			JSONObject userJSONObject = _commentJSONObject.getJSONObject(
				"user");

			return userJSONObject.getString("login");
		}

		private static final SimpleDateFormat _UtcIso8601SimpleDateFormat;

		static {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
				"yyyy-MM-dd'T'HH:mm:ss'Z'");

			simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

			_UtcIso8601SimpleDateFormat = simpleDateFormat;
		}

		private final JSONObject _commentJSONObject;

	}

	public static enum TestSuiteStatus {

		ERROR("fccdcc"), FAILURE("fccdcc"), MISSING("eeeeee"),
		PENDING("fff4c9"), SUCCESS("c7e8cb");

		public String getColor() {
			return _color;
		}

		private TestSuiteStatus(String color) {
			_color = color;
		}

		private final String _color;

	}

	protected PullRequest(JSONObject jsonObject) {
		JSONObject baseJSONObject = jsonObject.getJSONObject("base");

		JSONObject repoJSONObject = baseJSONObject.getJSONObject("repo");

		_gitHubRemoteGitRepositoryName = repoJSONObject.getString("name");

		_number = jsonObject.getInt("number");

		JSONObject ownerJSONObject = repoJSONObject.getJSONObject("owner");

		_ownerUsername = ownerJSONObject.getString("login");

		_jsonObject = jsonObject;
	}

	protected PullRequest(String gitHubURL) {
		Matcher matcher = _gitHubPullRequestURLPattern.matcher(gitHubURL);

		if (!matcher.find()) {
			throw new RuntimeException("Invalid GitHub URL " + gitHubURL);
		}

		_gitHubRemoteGitRepositoryName = matcher.group(
			"gitHubRemoteGitRepositoryName");
		_number = Integer.parseInt(matcher.group("number"));
		_ownerUsername = matcher.group("owner");

		refresh();
	}

	protected String getGitHubApiUrl() {
		return JenkinsResultsParserUtil.getGitHubApiUrl(
			_gitHubRemoteGitRepositoryName, _ownerUsername, "pulls/" + _number);
	}

	protected String getIssueURL() {
		return _jsonObject.getString("issue_url");
	}

	protected void updateGithub() {
		JSONObject jsonObject = new JSONObject();

		List labelNames = new ArrayList<>();

		for (GitHubRemoteGitRepository.Label label : getLabels()) {
			labelNames.add(label.getName());
		}

		jsonObject.put("labels", labelNames);

		try {
			JenkinsResultsParserUtil.toJSONObject(
				getIssueURL(), jsonObject.toString());
		}
		catch (IOException ioException) {
			throw new RuntimeException(ioException);
		}
	}

	private void _initCommits() {
		String commitsURL = _jsonObject.getString("commits_url");

		_gitHubRemoteGitCommits = new ArrayList<>();

		try {
			for (int pageNumber = 1;
				 pageNumber <=
					 JenkinsResultsParserUtil.PAGES_GITHUB_API_PAGES_SIZE_MAX;
				 pageNumber++) {

				JSONArray commitsJSONArray =
					JenkinsResultsParserUtil.toJSONArray(
						JenkinsResultsParserUtil.combine(
							commitsURL, "?per_page=100&page=",
							String.valueOf(pageNumber)));

				if (commitsJSONArray.length() == 0) {
					break;
				}

				for (int i = 0; i < commitsJSONArray.length(); i++) {
					JSONObject commitJSONObject =
						commitsJSONArray.getJSONObject(i);

					_gitHubRemoteGitCommits.add(
						GitCommitFactory.newGitHubRemoteGitCommit(
							getOwnerUsername(), getGitRepositoryName(),
							commitJSONObject.getString("sha"),
							commitJSONObject));
				}

				if (pageNumber == 1) {
					JSONObject firstCommitJSONObject =
						commitsJSONArray.getJSONObject(0);

					JSONArray parentsJSONArray =
						firstCommitJSONObject.getJSONArray("parents");

					JSONObject firstParentJSONObject =
						parentsJSONArray.getJSONObject(0);

					_commonParentSHA = firstParentJSONObject.getString("sha");
				}

				if (commitsJSONArray.length() < JenkinsResultsParserUtil.
						PER_PAGE_GITHUB_API_PAGES_SIZE_MAX) {

					break;
				}

				if (pageNumber ==
						JenkinsResultsParserUtil.
							PAGES_GITHUB_API_PAGES_SIZE_MAX) {

					throw new RuntimeException(
						JenkinsResultsParserUtil.combine(
							"Too many GitHub remote commits (>",
							String.valueOf(_gitHubRemoteGitCommits.size()),
							") found for ", "pull request ", getHtmlURL()));
				}
			}
		}
		catch (IOException ioException) {
			throw new RuntimeException(
				"Unable to get GitHub remote commits for pull request " +
					getHtmlURL(),
				ioException);
		}
	}

	private void _initJIRAIssues() {
		getGitHubRemoteCommits();

		_jiraIssues = new HashSet<>();

		for (GitHubRemoteGitCommit gitHubRemoteGitCommit :
				_gitHubRemoteGitCommits) {

			Issue issue = gitHubRemoteGitCommit.getJIRAIssue();

			if (issue != null) {
				_jiraIssues.add(issue);
			}
		}
	}

	private void _refreshJSONObject() {
		try {
			_jsonObject = JenkinsResultsParserUtil.toJSONObject(
				getGitHubApiUrl(), false);
		}
		catch (IOException ioException) {
			throw new RuntimeException(ioException);
		}
	}

	private static final String _NAME_TEST_SUITE_DEFAULT = "default";

	private static final Pattern _ciMergeSHAPattern = Pattern.compile(
		"\\+([0-9a-f]{40})");
	private static final Pattern _gitHubPullRequestURLPattern = Pattern.compile(
		JenkinsResultsParserUtil.combine(
			"https://github.com/(?[^/]+)/",
			"(?[^/]+)/pull/(?\\d+)"));
	private static final Pattern _liferayContextPattern = Pattern.compile(
		"liferay/ci:test:(?[^:]+)");

	private Boolean _autoCloseCommentAvailable;
	private String _ciMergeSHA = "";
	private List _comments;
	private String _commonParentSHA;
	private final List _fileNames = new ArrayList<>();
	private List _gitHubRemoteGitCommits;
	private GitHubRemoteGitRepository _gitHubRemoteGitRepository;
	private final String _gitHubRemoteGitRepositoryName;
	private Set _jiraIssues;
	private JSONObject _jsonObject;
	private List _labels;
	private RemoteGitBranch _liferayRemoteGitBranch;
	private final Integer _number;
	private final String _ownerUsername;
	private RemoteGitBranch _senderRemoteGitBranch;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy