diff --git a/pom.xml b/pom.xml index e4163b8..5e8c1f9 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,11 @@ 1.3 + + org.apache.httpcomponents + httpclient + + org.projectlombok lombok diff --git a/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java b/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java index 9008de4..f8f6eb3 100644 --- a/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java +++ b/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.release.model.Project; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.plugin.core.OrderAwarePluginRegistry; @@ -78,6 +79,7 @@ class IssueTrackerConfiguration { converters.add(converter); RestTemplate template = new RestTemplate(); + template.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); template.setMessageConverters(converters); return template; diff --git a/src/main/java/org/springframework/data/release/issues/github/GitHub.java b/src/main/java/org/springframework/data/release/issues/github/GitHub.java index 67e6a28..9dfc7d9 100644 --- a/src/main/java/org/springframework/data/release/issues/github/GitHub.java +++ b/src/main/java/org/springframework/data/release/issues/github/GitHub.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -159,7 +159,7 @@ class GitHub implements IssueTracker { return Changelog.of(moduleIteration, tickets); } - /* + /* * (non-Javadoc) * @see org.springframework.plugin.core.Plugin#supports(java.lang.Object) */ @@ -222,7 +222,7 @@ class GitHub implements IssueTracker { } /* - * + * * (non-Javadoc) * @see org.springframework.data.release.tracker.IssueTracker#createReleaseTicket(org.springframework.data.release.model.ModuleIteration) */ @@ -257,7 +257,6 @@ class GitHub implements IssueTracker { } /* - * * (non-Javadoc) * @see org.springframework.data.release.jira.IssueTracker#assignTicketToMe(org.springframework.data.release.jira.Ticket) */ @@ -266,15 +265,32 @@ class GitHub implements IssueTracker { logger.log("Ticket", "Skipping ticket assignment for %s", ticket); } - /* + /* * (non-Javadoc) * @see org.springframework.data.release.jira.IssueTracker#assignReleaseTicketToMe(org.springframework.data.release.model.ModuleIteration) */ @Override public Ticket assignReleaseTicketToMe(ModuleIteration module) { - logger.log("Ticket", "Skipping ticket assignment for %s", module); - return null; + Assert.notNull(module, "ModuleIteration must not be null."); + + Ticket releaseTicketFor = getReleaseTicketFor(module); + String repositoryName = GitProject.of(module.getProject()).getRepositoryName(); + + Map parameters = newUrlTemplateVariables(); + parameters.put("repoName", repositoryName); + parameters.put("id", stripHash(releaseTicketFor)); + + GitHubIssue edit = GitHubIssue.assignedTo(properties.getUsername()); + + GitHubIssue response = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.PATCH, + new HttpEntity<>(edit, newUserScopedHttpHeaders()), ISSUE_TYPE, parameters).getBody(); + + return toTicket(response); + } + + private String stripHash(Ticket ticket) { + return ticket.getId().startsWith("#") ? ticket.getId().substring(1) : ticket.getId(); } private HttpHeaders newUserScopedHttpHeaders() { @@ -324,7 +340,7 @@ class GitHub implements IssueTracker { return Optional.empty(); } - /* + /* * (non-Javadoc) * @see org.springframework.data.release.issues.IssueTracker#closeIteration(org.springframework.data.release.model.ModuleIteration) */ diff --git a/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java b/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java index a5a8526..42b5fa9 100644 --- a/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java +++ b/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,11 @@ package org.springframework.data.release.issues.github; import lombok.RequiredArgsConstructor; import lombok.Value; +import java.util.Collections; +import java.util.List; + import org.springframework.data.release.model.ModuleIteration; +import org.springframework.util.Assert; /** * @author Oliver Gierke @@ -29,10 +33,17 @@ import org.springframework.data.release.model.ModuleIteration; class GitHubIssue { String number, title, state; + List assignees; Object milestone; public static GitHubIssue of(String title, Milestone milestone) { - return new GitHubIssue(null, title, null, milestone.number); + return new GitHubIssue(null, title, null, null, milestone.number); + } + + public static GitHubIssue assignedTo(String username) { + + Assert.hasText(username, "Username must not be null or empty!"); + return new GitHubIssue(null, null, null, Collections.singletonList(username), null); } public String getId() { diff --git a/src/test/java/org/springframework/data/release/issues/github/GitHubIssueTrackerIntegrationTests.java b/src/test/java/org/springframework/data/release/issues/github/GitHubIssueTrackerIntegrationTests.java index 1fbcbf0..6f1bee5 100644 --- a/src/test/java/org/springframework/data/release/issues/github/GitHubIssueTrackerIntegrationTests.java +++ b/src/test/java/org/springframework/data/release/issues/github/GitHubIssueTrackerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.release.issues.github; import static com.github.tomakehurst.wiremock.client.WireMock.*; @@ -33,8 +32,6 @@ import org.junit.rules.ExpectedException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.release.AbstractIntegrationTests; import org.springframework.data.release.issues.Ticket; -import org.springframework.data.release.issues.github.GitHub; -import org.springframework.data.release.issues.github.GitHubProperties; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Projects; @@ -50,12 +47,13 @@ import com.github.tomakehurst.wiremock.junit.WireMockRule; /** * Integration Tests for {@link GitHub} using a local {@link WireMockRule} server. - * + * * @author Mark Paluch */ public class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests { public static final String ISSUES_URI = "/repos/spring-projects/spring-data-build/issues"; + public static final String RELEASE_TICKET_URI = "/repos/spring-projects/spring-data-build/issues/233"; public static final String MILESTONES_URI = "/repos/spring-projects/spring-data-build/milestones"; public static final ModuleIteration BUILD_HOPPER_RC1 = ReleaseTrains.HOPPER.getModuleIteration(Iteration.RC1, "Build"); @@ -75,7 +73,6 @@ public class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests Assume.assumeThat(uriComponents.getHost(), is("localhost")); github.reset(); - } /** @@ -216,6 +213,24 @@ public class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests verify(0, postRequestedFor(urlPathMatching(MILESTONES_URI))); } + /** + * @see #55 + */ + @Test + public void assignTicketToMe() { + + mockGetMilestonesWith("milestones.json"); + mockGetIssuesWith("issues.json"); + + mockService.stubFor(patch(urlPathMatching(RELEASE_TICKET_URI)).// + willReturn(json("issue.json"))); + + github.assignReleaseTicketToMe(BUILD_HOPPER_RC1); + + verify(patchRequestedFor(urlPathMatching(RELEASE_TICKET_URI)) + .withRequestBody(equalToJson("{\"assignees\":[\"mp911de\"]}"))); + } + private void mockGetIssueWith(String fromClassPath, int issueId) { mockService.stubFor(get(urlPathMatching(ISSUES_URI + "/" + issueId)).// willReturn(json(fromClassPath)));