package im.tox.upsourcebot.client;
import com.google.common.collect.ImmutableMap;
import org.kohsuke.github.GHCommitState;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.github.GitHub;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import im.tox.upsourcebot.Repository;
import im.tox.upsourcebot.client.tasks.FindReviewerTask;
import im.tox.upsourcebot.client.tasks.GitHubAssignTask;
import im.tox.upsourcebot.client.tasks.GitHubCommitStatusTask;
import im.tox.upsourcebot.client.tasks.GitHubGetOpenPullRequestsTask;
import im.tox.upsourcebot.client.tasks.GitHubGreeterTask;
import im.tox.upsourcebot.client.tasks.GitHubIssueCommentTask;
import im.tox.upsourcebot.client.tasks.RetryingCallable;
public class GitHubConnector {
private static final Logger LOGGER = LoggerFactory.getLogger(GitHubConnector.class);
private final GitHub gitHub;
private final ImmutableMap<String, Repository> repositories;
private final ImmutableMap<String, ExecutorService> executors;
public GitHubConnector(GitHub gitHub,
ImmutableMap<String, Repository> repositories,
ImmutableMap<String, ExecutorService> executors) {
this.gitHub = gitHub;
this.repositories = repositories;
this.executors = executors;
}
public void commentOnIssue(String repoName, String comment, int issueNumber) {
executors.get(repoName).submit(RetryingCallable.of(
new GitHubIssueCommentTask(gitHub, repoName, issueNumber, comment)));
}
public void setPendingCommitStatus(String repoName, String commitSHA, String url,
String description, String context) {
executors.get(repoName).submit(RetryingCallable
.of(new GitHubCommitStatusTask(gitHub, repoName, commitSHA, GHCommitState.PENDING, url,
description, context)));
}
public void assignAndGreet(String repoName, String author, int issueNumber) {
Future<String> reviewer = findReviewer(repoName, author);
ExecutorService executorService = executors.get(repoName);
executorService.submit(RetryingCallable
.of(new GitHubAssignTask(gitHub, repoName, issueNumber, reviewer)));
executorService.submit(RetryingCallable
.of(new GitHubGreeterTask(gitHub, repoName, issueNumber,
repositories.get(repoName).getGreetings(), reviewer, author)));
}
public void handleStartup() {
executors
.forEach(this::handleRepositoryStartup);
}
private Future<String> findReviewer(String repoName, String author) {
return executors.get(repoName).submit(RetryingCallable.of(
new FindReviewerTask(gitHub, repoName, repositories.get(repoName).getReviewers(), author)));
}
private void handleRepositoryStartup(String repoName, ExecutorService executorService) {
Future<List<GHPullRequest>> pullRequests = executorService
.submit(RetryingCallable.of(new GitHubGetOpenPullRequestsTask(gitHub, repoName)));
executorService.execute(() -> {
List<GHPullRequest> prs;
try {
prs = pullRequests.get();
} catch (InterruptedException e) {
LOGGER.error("Pull Request fetch was interrupted", e);
Thread.currentThread().interrupt();
return;
} catch (ExecutionException e) {
LOGGER.error("Pull Request fetch task was aborted", e);
return;
}
prs.stream().filter(ghPullRequest -> ghPullRequest.getAssignee() == null).forEach(
ghPullRequest -> assignAndGreet(repoName, ghPullRequest.getUser().getLogin(),
ghPullRequest.getNumber()));
});
}
}