com.liferay.jenkins.results.parser.MergeCentralGitSubrepositoryUtil 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 java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
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 MergeCentralGitSubrepositoryUtil {
public static void createGitSubrepositoryMergePullRequests(
String centralWorkingDirectory, String centralUpstreamBranchName,
String receiverUserName, String senderUserName,
String topLevelBranchName)
throws IOException {
GitWorkingDirectory centralGitWorkingDirectory =
GitWorkingDirectoryFactory.newGitWorkingDirectory(
centralUpstreamBranchName, centralWorkingDirectory);
File modulesDir = new File(
centralGitWorkingDirectory.getWorkingDirectory(), "modules");
if (!modulesDir.exists()) {
return;
}
List failedGitrepoPaths = new ArrayList<>();
List subrepoMergeBlacklist =
JenkinsResultsParserUtil.getBuildPropertyAsList(
false, "subrepo.merge.blacklist");
List gitrepoFiles = JenkinsResultsParserUtil.findFiles(
modulesDir, ".gitrepo");
for (File gitrepoFile : gitrepoFiles) {
try {
Properties gitrepoProperties = _getPropertiesFromGitrepoFile(
gitrepoFile);
String remote = gitrepoProperties.getProperty("remote");
Matcher matcher = _githubRemotePattern.matcher(remote);
if (matcher.find() && !subrepoMergeBlacklist.isEmpty() &&
subrepoMergeBlacklist.contains(
matcher.group("gitSubrepositoryName"))) {
continue;
}
CentralGitSubrepository centralGitSubrepository =
new CentralGitSubrepository(
gitrepoFile, centralUpstreamBranchName);
if (!centralGitSubrepository.isAutoPullEnabled()) {
continue;
}
String mergeBranchName = _getMergeBranchName(
centralUpstreamBranchName,
centralGitSubrepository.getGitSubrepositoryName(),
centralGitSubrepository.
getGitSubrepositoryUpstreamCommit());
if (centralGitSubrepository.isCentralPullRequestCandidate()) {
GitRemote upstreamGitRemote =
centralGitWorkingDirectory.getGitRemote("upstream");
if (!centralGitWorkingDirectory.remoteGitBranchExists(
mergeBranchName, upstreamGitRemote)) {
LocalGitBranch topLevelLocalGitBranch =
centralGitWorkingDirectory.getLocalGitBranch(
topLevelBranchName, true);
LocalGitBranch mergeLocalGitBranch =
_createMergeLocalGitBranch(
centralGitWorkingDirectory, mergeBranchName,
topLevelLocalGitBranch);
_commitCiMergeFile(
centralGitWorkingDirectory, centralGitSubrepository,
gitrepoFile);
_pushMergeLocalGitBranchToRemote(
centralGitWorkingDirectory, mergeLocalGitBranch,
senderUserName);
}
_createMergePullRequest(
centralGitWorkingDirectory, centralGitSubrepository,
mergeBranchName, receiverUserName, senderUserName);
}
_deleteStalePulls(
centralGitWorkingDirectory, centralGitSubrepository,
mergeBranchName, receiverUserName);
_deleteStaleBranches(
centralGitWorkingDirectory, centralGitSubrepository,
mergeBranchName);
}
catch (Exception exception) {
failedGitrepoPaths.add(gitrepoFile.getParent());
exception.printStackTrace();
}
}
if (!failedGitrepoPaths.isEmpty()) {
String message = JenkinsResultsParserUtil.combine(
"Unable to create a pull to merge these subrepositories:\n",
StringUtils.join(failedGitrepoPaths, "\n"));
Properties buildProperties =
JenkinsResultsParserUtil.getBuildProperties();
NotificationUtil.sendEmail(
message, "jenkins", "Merge Central Git Subrepository",
buildProperties.getProperty(
"email.list[merge-central-subrepository]"));
throw new RuntimeException(message);
}
}
private static void _commitCiMergeFile(
GitWorkingDirectory centralGitWorkingDirectory,
CentralGitSubrepository centralGitSubrepository, File gitrepoFile)
throws IOException {
String gitSubrepositoryUpstreamCommit =
centralGitSubrepository.getGitSubrepositoryUpstreamCommit();
String ciMergeFilePath = _getCiMergeFilePath(
centralGitWorkingDirectory, gitrepoFile);
JenkinsResultsParserUtil.write(
new File(
centralGitWorkingDirectory.getWorkingDirectory(),
ciMergeFilePath),
gitSubrepositoryUpstreamCommit);
centralGitWorkingDirectory.stageFileInCurrentLocalGitBranch(
ciMergeFilePath);
centralGitWorkingDirectory.commitStagedFilesToCurrentBranch(
"Create " + ciMergeFilePath + ".");
}
private static LocalGitBranch _createMergeLocalGitBranch(
GitWorkingDirectory centralGitWorkingDirectory, String mergeBranchName,
LocalGitBranch topLevelLocalGitBranch) {
centralGitWorkingDirectory.reset("--hard");
centralGitWorkingDirectory.checkoutLocalGitBranch(
topLevelLocalGitBranch);
LocalGitBranch mergeLocalGitBranch =
centralGitWorkingDirectory.getLocalGitBranch(mergeBranchName);
if (mergeLocalGitBranch != null) {
centralGitWorkingDirectory.deleteLocalGitBranch(
mergeLocalGitBranch);
}
mergeLocalGitBranch = centralGitWorkingDirectory.createLocalGitBranch(
mergeBranchName);
centralGitWorkingDirectory.checkoutLocalGitBranch(mergeLocalGitBranch);
return mergeLocalGitBranch;
}
private static void _createMergePullRequest(
GitWorkingDirectory centralGitWorkingDirectory,
CentralGitSubrepository centralGitSubrepository,
String mergeBranchName, String receiverUserName,
String senderUserName)
throws IOException {
String gitSubrepositoryName =
centralGitSubrepository.getGitSubrepositoryName();
String gitSubrepositoryUpstreamCommit =
centralGitSubrepository.getGitSubrepositoryUpstreamCommit();
String url = JenkinsResultsParserUtil.getGitHubApiUrl(
gitSubrepositoryName, senderUserName,
"statuses/" + gitSubrepositoryUpstreamCommit);
JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(
"context", "liferay/central-pull-request"
).put(
"description", "Tests are queued on Jenkins."
).put(
"state", "pending"
);
StringBuilder sb = new StringBuilder();
sb.append("Merging the following commit: [");
sb.append(gitSubrepositoryUpstreamCommit);
sb.append("](https://github.com/");
sb.append(senderUserName);
sb.append("/");
sb.append(gitSubrepositoryName);
sb.append("/commit/");
sb.append(gitSubrepositoryUpstreamCommit);
sb.append(")");
String title = gitSubrepositoryName + " - Central Merge Pull Request";
String pullRequestURL = centralGitWorkingDirectory.createPullRequest(
sb.toString(), mergeBranchName, receiverUserName, senderUserName,
title);
requestJSONObject.put("target_url", pullRequestURL);
JenkinsResultsParserUtil.toJSONObject(
url, requestJSONObject.toString());
}
private static void _deleteStaleBranches(
GitWorkingDirectory centralGitWorkingDirectory,
CentralGitSubrepository centralGitSubrepository,
String mergeBranchName)
throws IOException {
GitRemote upstreamGitRemote = centralGitWorkingDirectory.getGitRemote(
"upstream");
if (_upstreamRemoteGitBranchNames == null) {
_upstreamRemoteGitBranchNames =
centralGitWorkingDirectory.getRemoteGitBranchNames(
upstreamGitRemote);
}
String mergeBranchNamePrefix = mergeBranchName.substring(
0, mergeBranchName.lastIndexOf("-"));
for (String upstreamRemoteGitBranchName :
_upstreamRemoteGitBranchNames) {
if ((upstreamRemoteGitBranchName.equals(mergeBranchName) &&
!centralGitSubrepository.
isGitSubrepositoryUpstreamCommitMerged()) ||
!upstreamRemoteGitBranchName.startsWith(
mergeBranchNamePrefix)) {
continue;
}
centralGitWorkingDirectory.deleteRemoteGitBranch(
upstreamRemoteGitBranchName, upstreamGitRemote);
}
}
private static void _deleteStalePulls(
GitWorkingDirectory centralGitWorkingDirectory,
CentralGitSubrepository centralGitSubrepository,
String mergeBranchName, String receiverUserName)
throws IOException {
if (_pullsJSONArray == null) {
_pullsJSONArray = new JSONArray();
int page = 1;
while (page < 10) {
String url = JenkinsResultsParserUtil.getGitHubApiUrl(
centralGitWorkingDirectory.getGitRepositoryName(),
receiverUserName, "pulls?page=" + String.valueOf(page));
JSONArray jsonArray = JenkinsResultsParserUtil.toJSONArray(url);
if ((jsonArray != null) && (jsonArray.length() > 0)) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
JSONObject userJSONObject = jsonObject.getJSONObject(
"user");
String login = userJSONObject.getString("login");
if (login.equals("liferay-continuous-integration")) {
_pullsJSONArray.put(jsonObject);
}
}
}
else {
break;
}
page++;
}
}
String mergeBranchNamePrefix = mergeBranchName.substring(
0, mergeBranchName.lastIndexOf("-"));
for (int i = 0; i < _pullsJSONArray.length(); i++) {
JSONObject jsonObject = _pullsJSONArray.getJSONObject(i);
JSONObject headJSONObject = jsonObject.getJSONObject("head");
String refName = headJSONObject.getString("ref");
if ((refName.equals(mergeBranchName) &&
!centralGitSubrepository.
isGitSubrepositoryUpstreamCommitMerged()) ||
!refName.startsWith(mergeBranchNamePrefix)) {
continue;
}
System.out.println(
"Closing pull request " + jsonObject.getString("html_url"));
JSONObject requestJSONObject = new JSONObject();
requestJSONObject.put(
"body", "This stale merge pull request has been closed.");
JenkinsResultsParserUtil.toJSONObject(
jsonObject.getString("comments_url"),
requestJSONObject.toString());
requestJSONObject = new JSONObject();
requestJSONObject.put("state", "closed");
JenkinsResultsParserUtil.toJSONObject(
jsonObject.getString("url"), requestJSONObject.toString());
}
}
private static String _getCiMergeFilePath(
GitWorkingDirectory centralGitWorkingDirectory, File gitrepoFile)
throws IOException {
File centralWorkingDirectory =
centralGitWorkingDirectory.getWorkingDirectory();
String ciMergeFilePath = JenkinsResultsParserUtil.getCanonicalPath(
gitrepoFile);
ciMergeFilePath = ciMergeFilePath.replace(".gitrepo", "ci-merge");
return ciMergeFilePath.replace(
JenkinsResultsParserUtil.combine(
JenkinsResultsParserUtil.getCanonicalPath(
centralWorkingDirectory),
File.separator),
"");
}
private static String _getMergeBranchName(
String centralUpstreamBranchName, String gitSubrepositoryName,
String gitSubrepositoryUpstreamCommit) {
return JenkinsResultsParserUtil.combine(
"ci-merge-", gitSubrepositoryName, "-", centralUpstreamBranchName,
"-", gitSubrepositoryUpstreamCommit);
}
private static Properties _getPropertiesFromGitrepoFile(File gitrepoFile)
throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream(gitrepoFile));
return properties;
}
private static void _pushMergeLocalGitBranchToRemote(
GitWorkingDirectory centralGitWorkingDirectory,
LocalGitBranch mergeLocalGitBranch, String senderUserName) {
String centralGitRepositoryName =
centralGitWorkingDirectory.getGitRepositoryName();
String originRemoteURL = JenkinsResultsParserUtil.combine(
"[email protected]:", senderUserName, "/", centralGitRepositoryName,
".git");
GitRemote originGitRemote = centralGitWorkingDirectory.addGitRemote(
true, "tempRemote", originRemoteURL);
try {
centralGitWorkingDirectory.pushToRemoteGitRepository(
false, mergeLocalGitBranch, mergeLocalGitBranch.getName(),
originGitRemote);
}
finally {
centralGitWorkingDirectory.removeGitRemote(originGitRemote);
}
}
private static final Pattern _githubRemotePattern = Pattern.compile(
"[email protected]:[-\\w]+\\/(?[-\\w]+)\\.git");
private static JSONArray _pullsJSONArray;
private static List _upstreamRemoteGitBranchNames;
}