Skip to content

Commit 6d8374f

Browse files
committed
Add support for test/restest command in pull request comment
1 parent b2d8279 commit 6d8374f

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package io.quarkus.bot;
2+
3+
import io.quarkiverse.githubapp.event.IssueComment;
4+
import io.quarkus.bot.command.Command;
5+
import io.quarkus.bot.config.QuarkusBotConfig;
6+
import org.jboss.logging.Logger;
7+
import org.kohsuke.github.GHEventPayload;
8+
import org.kohsuke.github.GHIssue;
9+
import org.kohsuke.github.GHPermissionType;
10+
import org.kohsuke.github.GHPullRequest;
11+
import org.kohsuke.github.GHRepository;
12+
import org.kohsuke.github.GHUser;
13+
import org.kohsuke.github.ReactionContent;
14+
15+
import javax.enterprise.inject.Instance;
16+
import javax.inject.Inject;
17+
import java.io.IOException;
18+
import java.util.Optional;
19+
import java.util.regex.Matcher;
20+
import java.util.regex.Pattern;
21+
22+
public class PullRequestCommandHandler {
23+
24+
private static final Logger LOG = Logger.getLogger(PullRequestCommandHandler.class);
25+
26+
private static final String QUARKUS_BOT_NAME = "quarkus-bot[bot]";
27+
private static final Pattern QUARKUS_BOT_MENTION = Pattern.compile("^@(?:quarkus-?)?bot\\s+([a-z _\\-]+)");
28+
29+
@Inject
30+
Instance<Command<GHPullRequest>> commands;
31+
32+
@Inject
33+
QuarkusBotConfig quarkusBotConfig;
34+
35+
public void onComment(@IssueComment.Created @IssueComment.Edited GHEventPayload.IssueComment commentPayload)
36+
throws IOException {
37+
GHUser user = commentPayload.getComment().getUser();
38+
GHIssue issue = commentPayload.getIssue();
39+
GHRepository repository = commentPayload.getRepository();
40+
41+
if (QUARKUS_BOT_NAME.equals(commentPayload.getComment().getUserName())) {
42+
return;
43+
}
44+
45+
if (issue.isPullRequest()) {
46+
Optional<Command<GHPullRequest>> command = extractCommand(commentPayload.getComment().getBody());
47+
if (command.isPresent() && canRunCommand(repository, user)) {
48+
GHPullRequest pullRequest = repository.getPullRequest(issue.getNumber());
49+
ReactionContent reactionResult = command.get().run(pullRequest);
50+
postReaction(commentPayload, issue, reactionResult);
51+
} else {
52+
postReaction(commentPayload, issue, ReactionContent.MINUS_ONE);
53+
}
54+
}
55+
}
56+
57+
private void postReaction(GHEventPayload.IssueComment comment, GHIssue issue, ReactionContent reactionResult) throws IOException {
58+
if (!quarkusBotConfig.isDryRun()) {
59+
comment.getComment().createReaction(reactionResult);
60+
} else {
61+
LOG.info("Pull Request #" + issue.getNumber() + " - Add reaction: " + reactionResult.getContent());
62+
}
63+
}
64+
65+
private Optional<Command<GHPullRequest>> extractCommand(String comment) {
66+
Matcher matcher = QUARKUS_BOT_MENTION.matcher(comment);
67+
if (matcher.matches()) {
68+
String commandLabel = matcher.group(1);
69+
return commands.stream().filter(command -> command.labels().contains(commandLabel)).findFirst();
70+
}
71+
return Optional.empty();
72+
}
73+
74+
private boolean canRunCommand(GHRepository repository, GHUser user) throws IOException {
75+
return repository.getPermission(user) == GHPermissionType.WRITE || repository.getPermission(user) == GHPermissionType.ADMIN;
76+
}
77+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.quarkus.bot.command;
2+
3+
import org.kohsuke.github.ReactionContent;
4+
5+
import java.io.IOException;
6+
import java.util.List;
7+
8+
public interface Command<T> {
9+
10+
List<String> labels();
11+
12+
ReactionContent run(T input) throws IOException;
13+
14+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package io.quarkus.bot.command;
2+
3+
import io.quarkus.bot.config.QuarkusBotConfig;
4+
import io.quarkus.bot.workflow.WorkflowConstants;
5+
import org.jboss.logging.Logger;
6+
import org.kohsuke.github.GHPullRequest;
7+
import org.kohsuke.github.GHRepository;
8+
import org.kohsuke.github.GHWorkflowRun;
9+
import org.kohsuke.github.ReactionContent;
10+
11+
import javax.enterprise.context.ApplicationScoped;
12+
import javax.inject.Inject;
13+
import java.io.IOException;
14+
import java.util.Arrays;
15+
import java.util.Comparator;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.Optional;
19+
import java.util.stream.Collectors;
20+
21+
@ApplicationScoped
22+
public class RerunWorkflowCommand implements Command<GHPullRequest> {
23+
24+
private static final Logger LOG = Logger.getLogger(RerunWorkflowCommand.class);
25+
26+
@Inject
27+
QuarkusBotConfig quarkusBotConfig;
28+
29+
@Override
30+
public List<String> labels() {
31+
return Arrays.asList("test", "retest");
32+
}
33+
34+
@Override
35+
public ReactionContent run(GHPullRequest pullRequest) throws IOException {
36+
GHRepository repository = pullRequest.getRepository();
37+
38+
List<GHWorkflowRun> ghWorkflowRuns = repository
39+
.queryWorkflowRuns()
40+
.branch(pullRequest.getHead().getRef())
41+
.status(GHWorkflowRun.Status.COMPLETED)
42+
.list().toList();
43+
44+
Map<String, Optional<GHWorkflowRun>> lastWorkflowRuns = ghWorkflowRuns.stream()
45+
.filter(workflowRun -> WorkflowConstants.QUARKUS_CI_WORKFLOW_NAME.equals(workflowRun.getName())
46+
|| WorkflowConstants.QUARKUS_DOCUMENTATION_CI_WORKFLOW_NAME.equals(workflowRun.getName()))
47+
.filter(workflowRun -> workflowRun.getHeadRepository().getOwnerName()
48+
.equals(pullRequest.getHead().getRepository().getOwnerName()))
49+
.collect(Collectors.groupingBy(GHWorkflowRun::getName, Collectors.maxBy(Comparator.comparing(GHWorkflowRun::getRunNumber))));
50+
51+
for (Map.Entry<String, Optional<GHWorkflowRun>> lastWorkflowRun : lastWorkflowRuns.entrySet()) {
52+
if (lastWorkflowRun.getValue().isPresent()) {
53+
if (!quarkusBotConfig.isDryRun()) {
54+
lastWorkflowRun.getValue().get().rerun();
55+
LOG.debug("Pull request #" + pullRequest.getNumber() + " - Restart workflow: " + lastWorkflowRun.getValue().get().getHtmlUrl());
56+
} else {
57+
LOG.info("Pull request #" + pullRequest.getNumber() + " - Restart workflow " + lastWorkflowRun.getKey());
58+
}
59+
}
60+
}
61+
return ReactionContent.ROCKET;
62+
}
63+
}

0 commit comments

Comments
 (0)