Merge pull request #1 from ryanjbaxter/boot-upgrade
Upgrade to Spring Boot 3.1.4
This commit is contained in:
12
pom.xml
12
pom.xml
@@ -14,13 +14,13 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<version>3.1.4</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -29,8 +29,8 @@
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -58,7 +58,7 @@
|
||||
<plugin>
|
||||
<groupId>io.spring.javaformat</groupId>
|
||||
<artifactId>spring-javaformat-maven-plugin</artifactId>
|
||||
<version>0.0.6</version>
|
||||
<version>0.0.39</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
@@ -103,7 +103,7 @@
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.7.5.201505241946</version>
|
||||
<version>0.8.10</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jacoco-initialize</id>
|
||||
|
||||
@@ -49,11 +49,9 @@ public class IssueBotApplication {
|
||||
}
|
||||
|
||||
@Bean
|
||||
RepositoryMonitor repositoryMonitor(GitHubOperations gitHub,
|
||||
MonitoringProperties monitoringProperties,
|
||||
RepositoryMonitor repositoryMonitor(GitHubOperations gitHub, MonitoringProperties monitoringProperties,
|
||||
List<MultiRepositoryIssueListener> issueListeners) {
|
||||
return new RepositoryMonitor(gitHub, monitoringProperties.getRepositories(),
|
||||
issueListeners);
|
||||
return new RepositoryMonitor(gitHub, monitoringProperties.getRepositories(), issueListeners);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,8 +59,7 @@ class RepositoryMonitor {
|
||||
private void monitor(Repository repository) {
|
||||
log.info("Monitoring {}/{}", repository.getOrganization(), repository.getName());
|
||||
try {
|
||||
Page<Issue> page = this.gitHub.getIssues(repository.getOrganization(),
|
||||
repository.getName());
|
||||
Page<Issue> page = this.gitHub.getIssues(repository.getOrganization(), repository.getName());
|
||||
while (page != null) {
|
||||
for (Issue issue : page.getContent()) {
|
||||
for (MultiRepositoryIssueListener issueListener : this.issueListeners) {
|
||||
@@ -68,8 +67,7 @@ class RepositoryMonitor {
|
||||
issueListener.onOpenIssue(repository, issue);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
log.warn("Listener '{}' failed when handling issue '{}'",
|
||||
issueListener, issue, ex);
|
||||
log.warn("Listener '{}' failed when handling issue '{}'", issueListener, issue, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,11 +75,10 @@ class RepositoryMonitor {
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
log.warn("A failure occurred during monitoring of {}/{}",
|
||||
repository.getOrganization(), repository.getName(), ex);
|
||||
log.warn("A failure occurred during monitoring of {}/{}", repository.getOrganization(),
|
||||
repository.getName(), ex);
|
||||
}
|
||||
log.info("Monitoring of {}/{} completed", repository.getOrganization(),
|
||||
repository.getName());
|
||||
log.info("Monitoring of {}/{} completed", repository.getOrganization(), repository.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,29 +44,23 @@ import org.springframework.context.annotation.Configuration;
|
||||
class FeedbackConfiguration {
|
||||
|
||||
@Bean
|
||||
MultiRepositoryIssueListener feedbackIssueListener(
|
||||
MonitoringProperties monitoringProperties, GitHubOperations gitHub,
|
||||
GitHubProperties githubProperties, FeedbackProperties feedbackProperties) {
|
||||
MultiRepositoryIssueListener feedbackIssueListener(MonitoringProperties monitoringProperties,
|
||||
GitHubOperations gitHub, GitHubProperties githubProperties, FeedbackProperties feedbackProperties) {
|
||||
Map<Repository, IssueListener> delegates = monitoringProperties.getRepositories()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Function.identity(),
|
||||
(repository) -> createListener(repository, gitHub,
|
||||
githubProperties, feedbackProperties)));
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Function.identity(),
|
||||
(repository) -> createListener(repository, gitHub, githubProperties, feedbackProperties)));
|
||||
return new RoutingMultiRepositoryIssueListener(delegates);
|
||||
}
|
||||
|
||||
private FeedbackIssueListener createListener(Repository repository,
|
||||
GitHubOperations gitHub, GitHubProperties githubProperties,
|
||||
FeedbackProperties feedbackProperties) {
|
||||
return new FeedbackIssueListener(gitHub, feedbackProperties.getRequiredLabel(),
|
||||
repository.getCollaborators(),
|
||||
private FeedbackIssueListener createListener(Repository repository, GitHubOperations gitHub,
|
||||
GitHubProperties githubProperties, FeedbackProperties feedbackProperties) {
|
||||
return new FeedbackIssueListener(gitHub, feedbackProperties.getRequiredLabel(), repository.getCollaborators(),
|
||||
githubProperties.getCredentials().getUsername(),
|
||||
new StandardFeedbackListener(gitHub,
|
||||
feedbackProperties.getProvidedLabel(),
|
||||
feedbackProperties.getRequiredLabel(),
|
||||
feedbackProperties.getReminderLabel(),
|
||||
feedbackProperties.getReminderComment(),
|
||||
feedbackProperties.getCloseComment(), Collections.emptyList()));
|
||||
new StandardFeedbackListener(gitHub, feedbackProperties.getProvidedLabel(),
|
||||
feedbackProperties.getRequiredLabel(), feedbackProperties.getReminderLabel(),
|
||||
feedbackProperties.getReminderComment(), feedbackProperties.getCloseComment(),
|
||||
Collections.emptyList()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,8 +43,7 @@ final class FeedbackIssueListener implements IssueListener {
|
||||
|
||||
private final FeedbackListener feedbackListener;
|
||||
|
||||
FeedbackIssueListener(GitHubOperations gitHub, String labelName,
|
||||
List<String> collaborators, String username,
|
||||
FeedbackIssueListener(GitHubOperations gitHub, String labelName, List<String> collaborators, String username,
|
||||
FeedbackListener feedbackListener) {
|
||||
this.gitHub = gitHub;
|
||||
this.labelName = labelName;
|
||||
@@ -90,8 +89,7 @@ final class FeedbackIssueListener implements IssueListener {
|
||||
Page<Event> page = this.gitHub.getEvents(issue);
|
||||
while (page != null) {
|
||||
for (Event event : page.getContent()) {
|
||||
if (Event.Type.LABELED.equals(event.getType())
|
||||
&& this.labelName.equals(event.getLabel().getName())) {
|
||||
if (Event.Type.LABELED.equals(event.getType()) && this.labelName.equals(event.getLabel().getName())) {
|
||||
createdAt = event.getCreationTime();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,8 @@ final class StandardFeedbackListener implements FeedbackListener {
|
||||
|
||||
private final List<IssueListener> issueListeners;
|
||||
|
||||
StandardFeedbackListener(GitHubOperations gitHub, String providedLabel,
|
||||
String requiredLabel, String reminderLabel, String reminderComment,
|
||||
String closeComment, List<IssueListener> issueListeners) {
|
||||
StandardFeedbackListener(GitHubOperations gitHub, String providedLabel, String requiredLabel, String reminderLabel,
|
||||
String reminderComment, String closeComment, List<IssueListener> issueListeners) {
|
||||
this.gitHub = gitHub;
|
||||
this.providedLabel = providedLabel;
|
||||
this.requiredLabel = requiredLabel;
|
||||
|
||||
@@ -39,8 +39,7 @@ public final class Comment {
|
||||
* @param creationTime the creation time
|
||||
*/
|
||||
@JsonCreator
|
||||
public Comment(@JsonProperty("user") User user,
|
||||
@JsonProperty("created_at") OffsetDateTime creationTime) {
|
||||
public Comment(@JsonProperty("user") User user, @JsonProperty("created_at") OffsetDateTime creationTime) {
|
||||
this.user = user;
|
||||
this.creationTime = creationTime;
|
||||
}
|
||||
|
||||
@@ -45,8 +45,7 @@ public class Event {
|
||||
* @param label the label associated with the event
|
||||
*/
|
||||
@JsonCreator
|
||||
public Event(@JsonProperty("event") String type,
|
||||
@JsonProperty("created_at") OffsetDateTime creationTime,
|
||||
public Event(@JsonProperty("event") String type, @JsonProperty("created_at") OffsetDateTime creationTime,
|
||||
@JsonProperty("label") Label label) {
|
||||
this.type = Type.valueFrom(type);
|
||||
this.creationTime = creationTime;
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hc.client5.http.utils.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -44,7 +45,6 @@ import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
@@ -86,31 +86,24 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
rest.setErrorHandler(new DefaultResponseErrorHandler() {
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
if (response.getStatusCode() == HttpStatus.FORBIDDEN && response
|
||||
.getHeaders().getFirst("X-RateLimit-Remaining").equals("0")) {
|
||||
throw new IllegalStateException(
|
||||
"Rate limit exceeded. Limit will reset at "
|
||||
+ new Date(Long
|
||||
.valueOf(response.getHeaders()
|
||||
.getFirst("X-RateLimit-Reset"))
|
||||
* 1000));
|
||||
if (response.getStatusCode() == HttpStatus.FORBIDDEN
|
||||
&& response.getHeaders().getFirst("X-RateLimit-Remaining").equals("0")) {
|
||||
throw new IllegalStateException("Rate limit exceeded. Limit will reset at "
|
||||
+ new Date(Long.valueOf(response.getHeaders().getFirst("X-RateLimit-Reset")) * 1000));
|
||||
}
|
||||
}
|
||||
});
|
||||
BufferingClientHttpRequestFactory bufferingClient = new BufferingClientHttpRequestFactory(
|
||||
new HttpComponentsClientHttpRequestFactory());
|
||||
rest.setRequestFactory(bufferingClient);
|
||||
rest.setInterceptors(Collections
|
||||
.singletonList(new BasicAuthorizationInterceptor(username, password)));
|
||||
rest.setMessageConverters(
|
||||
Arrays.asList(new ErrorLoggingMappingJackson2HttpMessageConverter()));
|
||||
rest.setInterceptors(Collections.singletonList(new BasicAuthorizationInterceptor(username, password)));
|
||||
rest.setMessageConverters(Arrays.asList(new ErrorLoggingMappingJackson2HttpMessageConverter()));
|
||||
return rest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Issue> getIssues(String organization, String repository) {
|
||||
String url = "https://api.github.com/repos/" + organization + "/" + repository
|
||||
+ "/issues";
|
||||
String url = "https://api.github.com/repos/" + organization + "/" + repository + "/issues";
|
||||
return getPage(url, Issue[].class);
|
||||
}
|
||||
|
||||
@@ -129,8 +122,7 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
return null;
|
||||
}
|
||||
ResponseEntity<T[]> contents = this.rest.getForEntity(url, type);
|
||||
return new StandardPage<>(Arrays.asList(contents.getBody()),
|
||||
() -> getPage(getNextUrl(contents), type));
|
||||
return new StandardPage<>(Arrays.asList(contents.getBody()), () -> getPage(getNextUrl(contents), type));
|
||||
}
|
||||
|
||||
private String getNextUrl(ResponseEntity<?> response) {
|
||||
@@ -141,16 +133,13 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
public Issue addLabel(Issue issue, String labelName) {
|
||||
URI uri = URI.create(issue.getLabelsUrl().replace("{/name}", ""));
|
||||
log.info("Adding label {} to {}", labelName, uri);
|
||||
ResponseEntity<Label[]> response = this.rest.exchange(
|
||||
new RequestEntity<>(Arrays.asList(labelName), HttpMethod.POST, uri),
|
||||
Label[].class);
|
||||
ResponseEntity<Label[]> response = this.rest
|
||||
.exchange(new RequestEntity<>(Arrays.asList(labelName), HttpMethod.POST, uri), Label[].class);
|
||||
if (response.getStatusCode() != HttpStatus.OK) {
|
||||
log.warn("Failed to add label to issue. Response status: "
|
||||
+ response.getStatusCode());
|
||||
log.warn("Failed to add label to issue. Response status: " + response.getStatusCode());
|
||||
}
|
||||
return new Issue(issue.getUrl(), issue.getCommentsUrl(), issue.getEventsUrl(),
|
||||
issue.getLabelsUrl(), issue.getUser(), Arrays.asList(response.getBody()),
|
||||
issue.getMilestone(), issue.getPullRequest());
|
||||
return new Issue(issue.getUrl(), issue.getCommentsUrl(), issue.getEventsUrl(), issue.getLabelsUrl(),
|
||||
issue.getUser(), Arrays.asList(response.getBody()), issue.getMilestone(), issue.getPullRequest());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -162,42 +151,35 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
catch (URISyntaxException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
ResponseEntity<Label[]> response = this.rest.exchange(
|
||||
new RequestEntity<Void>(HttpMethod.DELETE, URI.create(
|
||||
issue.getLabelsUrl().replace("{/name}", "/" + encodedName))),
|
||||
Label[].class);
|
||||
ResponseEntity<Label[]> response = this.rest.exchange(new RequestEntity<Void>(HttpMethod.DELETE,
|
||||
URI.create(issue.getLabelsUrl().replace("{/name}", "/" + encodedName))), Label[].class);
|
||||
List<Label> labels;
|
||||
if (response.getStatusCode() != HttpStatus.OK) {
|
||||
log.warn("Failed to remove label from issue. Response status: "
|
||||
+ response.getStatusCode());
|
||||
log.warn("Failed to remove label from issue. Response status: " + response.getStatusCode());
|
||||
labels = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
labels = Arrays.asList(response.getBody());
|
||||
}
|
||||
return new Issue(issue.getUrl(), issue.getCommentsUrl(), issue.getEventsUrl(),
|
||||
issue.getLabelsUrl(), issue.getUser(), labels, issue.getMilestone(),
|
||||
issue.getPullRequest());
|
||||
return new Issue(issue.getUrl(), issue.getCommentsUrl(), issue.getEventsUrl(), issue.getLabelsUrl(),
|
||||
issue.getUser(), labels, issue.getMilestone(), issue.getPullRequest());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comment addComment(Issue issue, String comment) {
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put("body", comment);
|
||||
return this.rest.postForEntity(issue.getCommentsUrl(), body, Comment.class)
|
||||
.getBody();
|
||||
return this.rest.postForEntity(issue.getCommentsUrl(), body, Comment.class).getBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Issue close(Issue issue) {
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put("state", "closed");
|
||||
ResponseEntity<Issue> response = this.rest.exchange(
|
||||
new RequestEntity<>(body, HttpMethod.PATCH, URI.create(issue.getUrl())),
|
||||
Issue.class);
|
||||
ResponseEntity<Issue> response = this.rest
|
||||
.exchange(new RequestEntity<>(body, HttpMethod.PATCH, URI.create(issue.getUrl())), Issue.class);
|
||||
if (response.getStatusCode() != HttpStatus.OK) {
|
||||
log.warn("Failed to close issue. Response status: "
|
||||
+ response.getStatusCode());
|
||||
log.warn("Failed to close issue. Response status: " + response.getStatusCode());
|
||||
}
|
||||
return response.getBody();
|
||||
}
|
||||
@@ -208,8 +190,7 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
private static final Charset CHARSET_UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
@Override
|
||||
public Object read(Type type, Class<?> contextClass,
|
||||
HttpInputMessage inputMessage)
|
||||
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
|
||||
throws IOException, HttpMessageNotReadableException {
|
||||
try {
|
||||
return super.read(type, contextClass, inputMessage);
|
||||
@@ -226,8 +207,7 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
if (inputMessage instanceof ClientHttpResponse) {
|
||||
ClientHttpResponse response = (ClientHttpResponse) inputMessage;
|
||||
if (response.getStatusCode().is2xxSuccessful()) {
|
||||
log.error("Failed to create {} from {}", type.getTypeName(),
|
||||
read(inputMessage), ex);
|
||||
log.error("Failed to create {} from {}", type.getTypeName(), read(inputMessage), ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@@ -241,8 +221,7 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
|
||||
}
|
||||
|
||||
private static class BasicAuthorizationInterceptor
|
||||
implements ClientHttpRequestInterceptor {
|
||||
private static class BasicAuthorizationInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
@@ -256,10 +235,9 @@ public class GitHubTemplate implements GitHubOperations {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution) throws IOException {
|
||||
String token = Base64Utils.encodeToString(
|
||||
(this.username + ":" + this.password).getBytes(UTF_8));
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
String token = Base64.encodeBase64String((this.username + ":" + this.password).getBytes(UTF_8));
|
||||
request.getHeaders().add("Authorization", "Basic " + token);
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
|
||||
@@ -56,13 +56,10 @@ public class Issue {
|
||||
* @param pullRequest details of the pull request (if this issue is a pull request)
|
||||
*/
|
||||
@JsonCreator
|
||||
public Issue(@JsonProperty("url") String url,
|
||||
@JsonProperty("comments_url") String commentsUrl,
|
||||
@JsonProperty("events_url") String eventsUrl,
|
||||
@JsonProperty("labels_url") String labelsUrl, @JsonProperty("user") User user,
|
||||
@JsonProperty("labels") List<Label> labels,
|
||||
@JsonProperty("milestone") Milestone milestone,
|
||||
@JsonProperty("pull_request") PullRequest pullRequest) {
|
||||
public Issue(@JsonProperty("url") String url, @JsonProperty("comments_url") String commentsUrl,
|
||||
@JsonProperty("events_url") String eventsUrl, @JsonProperty("labels_url") String labelsUrl,
|
||||
@JsonProperty("user") User user, @JsonProperty("labels") List<Label> labels,
|
||||
@JsonProperty("milestone") Milestone milestone, @JsonProperty("pull_request") PullRequest pullRequest) {
|
||||
this.url = url;
|
||||
this.commentsUrl = commentsUrl;
|
||||
this.eventsUrl = eventsUrl;
|
||||
|
||||
@@ -43,19 +43,17 @@ import org.springframework.context.annotation.Configuration;
|
||||
class QuestionConfiguration {
|
||||
|
||||
@Bean
|
||||
MultiRepositoryIssueListener questionIssueListener(
|
||||
MonitoringProperties monitoringProperties, GitHubOperations gitHub,
|
||||
QuestionProperties questionProperties) {
|
||||
MultiRepositoryIssueListener questionIssueListener(MonitoringProperties monitoringProperties,
|
||||
GitHubOperations gitHub, QuestionProperties questionProperties) {
|
||||
Map<Repository, IssueListener> delegates = monitoringProperties.getRepositories()
|
||||
.stream().collect(Collectors.toMap(Function.identity(),
|
||||
(repository) -> createListener(gitHub, questionProperties)));
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Function.identity(), (repository) -> createListener(gitHub, questionProperties)));
|
||||
return new RoutingMultiRepositoryIssueListener(delegates);
|
||||
}
|
||||
|
||||
private QuestionIssueListener createListener(GitHubOperations gitHub,
|
||||
QuestionProperties questionProperties) {
|
||||
return new QuestionIssueListener(gitHub, questionProperties.getLabel(),
|
||||
questionProperties.getCloseComment(), Collections.emptyList());
|
||||
private QuestionIssueListener createListener(GitHubOperations gitHub, QuestionProperties questionProperties) {
|
||||
return new QuestionIssueListener(gitHub, questionProperties.getLabel(), questionProperties.getCloseComment(),
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -87,8 +87,7 @@ final class QuestionIssueListener implements IssueListener {
|
||||
Page<Event> page = this.gitHub.getEvents(issue);
|
||||
while (page != null) {
|
||||
for (Event event : page.getContent()) {
|
||||
if (Event.Type.LABELED.equals(event.getType())
|
||||
&& this.labelName.equals(event.getLabel().getName())) {
|
||||
if (Event.Type.LABELED.equals(event.getType()) && this.labelName.equals(event.getLabel().getName())) {
|
||||
createdAt = event.getCreationTime();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ final class MilestoneAppliedTriageFilter implements TriageFilter {
|
||||
@Override
|
||||
public boolean triaged(Issue issue) {
|
||||
if (issue.getMilestone() != null) {
|
||||
log.debug("Issue has been triaged. It has been added to milestone {}",
|
||||
issue.getMilestone().getTitle());
|
||||
log.debug("Issue has been triaged. It has been added to milestone {}", issue.getMilestone().getTitle());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -31,14 +31,12 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
final class OpenedByCollaboratorTriageFilter implements TriageFilter {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(OpenedByCollaboratorTriageFilter.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenedByCollaboratorTriageFilter.class);
|
||||
|
||||
private final List<String> collaborators;
|
||||
|
||||
OpenedByCollaboratorTriageFilter(List<String> collaborators) {
|
||||
this.collaborators = (collaborators != null) ? collaborators
|
||||
: Collections.emptyList();
|
||||
this.collaborators = (collaborators != null) ? collaborators : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,22 +47,18 @@ class TriageConfiguration {
|
||||
TriageProperties triageProperties, MonitoringProperties monitoringProperties,
|
||||
GitHubProperties gitHubProperties) {
|
||||
Map<Repository, IssueListener> delegates = monitoringProperties.getRepositories()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Function.identity(),
|
||||
(repository) -> createListener(repository, gitHubOperations,
|
||||
triageProperties)));
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Function.identity(),
|
||||
(repository) -> createListener(repository, gitHubOperations, triageProperties)));
|
||||
return new RoutingMultiRepositoryIssueListener(delegates);
|
||||
}
|
||||
|
||||
private TriageIssueListener createListener(Repository repository,
|
||||
GitHubOperations gitHubOperations, TriageProperties triageProperties) {
|
||||
private TriageIssueListener createListener(Repository repository, GitHubOperations gitHubOperations,
|
||||
TriageProperties triageProperties) {
|
||||
return new TriageIssueListener(
|
||||
Arrays.asList(
|
||||
new OpenedByCollaboratorTriageFilter(
|
||||
repository.getCollaborators()),
|
||||
Arrays.asList(new OpenedByCollaboratorTriageFilter(repository.getCollaborators()),
|
||||
new LabelledTriageFilter(), new MilestoneAppliedTriageFilter()),
|
||||
new LabelApplyingTriageListener(gitHubOperations,
|
||||
triageProperties.getLabel()));
|
||||
new LabelApplyingTriageListener(gitHubOperations, triageProperties.getLabel()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
package io.spring.issuebot;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
/**
|
||||
* Tests for {@link IssueBotApplication}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@SpringBootTest
|
||||
public class IssueBotApplicationTests {
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import io.spring.issuebot.MonitoringProperties.Repository;
|
||||
import io.spring.issuebot.github.GitHubOperations;
|
||||
import io.spring.issuebot.github.Issue;
|
||||
import io.spring.issuebot.github.Page;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.willThrow;
|
||||
@@ -40,11 +40,9 @@ public class RepositoryMonitorTests {
|
||||
|
||||
private final GitHubOperations gitHub = mock(GitHubOperations.class);
|
||||
|
||||
private final MultiRepositoryIssueListener issueListenerOne = mock(
|
||||
MultiRepositoryIssueListener.class);
|
||||
private final MultiRepositoryIssueListener issueListenerOne = mock(MultiRepositoryIssueListener.class);
|
||||
|
||||
private final MultiRepositoryIssueListener issueListenerTwo = mock(
|
||||
MultiRepositoryIssueListener.class);
|
||||
private final MultiRepositoryIssueListener issueListenerTwo = mock(MultiRepositoryIssueListener.class);
|
||||
|
||||
private final Repository repositoryOne = new Repository();
|
||||
|
||||
@@ -54,7 +52,7 @@ public class RepositoryMonitorTests {
|
||||
Arrays.asList(this.repositoryOne, this.repositoryTwo),
|
||||
Arrays.asList(this.issueListenerOne, this.issueListenerTwo));
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.repositoryOne.setOrganization("test");
|
||||
this.repositoryOne.setName("one");
|
||||
@@ -113,8 +111,7 @@ public class RepositoryMonitorTests {
|
||||
Issue issue = new Issue(null, null, null, null, null, null, null, null);
|
||||
given(page.getContent()).willReturn(Arrays.asList(issue));
|
||||
given(this.gitHub.getIssues("test", "one")).willReturn(page);
|
||||
willThrow(new RuntimeException()).given(this.issueListenerOne)
|
||||
.onOpenIssue(this.repositoryOne, issue);
|
||||
willThrow(new RuntimeException()).given(this.issueListenerOne).onOpenIssue(this.repositoryOne, issue);
|
||||
this.repositoryMonitor.monitor();
|
||||
verify(this.issueListenerOne).onOpenIssue(this.repositoryOne, issue);
|
||||
verify(this.issueListenerTwo).onOpenIssue(this.repositoryOne, issue);
|
||||
|
||||
@@ -28,7 +28,7 @@ import io.spring.issuebot.github.Label;
|
||||
import io.spring.issuebot.github.PullRequest;
|
||||
import io.spring.issuebot.github.StandardPage;
|
||||
import io.spring.issuebot.github.User;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -46,117 +46,98 @@ public class FeedbackIssueListenerTests {
|
||||
|
||||
private final FeedbackListener feedbackListener = mock(FeedbackListener.class);
|
||||
|
||||
private final IssueListener listener = new FeedbackIssueListener(this.gitHub,
|
||||
"required", Arrays.asList("Amy", "Brian"), "IssueBot", this.feedbackListener);
|
||||
private final IssueListener listener = new FeedbackIssueListener(this.gitHub, "required",
|
||||
Arrays.asList("Amy", "Brian"), "IssueBot", this.feedbackListener);
|
||||
|
||||
@Test
|
||||
public void pullRequestsAreIgnored() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, new PullRequest("url"));
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("required")), null,
|
||||
new PullRequest("url"));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verifyNoMoreInteractions(this.gitHub, this.feedbackListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issuesWithFeedbackRequiredLabelAreIgnored() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("something-else")), null, null);
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("something-else")), null, null);
|
||||
this.listener.onOpenIssue(issue);
|
||||
verifyNoMoreInteractions(this.gitHub, this.feedbackListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void feedbackRequiredForLabeledIssueWithEvent() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, null);
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("required")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now();
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verify(this.feedbackListener).feedbackRequired(issue, requestTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void feedbackProvidedAfterCommentFromNonCollaborator() {
|
||||
Issue issue = new Issue("issue_url", null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, null);
|
||||
Issue issue = new Issue("issue_url", null, null, null, null, Arrays.asList(new Label("required")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now().minusDays(1);
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))),
|
||||
() -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Comment(new User("Charlie"), OffsetDateTime.now())),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))), () -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(
|
||||
new StandardPage<>(Arrays.asList(new Comment(new User("Charlie"), OffsetDateTime.now())), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verify(this.feedbackListener).feedbackProvided(issue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void feedbackRequiredAfterCommentFromNonCollaboratorBeforeRequest() {
|
||||
Issue issue = new Issue("issue_url", null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, null);
|
||||
Issue issue = new Issue("issue_url", null, null, null, null, Arrays.asList(new Label("required")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now().minusDays(1);
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))),
|
||||
() -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(new StandardPage<>(Arrays.asList(
|
||||
new Comment(new User("Charlie"), OffsetDateTime.now().minusDays(2))),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))), () -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Comment(new User("Charlie"), OffsetDateTime.now().minusDays(2))), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verify(this.feedbackListener).feedbackRequired(issue, requestTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void feedbackRequiredAfterCommentFromCollaborator() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, null);
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("required")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now().minusDays(1);
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))),
|
||||
() -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Comment(new User("Amy"), OffsetDateTime.now())),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))), () -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(
|
||||
new StandardPage<>(Arrays.asList(new Comment(new User("Amy"), OffsetDateTime.now())), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verify(this.feedbackListener).feedbackRequired(issue, requestTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void feedbackRequiredAfterCommentFromIssueBot() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, null);
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("required")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now().minusDays(1);
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))),
|
||||
() -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Comment(new User("IssueBot"), OffsetDateTime.now())),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))), () -> null));
|
||||
given(this.gitHub.getComments(issue)).willReturn(
|
||||
new StandardPage<>(Arrays.asList(new Comment(new User("IssueBot"), OffsetDateTime.now())), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verify(this.feedbackListener).feedbackRequired(issue, requestTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issueWithNoMatchingLabeledEventIsIgnored() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, null);
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("required")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now();
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(
|
||||
new Event("labeled", requestTime, new Label("something-else"))),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("something-else"))), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verifyNoMoreInteractions(this.feedbackListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eventsWithWrongTypeAreIgnored() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("required")), null, null);
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("required")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now();
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("milestoned", requestTime, null)), () -> null));
|
||||
given(this.gitHub.getEvents(issue))
|
||||
.willReturn(new StandardPage<>(Arrays.asList(new Event("milestoned", requestTime, null)), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verifyNoMoreInteractions(this.feedbackListener);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import io.spring.issuebot.IssueListener;
|
||||
import io.spring.issuebot.github.GitHubOperations;
|
||||
import io.spring.issuebot.github.Issue;
|
||||
import io.spring.issuebot.github.Label;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -41,13 +41,11 @@ public class StandardFeedbackListenerTests {
|
||||
|
||||
private final IssueListener issueListener = mock(IssueListener.class);
|
||||
|
||||
private final FeedbackListener listener = new StandardFeedbackListener(this.gitHub,
|
||||
"feedback-provided", "feedback-required", "feedback-reminder",
|
||||
"Please provide requested feedback", "Closing due to lack of feedback",
|
||||
Arrays.asList(this.issueListener));
|
||||
private final FeedbackListener listener = new StandardFeedbackListener(this.gitHub, "feedback-provided",
|
||||
"feedback-required", "feedback-reminder", "Please provide requested feedback",
|
||||
"Closing due to lack of feedback", Arrays.asList(this.issueListener));
|
||||
|
||||
private final Issue issue = new Issue(null, null, null, null, null, new ArrayList<>(),
|
||||
null, null);
|
||||
private final Issue issue = new Issue(null, null, null, null, null, new ArrayList<>(), null, null);
|
||||
|
||||
@Test
|
||||
public void feedbackProvided() {
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
package io.spring.issuebot.github;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -30,11 +29,10 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.test.web.client.RequestMatcher;
|
||||
import org.springframework.test.web.client.response.DefaultResponseCreator;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
@@ -49,22 +47,18 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
|
||||
*/
|
||||
public class GitHubTemplateTests {
|
||||
|
||||
private final RestTemplate rest = GitHubTemplate.createDefaultRestTemplate("username",
|
||||
"password");
|
||||
private final RestTemplate rest = GitHubTemplate.createDefaultRestTemplate("username", "password");
|
||||
|
||||
private final MockRestServiceServer server = MockRestServiceServer
|
||||
.createServer(this.rest);
|
||||
private final MockRestServiceServer server = MockRestServiceServer.createServer(this.rest);
|
||||
|
||||
private GitHubTemplate gitHub = new GitHubTemplate(this.rest, new RegexLinkParser());
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void noIssues() {
|
||||
this.server.expect(requestTo("https://api.github.com/repos/org/repo/issues"))
|
||||
.andExpect(method(HttpMethod.GET)).andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
Page<Issue> issues = this.gitHub.getIssues("org", "repo");
|
||||
assertThat(issues.getContent()).isEmpty();
|
||||
assertThat(issues.next()).isNull();
|
||||
@@ -73,8 +67,9 @@ public class GitHubTemplateTests {
|
||||
@Test
|
||||
public void singlePageOfIssues() {
|
||||
this.server.expect(requestTo("https://api.github.com/repos/org/repo/issues"))
|
||||
.andExpect(method(HttpMethod.GET)).andExpect(basicAuth())
|
||||
.andRespond(withResource("issues-page-one.json"));
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("issues-page-one.json"));
|
||||
Page<Issue> issues = this.gitHub.getIssues("org", "repo");
|
||||
assertThat(issues.getContent()).hasSize(15);
|
||||
assertThat(issues.next()).isNull();
|
||||
@@ -85,11 +80,13 @@ public class GitHubTemplateTests {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Link", "<page-two>; rel=\"next\"");
|
||||
this.server.expect(requestTo("https://api.github.com/repos/org/repo/issues"))
|
||||
.andExpect(method(HttpMethod.GET)).andExpect(basicAuth())
|
||||
.andRespond(withResource("issues-page-one.json",
|
||||
"Link:<page-two>; rel=\"next\""));
|
||||
this.server.expect(requestTo("/page-two")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth()).andRespond(withResource("issues-page-two.json"));
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("issues-page-one.json", "Link:<page-two>; rel=\"next\""));
|
||||
this.server.expect(requestTo("/page-two"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("issues-page-two.json"));
|
||||
Page<Issue> pageOne = this.gitHub.getIssues("org", "repo");
|
||||
assertThat(pageOne.getContent()).hasSize(15);
|
||||
Page<Issue> pageTwo = pageOne.next();
|
||||
@@ -104,32 +101,33 @@ public class GitHubTemplateTests {
|
||||
headers.set("X-RateLimit-Remaining", "0");
|
||||
headers.set("X-RateLimit-Reset", Long.toString(reset / 1000));
|
||||
this.server.expect(requestTo("https://api.github.com/repos/org/repo/issues"))
|
||||
.andExpect(method(HttpMethod.GET)).andExpect(basicAuth())
|
||||
.andRespond(withStatus(HttpStatus.FORBIDDEN).headers(headers));
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage(equalToIgnoringCase(
|
||||
"Rate limit exceeded. Limit will reset at " + new Date(reset)));
|
||||
this.gitHub.getIssues("org", "repo");
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withStatus(HttpStatus.FORBIDDEN).headers(headers));
|
||||
assertThatThrownBy(() -> this.gitHub.getIssues("org", "repo")).isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("Rate limit exceeded. Limit will reset at " + new Date(reset));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noComments() {
|
||||
this.server.expect(requestTo("/commentsUrl")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
Page<Comment> comments = this.gitHub.getComments(
|
||||
new Issue(null, "commentsUrl", null, null, null, null, null, null));
|
||||
this.server.expect(requestTo("/commentsUrl"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
Page<Comment> comments = this.gitHub
|
||||
.getComments(new Issue(null, "commentsUrl", null, null, null, null, null, null));
|
||||
assertThat(comments.getContent()).isEmpty();
|
||||
assertThat(comments.next()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singlePageOfComments() {
|
||||
this.server.expect(requestTo("/commentsUrl")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("comments-page-one.json"));
|
||||
Page<Comment> comments = this.gitHub.getComments(
|
||||
new Issue(null, "commentsUrl", null, null, null, null, null, null));
|
||||
this.server.expect(requestTo("/commentsUrl"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("comments-page-one.json"));
|
||||
Page<Comment> comments = this.gitHub
|
||||
.getComments(new Issue(null, "commentsUrl", null, null, null, null, null, null));
|
||||
assertThat(comments.getContent()).hasSize(17);
|
||||
assertThat(comments.next()).isNull();
|
||||
}
|
||||
@@ -138,14 +136,16 @@ public class GitHubTemplateTests {
|
||||
public void multiplePagesOfComments() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Link", "<page-two>; rel=\"next\"");
|
||||
this.server.expect(requestTo("/commentsUrl")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth()).andRespond(withResource("comments-page-one.json",
|
||||
"Link:<page-two>; rel=\"next\""));
|
||||
this.server.expect(requestTo("/page-two")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("comments-page-two.json"));
|
||||
Page<Comment> pageOne = this.gitHub.getComments(
|
||||
new Issue(null, "commentsUrl", null, null, null, null, null, null));
|
||||
this.server.expect(requestTo("/commentsUrl"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("comments-page-one.json", "Link:<page-two>; rel=\"next\""));
|
||||
this.server.expect(requestTo("/page-two"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("comments-page-two.json"));
|
||||
Page<Comment> pageOne = this.gitHub
|
||||
.getComments(new Issue(null, "commentsUrl", null, null, null, null, null, null));
|
||||
assertThat(pageOne.getContent()).hasSize(17);
|
||||
Page<Comment> pageTwo = pageOne.next();
|
||||
assertThat(pageTwo).isNotNull();
|
||||
@@ -154,23 +154,23 @@ public class GitHubTemplateTests {
|
||||
|
||||
@Test
|
||||
public void addLabelToIssue() {
|
||||
this.server.expect(requestTo("labelsUrl")).andExpect(method(HttpMethod.POST))
|
||||
.andExpect(basicAuth()).andExpect(content().string("[\"test\"]"))
|
||||
.andRespond(
|
||||
withSuccess("[{\"name\":\"test\"}]", MediaType.APPLICATION_JSON));
|
||||
Issue issue = new Issue("issueUrl", null, null, "labelsUrl{/name}", null, null,
|
||||
null, null);
|
||||
this.server.expect(requestTo("labelsUrl"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(basicAuth())
|
||||
.andExpect(content().string("[\"test\"]"))
|
||||
.andRespond(withSuccess("[{\"name\":\"test\"}]", MediaType.APPLICATION_JSON));
|
||||
Issue issue = new Issue("issueUrl", null, null, "labelsUrl{/name}", null, null, null, null);
|
||||
Issue modifiedIssue = this.gitHub.addLabel(issue, "test");
|
||||
assertThat(modifiedIssue.getLabels()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeLabelFromIssue() {
|
||||
this.server.expect(requestTo("labels/test")).andExpect(method(HttpMethod.DELETE))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
Issue issue = new Issue(null, null, null, "labels{/name}", null, null, null,
|
||||
null);
|
||||
this.server.expect(requestTo("labels/test"))
|
||||
.andExpect(method(HttpMethod.DELETE))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
Issue issue = new Issue(null, null, null, "labels{/name}", null, null, null, null);
|
||||
Issue modifiedIssue = this.gitHub.removeLabel(issue, "test");
|
||||
assertThat(modifiedIssue.getLabels()).isEmpty();
|
||||
}
|
||||
@@ -178,20 +178,21 @@ public class GitHubTemplateTests {
|
||||
@Test
|
||||
public void removeLabelWithNameThatRequiresEncodingFromIssue() {
|
||||
this.server.expect(requestTo("labels/status:%20foo"))
|
||||
.andExpect(method(HttpMethod.DELETE)).andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
Issue issue = new Issue(null, null, null, "labels{/name}", null, null, null,
|
||||
null);
|
||||
.andExpect(method(HttpMethod.DELETE))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withSuccess("[]", MediaType.APPLICATION_JSON));
|
||||
Issue issue = new Issue(null, null, null, "labels{/name}", null, null, null, null);
|
||||
Issue modifiedIssue = this.gitHub.removeLabel(issue, "status: foo");
|
||||
assertThat(modifiedIssue.getLabels()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addCommentToIssue() {
|
||||
this.server.expect(requestTo("/commentsUrl")).andExpect(method(HttpMethod.POST))
|
||||
.andExpect(basicAuth())
|
||||
.andExpect(content().string("{\"body\":\"A test comment\"}"))
|
||||
.andRespond(withResource("new-comment.json"));
|
||||
this.server.expect(requestTo("/commentsUrl"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(basicAuth())
|
||||
.andExpect(content().string("{\"body\":\"A test comment\"}"))
|
||||
.andRespond(withResource("new-comment.json"));
|
||||
Issue issue = new Issue(null, "commentsUrl", null, null, null, null, null, null);
|
||||
Comment comment = this.gitHub.addComment(issue, "A test comment");
|
||||
assertThat(comment).isNotNull();
|
||||
@@ -199,10 +200,11 @@ public class GitHubTemplateTests {
|
||||
|
||||
@Test
|
||||
public void singlePageOfEvents() {
|
||||
this.server.expect(requestTo("/eventsUrl")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth()).andRespond(withResource("events-page-one.json"));
|
||||
Page<Event> events = this.gitHub.getEvents(
|
||||
new Issue(null, null, "eventsUrl", null, null, null, null, null));
|
||||
this.server.expect(requestTo("/eventsUrl"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("events-page-one.json"));
|
||||
Page<Event> events = this.gitHub.getEvents(new Issue(null, null, "eventsUrl", null, null, null, null, null));
|
||||
assertThat(events.getContent()).hasSize(12);
|
||||
assertThat(events.next()).isNull();
|
||||
}
|
||||
@@ -211,13 +213,15 @@ public class GitHubTemplateTests {
|
||||
public void multiplePagesOfEvents() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Link", "<page-two>; rel=\"next\"");
|
||||
this.server.expect(requestTo("/eventsUrl")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth()).andRespond(withResource("events-page-one.json",
|
||||
"Link:<page-two>; rel=\"next\""));
|
||||
this.server.expect(requestTo("/page-two")).andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth()).andRespond(withResource("events-page-two.json"));
|
||||
Page<Event> pageOne = this.gitHub.getEvents(
|
||||
new Issue(null, null, "eventsUrl", null, null, null, null, null));
|
||||
this.server.expect(requestTo("/eventsUrl"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("events-page-one.json", "Link:<page-two>; rel=\"next\""));
|
||||
this.server.expect(requestTo("/page-two"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(basicAuth())
|
||||
.andRespond(withResource("events-page-two.json"));
|
||||
Page<Event> pageOne = this.gitHub.getEvents(new Issue(null, null, "eventsUrl", null, null, null, null, null));
|
||||
assertThat(pageOne.getContent()).hasSize(12);
|
||||
Page<Event> pageTwo = pageOne.next();
|
||||
assertThat(pageTwo).isNotNull();
|
||||
@@ -226,13 +230,12 @@ public class GitHubTemplateTests {
|
||||
|
||||
@Test
|
||||
public void closeIssue() {
|
||||
this.server.expect(requestTo("issueUrl")).andExpect(method(HttpMethod.PATCH))
|
||||
.andExpect(basicAuth())
|
||||
.andExpect(content().string("{\"state\":\"closed\"}"))
|
||||
.andRespond(withSuccess("{\"url\":\"updatedIssueUrl\"}",
|
||||
MediaType.APPLICATION_JSON));
|
||||
Issue closedIssue = this.gitHub
|
||||
.close(new Issue("issueUrl", null, null, null, null, null, null, null));
|
||||
this.server.expect(requestTo("issueUrl"))
|
||||
.andExpect(method(HttpMethod.PATCH))
|
||||
.andExpect(basicAuth())
|
||||
.andExpect(content().string("{\"state\":\"closed\"}"))
|
||||
.andRespond(withSuccess("{\"url\":\"updatedIssueUrl\"}", MediaType.APPLICATION_JSON));
|
||||
Issue closedIssue = this.gitHub.close(new Issue("issueUrl", null, null, null, null, null, null, null));
|
||||
assertThat(closedIssue.getUrl()).isEqualTo("updatedIssueUrl");
|
||||
}
|
||||
|
||||
@@ -242,13 +245,13 @@ public class GitHubTemplateTests {
|
||||
String[] components = header.split(":");
|
||||
httpHeaders.set(components[0], components[1]);
|
||||
}
|
||||
return withSuccess(new UrlResource(getClass().getResource(resource)),
|
||||
MediaType.APPLICATION_JSON).headers(httpHeaders);
|
||||
return withSuccess(new UrlResource(getClass().getResource(resource)), MediaType.APPLICATION_JSON)
|
||||
.headers(httpHeaders);
|
||||
}
|
||||
|
||||
private RequestMatcher basicAuth() {
|
||||
return header("Authorization", "Basic "
|
||||
+ new String(Base64Utils.encode("username:password".getBytes())));
|
||||
return header("Authorization",
|
||||
"Basic " + new String(Base64.getEncoder().encode("username:password".getBytes())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.spring.issuebot.github;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -56,8 +56,7 @@ public class RegexLinkParserTests {
|
||||
|
||||
@Test
|
||||
public void multipleLinks() {
|
||||
Map<String, String> links = this.linkParser
|
||||
.parse("<url-one>; rel=\"foo\", <url-two>; rel=\"bar\"");
|
||||
Map<String, String> links = this.linkParser.parse("<url-one>; rel=\"foo\", <url-two>; rel=\"bar\"");
|
||||
assertThat(links).hasSize(2);
|
||||
assertThat(links).containsEntry("foo", "url-one");
|
||||
assertThat(links).containsEntry("bar", "url-two");
|
||||
|
||||
@@ -26,7 +26,7 @@ import io.spring.issuebot.github.Issue;
|
||||
import io.spring.issuebot.github.Label;
|
||||
import io.spring.issuebot.github.PullRequest;
|
||||
import io.spring.issuebot.github.StandardPage;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -44,25 +44,23 @@ public class QuestionIssueListenerTests {
|
||||
|
||||
private final IssueListener issueListener = mock(IssueListener.class);
|
||||
|
||||
private final IssueListener listener = new QuestionIssueListener(this.gitHub,
|
||||
"question", "Closing old question", Arrays.asList(this.issueListener));
|
||||
private final IssueListener listener = new QuestionIssueListener(this.gitHub, "question", "Closing old question",
|
||||
Arrays.asList(this.issueListener));
|
||||
|
||||
@Test
|
||||
public void nonQuestionsAreIgnored() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("foo")), null, new PullRequest("url"));
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("foo")), null,
|
||||
new PullRequest("url"));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verifyNoMoreInteractions(this.gitHub, this.issueListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void questionsLessThanSixMonthsAreIgnored() {
|
||||
Issue issue = new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("question")), null, null);
|
||||
Issue issue = new Issue(null, null, null, null, null, Arrays.asList(new Label("question")), null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now();
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("required"))), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verify(this.gitHub).getEvents(issue);
|
||||
verifyNoMoreInteractions(this.gitHub);
|
||||
@@ -70,12 +68,11 @@ public class QuestionIssueListenerTests {
|
||||
|
||||
@Test
|
||||
public void questionsOlderThanSixMonthsAreClosed() {
|
||||
Issue issue = new Issue("http://github/old/issue", null, null, null, null,
|
||||
Arrays.asList(new Label("question")), null, null);
|
||||
Issue issue = new Issue("http://github/old/issue", null, null, null, null, Arrays.asList(new Label("question")),
|
||||
null, null);
|
||||
OffsetDateTime requestTime = OffsetDateTime.now().minusMonths(7);
|
||||
given(this.gitHub.getEvents(issue)).willReturn(new StandardPage<>(
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("question"))),
|
||||
() -> null));
|
||||
Arrays.asList(new Event("labeled", requestTime, new Label("question"))), () -> null));
|
||||
this.listener.onOpenIssue(issue);
|
||||
verify(this.gitHub).addComment(issue, "Closing old question");
|
||||
verify(this.gitHub).close(issue);
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.spring.issuebot.triage;
|
||||
|
||||
import io.spring.issuebot.github.GitHubOperations;
|
||||
import io.spring.issuebot.github.Issue;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -32,8 +32,7 @@ public class LabelApplyingTriageListenerTests {
|
||||
|
||||
private GitHubOperations gitHub = mock(GitHubOperations.class);
|
||||
|
||||
private final LabelApplyingTriageListener listener = new LabelApplyingTriageListener(
|
||||
this.gitHub, "test");
|
||||
private final LabelApplyingTriageListener listener = new LabelApplyingTriageListener(this.gitHub, "test");
|
||||
|
||||
@Test
|
||||
public void requiresTriage() {
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.Collections;
|
||||
|
||||
import io.spring.issuebot.github.Issue;
|
||||
import io.spring.issuebot.github.Label;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -36,21 +36,19 @@ public class LabelledTriageFilterTests {
|
||||
|
||||
@Test
|
||||
public void issueWithLabels() {
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, null,
|
||||
Arrays.asList(new Label("test")), null, null))).isTrue();
|
||||
assertThat(this.filter
|
||||
.triaged(new Issue(null, null, null, null, null, Arrays.asList(new Label("test")), null, null))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issueWithNullLabels() {
|
||||
assertThat(this.filter
|
||||
.triaged(new Issue(null, null, null, null, null, null, null, null)))
|
||||
.isFalse();
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, null, null, null, null))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issueWithNoLabels() {
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, null,
|
||||
Collections.emptyList(), null, null))).isFalse();
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, null, Collections.emptyList(), null, null)))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.spring.issuebot.triage;
|
||||
|
||||
import io.spring.issuebot.github.Issue;
|
||||
import io.spring.issuebot.github.Milestone;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -34,15 +34,13 @@ public class MilestoneAppliedTriageFilterTests {
|
||||
|
||||
@Test
|
||||
public void issueWithMilestoneApplied() {
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, null, null,
|
||||
new Milestone("test"), null))).isTrue();
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, null, null, new Milestone("test"), null)))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issueWithNoMilestoneApplied() {
|
||||
assertThat(this.filter
|
||||
.triaged(new Issue(null, null, null, null, null, null, null, null)))
|
||||
.isFalse();
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, null, null, null, null))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Arrays;
|
||||
|
||||
import io.spring.issuebot.github.Issue;
|
||||
import io.spring.issuebot.github.User;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -31,21 +31,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class OpenedByCollaboratorTriageFilterTests {
|
||||
|
||||
private TriageFilter filter = new OpenedByCollaboratorTriageFilter(
|
||||
Arrays.asList("Adam", "Brenda", "Charlie"));
|
||||
private TriageFilter filter = new OpenedByCollaboratorTriageFilter(Arrays.asList("Adam", "Brenda", "Charlie"));
|
||||
|
||||
@Test
|
||||
public void openedByCollaborator() {
|
||||
assertThat(this.filter.triaged(
|
||||
new Issue(null, null, null, null, new User("Adam"), null, null, null)))
|
||||
.isTrue();
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, new User("Adam"), null, null, null))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openedByAnotherUser() {
|
||||
assertThat(this.filter.triaged(
|
||||
new Issue(null, null, null, null, new User("Debbie"), null, null, null)))
|
||||
.isFalse();
|
||||
assertThat(this.filter.triaged(new Issue(null, null, null, null, new User("Debbie"), null, null, null)))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Arrays;
|
||||
|
||||
import io.spring.issuebot.IssueListener;
|
||||
import io.spring.issuebot.github.Issue;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
Reference in New Issue
Block a user