Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved code readbility for hosting checks #4023

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import com.atlassian.jira.rest.client.api.domain.Component;
import com.atlassian.jira.rest.client.api.domain.input.ComponentInput;
import io.atlassian.util.concurrent.Promise;
import io.jenkins.infra.repository_permissions_updater.hosting.HostingRequest.IssueTracker;
import io.jenkins.infra.repository_permissions_updater.hosting.model.HostingRequest;
import io.jenkins.infra.repository_permissions_updater.hosting.model.HostingRequest.IssueTracker;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
Expand All @@ -19,6 +20,8 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import io.jenkins.infra.repository_permissions_updater.hosting.verify.MavenVerifierConsumer;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.kohsuke.github.GHContent;
Expand Down Expand Up @@ -47,6 +50,7 @@
public class Hoster {

private static final Logger LOGGER = LoggerFactory.getLogger(Hoster.class);
private static final Pattern GITHUB_HOST_PATTERN = Pattern.compile("(?:https://github\\.com/)?(\\S+)/(\\S+)", CASE_INSENSITIVE);

public static void main(String[] args) {
new Hoster().run(Integer.parseInt(args[0]));
Expand All @@ -59,20 +63,20 @@ private void run(int issueID) {
try {
final HostingRequest hostingRequest = HostingRequestParser.retrieveAndParse(issueID);

String defaultAssignee = hostingRequest.getJenkinsProjectUsers().getFirst();
String forkFrom = hostingRequest.getRepositoryUrl();
List<String> users = hostingRequest.getGithubUsers();
IssueTracker issueTrackerChoice = hostingRequest.getIssueTracker();
String defaultAssignee = hostingRequest.jenkinsProjectUsers().getFirst();
String forkFrom = hostingRequest.repositoryUrl();
List<String> users = hostingRequest.githubUsers();
IssueTracker issueTrackerChoice = hostingRequest.issueTracker();

String forkTo = hostingRequest.getNewRepoName();
String forkTo = hostingRequest.newRepoName();

if (StringUtils.isBlank(forkFrom) || StringUtils.isBlank(forkTo) || users.isEmpty()) {
LOGGER.info("Could not retrieve information (or information does not exist) from the Hosting request");
return;
}

// Parse forkFrom in order to determine original repo owner and repo name
Matcher m = Pattern.compile("(?:https://github\\.com/)?(\\S+)/(\\S+)", CASE_INSENSITIVE).matcher(forkFrom);
Matcher m = GITHUB_HOST_PATTERN.matcher(forkFrom);
if (m.matches()) {
if (!forkGitHub(m.group(1), m.group(2), forkTo, users, issueTrackerChoice == IssueTracker.GITHUB)) {
LOGGER.error("Hosting request failed to fork repository on Github");
Expand Down Expand Up @@ -103,7 +107,7 @@ private void run(int issueID) {
componentId = "";
}

String prUrl = createUploadPermissionPR(issueID, forkTo, users, hostingRequest.getJenkinsProjectUsers(), issueTrackerChoice == IssueTracker.GITHUB, componentId);
String prUrl = createUploadPermissionPR(issueID, forkTo, users, hostingRequest.jenkinsProjectUsers(), issueTrackerChoice == IssueTracker.GITHUB, componentId);
if (StringUtils.isBlank(prUrl)) {
LOGGER.error("Could not create upload permission pull request");
}
Expand Down Expand Up @@ -393,8 +397,8 @@ private static String getArtifactPath(GitHub github, String forkTo) throws IOExc
if (file != null && file.isFile()) {
String contents = IOUtils.toString(file.read(), StandardCharsets.UTF_8);
if (file.isFile()) {
artifactId = MavenVerifier.getArtifactId(contents);
groupId = MavenVerifier.getGroupId(contents);
artifactId = MavenVerifierConsumer.getArtifactId(contents);
groupId = MavenVerifierConsumer.getGroupId(contents);
}
}
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import io.jenkins.infra.repository_permissions_updater.hosting.condition.PomFileExistsCondition;
import io.jenkins.infra.repository_permissions_updater.hosting.model.HostingRequest;
import io.jenkins.infra.repository_permissions_updater.hosting.model.VerificationMessage;
import io.jenkins.infra.repository_permissions_updater.hosting.model.Version;
import io.jenkins.infra.repository_permissions_updater.hosting.verify.*;
import org.apache.commons.lang3.StringUtils;
import org.javatuples.Triplet;
import org.kohsuke.github.GHContent;
Expand All @@ -25,10 +32,16 @@ public class HostingChecker {

private static final Logger LOGGER = LoggerFactory.getLogger(HostingChecker.class);

public static final String INVALID_FORK_FROM = "Repository URL '%s' is not a valid GitHub repository (check that you do not have .git at the end, GitHub API doesn't support this).";

public static final Version LOWEST_JENKINS_VERSION = new Version(2, 440, 3);

private static final boolean DEBUG_HOSTING = Boolean.getBoolean("debugHosting");
public static final String INITIAL_HOSTING_REQUEST_FEEDBACK = """
It appears you have some issues with your hosting request. Please see the list below and \
correct all issues marked Required. Your hosting request will not be \
approved until these issues are corrected. Issues marked with Warning \
or Info are just recommendations and will not stall the hosting process.
""";

public static void main(String[] args) throws IOException {
new HostingChecker().checkRequest(Integer.parseInt(args[0]));
}
Expand All @@ -37,26 +50,24 @@ public void checkRequest(int issueID) throws IOException {
boolean hasBuildSystem = false;
HashSet<VerificationMessage> hostingIssues = new HashSet<>();

boolean debug = System.getProperty("debugHosting", "false").equalsIgnoreCase("true");

ArrayList<Triplet<String, Verifier, ConditionChecker>> verifications = new ArrayList<>();
verifications.add(Triplet.with("Jira", new HostingFieldVerifier(), null));
verifications.add(Triplet.with("GitHub", new GitHubVerifier(), null));
verifications.add(Triplet.with("Maven", new MavenVerifier(), new FileExistsConditionChecker("pom.xml")));
verifications.add(Triplet.with("JenkinsProjectUsers", new JenkinsProjectUserVerifier(), null));
ArrayList<Triplet<String, BiConsumer<HostingRequest, HashSet<VerificationMessage>>, Predicate<HostingRequest>>> verifications = new ArrayList<>();
verifications.add(Triplet.with("Jira", new HostingFieldVerifierConsumer(), null));
verifications.add(Triplet.with("GitHub", new GitHubVerifierConsumer(), null));
verifications.add(Triplet.with("Maven", new MavenVerifierConsumer(), new PomFileExistsCondition()));
verifications.add(Triplet.with("JenkinsProjectUsers", new JenkinsProjectUserVerifierConsumer(), null));

final HostingRequest hostingRequest = HostingRequestParser.retrieveAndParse(issueID);

for (Triplet<String, Verifier, ConditionChecker> verifier : verifications) {
for (Triplet<String, BiConsumer<HostingRequest, HashSet<VerificationMessage>>, Predicate<HostingRequest>> verifier : verifications) {
try {
boolean runIt = verifier.getValue2() == null || verifier.getValue2().checkCondition(hostingRequest);
boolean runIt = verifier.getValue2() == null || verifier.getValue2().test(hostingRequest);
if (runIt) {
LOGGER.info("Running verification '" + verifier.getValue0() + "'");
verifier.getValue1().verify(hostingRequest, hostingIssues);
verifier.getValue1().accept(hostingRequest, hostingIssues);
}

if (verifier.getValue1() instanceof BuildSystemVerifier) {
hasBuildSystem |= ((BuildSystemVerifier) verifier.getValue1()).hasBuildFile(hostingRequest);
if (verifier.getValue1() instanceof MavenVerifierConsumer mavenVerifierConsumer) {
hasBuildSystem |= mavenVerifierConsumer.hasBuildFile(hostingRequest);
}
} catch (Exception e) {
LOGGER.error("Error running verification '" + verifier.getValue0(), e);
Expand All @@ -72,24 +83,27 @@ public void checkRequest(int issueID) throws IOException {
StringBuilder msg = new StringBuilder("Hello from your friendly Jenkins Hosting Checker\n\n");
LOGGER.info("Checking if there were errors");
if (!hostingIssues.isEmpty()) {
msg.append("It appears you have some issues with your hosting request. Please see the list below and "
+ "correct all issues marked Required. Your hosting request will not be "
+ "approved until these issues are corrected. Issues marked with Warning "
+ "or Info are just recommendations and will not stall the hosting process.\n");
msg.append(INITIAL_HOSTING_REQUEST_FEEDBACK);
LOGGER.info("Appending issues to msg");
appendIssues(msg, hostingIssues, 1);
msg.append("\nYou can re-trigger a check by editing your hosting request or by commenting `/hosting re-check`");
msg.append("""

You can re-trigger a check by editing your hosting request or by commenting `/hosting re-check`""");
} else {
msg.append("It looks like you have everything in order for your hosting request. "
+ "A member of the [Jenkins hosting team](https://www.jenkins.io/project/teams/hosting/#members-of-the-hosting-team) "
+ "will check over things that I am not able to check"
+ "(code review, README content, etc) and process the request as quickly as possible. "
+ "Thank you for your patience.\n")
.append("\nHosting team members can host this request with `/hosting host`");
msg.append("""
It looks like you have everything in order for your hosting request. \
A member of the [Jenkins hosting team](https://www.jenkins.io/project/teams/hosting/#members-of-the-hosting-team) \
will check over things that I am not able to check\
(code review, README content, etc) and process the request as quickly as possible. \
Thank you for your patience.
""")
.append("""

Hosting team members can host this request with `/hosting host`""");
}

LOGGER.info(msg.toString());
if (!debug) {
if (!DEBUG_HOSTING) {
GitHub github = GitHub.connect();
GHIssue issue = github.getRepository(HOSTING_REPO_SLUG).getIssue(issueID);
issue.comment(msg.toString());
Expand All @@ -108,7 +122,7 @@ public void checkRequest(int issueID) throws IOException {
}

private void appendIssues(StringBuilder msg, Set<VerificationMessage> issues, int level) {
for (VerificationMessage issue : issues.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList())) {
for (VerificationMessage issue : issues.stream().sorted(Comparator.reverseOrder()).toList()) {
if (level == 1) {
msg.append("%s %s %s: %s%n".formatted(StringUtils.repeat("*", level), issue.getSeverity().getColor(), issue.getSeverity().getMessage(), issue.getMessage()));
} else {
Expand All @@ -124,7 +138,7 @@ private void appendIssues(StringBuilder msg, Set<VerificationMessage> issues, in
public static boolean fileExistsInRepo(HostingRequest issue, String fileName) throws IOException {
boolean res = false;
GitHub github = GitHub.connect();
String forkFrom = issue.getRepositoryUrl();
String forkFrom = issue.repositoryUrl();
if (StringUtils.isNotBlank(forkFrom)) {
Matcher m = Pattern.compile("https://github\\.com/(\\S+)/(\\S+)", CASE_INSENSITIVE).matcher(forkFrom);
if (m.matches()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.jenkins.infra.repository_permissions_updater.hosting;

import java.util.ResourceBundle;
import java.util.regex.Pattern;

public final class HostingConfig {

static final String TARGET_ORG_NAME;
Expand All @@ -10,8 +13,11 @@ public final class HostingConfig {
static final String JIRA_USERNAME = System.getenv("JIRA_USERNAME");
static final String JIRA_PASSWORD = System.getenv("JIRA_PASSWORD");
static final String JIRA_PROJECT;
public static final Pattern GITHUB_FORK_PATTERN;
public static final ResourceBundle RESOURCE_BUNDLE;

private HostingConfig() {
throw new IllegalStateException("Utility class");
}

static {
Expand All @@ -24,5 +30,8 @@ private HostingConfig() {

String projectOverride = System.getenv("JIRA_PROJECT_NAME");
JIRA_PROJECT = projectOverride != null ? projectOverride : "JENKINS";

GITHUB_FORK_PATTERN = Pattern.compile("(?:https://github\\.com/)?(\\S+)/(\\S+)", Pattern.CASE_INSENSITIVE);
RESOURCE_BUNDLE = ResourceBundle.getBundle(HOSTING_REPO_NAME);
}
}
Loading