From 5451682c64dbcb39e42c5e355467c8760f7f4ff9 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 5 Apr 2016 18:35:31 +0200 Subject: [PATCH] #5 - Polishing. Refactored issue tracker implementation into dedicated packages. Removed package tangles by moving some types around. Extracted GitHub specific properties into its own properties type reusing the Git credentials as we're talking to GitHub anyway. Added Jackson parameter name module and enabled Java 8 parameter names to be able to get rid of the manually declared constructors for payload classes. Turned them into value objects where possible. Original pull request: #14. --- release-tools/pom.xml | 15 ++ .../data/release/build/BuildCommands.java | 54 +++++ .../data/release/build/BuildOperations.java | 5 +- .../data/release/build/BuildSystem.java | 32 ++- .../data/release/build/GradleBuildSystem.java | 3 +- .../data/release/build/MavenBuildSystem.java | 3 +- .../data/release/build/PomUpdater.java | 3 +- .../{model => build}/UpdateInformation.java | 24 +- .../data/release/git/Commit.java | 4 +- .../data/release/git/GitCommands.java | 12 +- .../data/release/git/GitOperations.java | 24 +- .../data/release/git/GitProperties.java | 4 - .../release/{jira => git}/TicketBranches.java | 8 +- .../data/release/io/WorkspaceCommands.java | 17 -- .../release/{jira => issues}/Changelog.java | 13 +- .../{jira => issues}/IssueTracker.java | 46 +++- .../{cli => issues}/IssueTrackerCommands.java | 84 ++++--- .../IssueTrackerConfiguration.java | 63 +++-- .../data/release/{jira => issues}/Ticket.java | 38 +++- .../{jira => issues}/TicketStatus.java | 12 +- .../release/{jira => issues}/Tickets.java | 47 +++- .../github/GitHub.java} | 215 ++++++++++-------- .../release/issues/github/GitHubIssue.java | 60 +++++ .../github}/GitHubMilestone.java | 25 +- .../issues/github/GitHubProperties.java | 57 +++++ .../github}/GithubTicketStatus.java | 23 +- .../{ => issues}/jira/CreatedJiraIssue.java | 16 +- .../{ => issues}/jira/Credentials.java | 12 +- .../data/release/{ => issues}/jira/Jira.java | 141 +++++++----- .../{ => issues}/jira/JiraComponent.java | 18 +- .../{ => issues}/jira/JiraComponents.java | 31 ++- .../{ => issues}/jira/JiraConnector.java | 24 +- .../release/{ => issues}/jira/JiraIssue.java | 156 ++++++------- .../release/{ => issues}/jira/JiraIssues.java | 24 +- .../{ => issues}/jira/JiraProperties.java | 17 +- .../{ => issues}/jira/JiraReleaseVersion.java | 32 +-- .../jira/JiraReleaseVersions.java | 16 +- .../{ => issues}/jira/JiraTicketStatus.java | 20 +- .../{ => issues}/jira/JiraVersion.java | 14 +- .../release/{ => issues}/jira/JqlQuery.java | 37 ++- .../data/release/jira/GitHubIssue.java | 91 -------- .../data/release/misc/ReleaseOperations.java | 4 +- .../data/release/utils/ExecutionUtils.java | 11 +- .../src/main/resources/application.properties | 10 +- .../release/build/MavenIntegrationTests.java | 3 +- .../UpdateInformationUnitTests.java | 21 +- .../GitHubIssueTrackerIntegrationTests.java | 18 +- .../github}/GithubMilestoneUnitTests.java | 3 +- .../jira/JiraComponentsUnitTests.java | 4 +- .../jira/JiraConnectorIntegrationTests.java} | 17 +- .../jira/JiraVersionUnitTests.java | 3 +- .../{ => issues}/jira/TicketsUnitTests.java | 6 +- .../resources/application-test.properties | 5 +- 53 files changed, 966 insertions(+), 679 deletions(-) create mode 100644 release-tools/src/main/java/org/springframework/data/release/build/BuildCommands.java rename release-tools/src/main/java/org/springframework/data/release/{model => build}/UpdateInformation.java (71%) rename release-tools/src/main/java/org/springframework/data/release/{jira => git}/TicketBranches.java (93%) rename release-tools/src/main/java/org/springframework/data/release/{jira => issues}/Changelog.java (91%) rename release-tools/src/main/java/org/springframework/data/release/{jira => issues}/IssueTracker.java (65%) rename release-tools/src/main/java/org/springframework/data/release/{cli => issues}/IssueTrackerCommands.java (63%) rename release-tools/src/main/java/org/springframework/data/release/{jira => issues}/IssueTrackerConfiguration.java (58%) rename release-tools/src/main/java/org/springframework/data/release/{jira => issues}/Ticket.java (54%) rename release-tools/src/main/java/org/springframework/data/release/{jira => issues}/TicketStatus.java (81%) rename release-tools/src/main/java/org/springframework/data/release/{jira => issues}/Tickets.java (84%) rename release-tools/src/main/java/org/springframework/data/release/{jira/GitHubIssueTracker.java => issues/github/GitHub.java} (73%) create mode 100644 release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java rename release-tools/src/main/java/org/springframework/data/release/{jira => issues/github}/GitHubMilestone.java (80%) create mode 100644 release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubProperties.java rename release-tools/src/main/java/org/springframework/data/release/{jira => issues/github}/GithubTicketStatus.java (60%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/CreatedJiraIssue.java (77%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/Credentials.java (82%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/Jira.java (86%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraComponent.java (70%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraComponents.java (71%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraConnector.java (76%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraIssue.java (77%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraIssues.java (75%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraProperties.java (88%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraReleaseVersion.java (55%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraReleaseVersions.java (85%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraTicketStatus.java (70%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JiraVersion.java (81%) rename release-tools/src/main/java/org/springframework/data/release/{ => issues}/jira/JqlQuery.java (83%) delete mode 100644 release-tools/src/main/java/org/springframework/data/release/jira/GitHubIssue.java rename release-tools/src/test/java/org/springframework/data/release/{model => build}/UpdateInformationUnitTests.java (66%) rename release-tools/src/test/java/org/springframework/data/release/{jira => issues/github}/GitHubIssueTrackerIntegrationTests.java (90%) rename release-tools/src/test/java/org/springframework/data/release/{jira => issues/github}/GithubMilestoneUnitTests.java (95%) rename release-tools/src/test/java/org/springframework/data/release/{ => issues}/jira/JiraComponentsUnitTests.java (90%) rename release-tools/src/test/java/org/springframework/data/release/{jira/JiraIntegrationTests.java => issues/jira/JiraConnectorIntegrationTests.java} (92%) rename release-tools/src/test/java/org/springframework/data/release/{ => issues}/jira/JiraVersionUnitTests.java (95%) rename release-tools/src/test/java/org/springframework/data/release/{ => issues}/jira/TicketsUnitTests.java (93%) diff --git a/release-tools/pom.xml b/release-tools/pom.xml index 65ea289..a907794 100644 --- a/release-tools/pom.xml +++ b/release-tools/pom.xml @@ -39,6 +39,11 @@ jackson-databind + + com.fasterxml.jackson.module + jackson-module-parameter-names + + joda-time joda-time @@ -137,6 +142,16 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + -parameters + + + diff --git a/release-tools/src/main/java/org/springframework/data/release/build/BuildCommands.java b/release-tools/src/main/java/org/springframework/data/release/build/BuildCommands.java new file mode 100644 index 0000000..4a25bcf --- /dev/null +++ b/release-tools/src/main/java/org/springframework/data/release/build/BuildCommands.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.release.build; + +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.release.CliComponent; +import org.springframework.data.release.io.Workspace; +import org.springframework.data.release.utils.Logger; +import org.springframework.shell.core.annotation.CliCommand; + +/** + * @author Oliver Gierke + */ +@CliComponent +@RequiredArgsConstructor(onConstructor = @__(@Autowired) ) +public class BuildCommands { + + private final @NonNull BuildOperations build; + private final @NonNull Workspace workspace; + private final @NonNull Logger logger; + + /** + * Removes all Spring Data artifacts from the local repository. + * + * @throws IOException + */ + @CliCommand("workspace purge artifacts") + public void purge() throws IOException { + + logger.log("Workspace", "Cleaning up workspace directory at %s.", + workspace.getWorkingDirectory().getAbsolutePath()); + + workspace.purge(build.getLocalRepository(), + path -> build.getLocalRepository().relativize(path).startsWith("org/springframework/data")); + } +} diff --git a/release-tools/src/main/java/org/springframework/data/release/build/BuildOperations.java b/release-tools/src/main/java/org/springframework/data/release/build/BuildOperations.java index 075bc1c..76ac831 100644 --- a/release-tools/src/main/java/org/springframework/data/release/build/BuildOperations.java +++ b/release-tools/src/main/java/org/springframework/data/release/build/BuildOperations.java @@ -28,7 +28,6 @@ import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.TrainIteration; -import org.springframework.data.release.model.UpdateInformation; import org.springframework.plugin.core.PluginRegistry; import org.springframework.plugin.core.PluginRegistry.Supplier; import org.springframework.stereotype.Component; @@ -56,13 +55,13 @@ public class BuildOperations { Assert.notNull(iteration, "Train iteration must not be null!"); Assert.notNull(phase, "Phase must not be null!"); - UpdateInformation updateInformation = new UpdateInformation(iteration, phase); + UpdateInformation updateInformation = UpdateInformation.of(iteration, phase); doWithBuildSystem(iteration, (system, it) -> system.updateProjectDescriptors(it, updateInformation)); } /** - * Triggers the distribution builds for all modules particitpating in the given {@link TrainIteration}. + * Triggers the distribution builds for all modules participating in the given {@link TrainIteration}. * * @param iteration must not be {@literal null}. */ diff --git a/release-tools/src/main/java/org/springframework/data/release/build/BuildSystem.java b/release-tools/src/main/java/org/springframework/data/release/build/BuildSystem.java index 133d56e..649143b 100644 --- a/release-tools/src/main/java/org/springframework/data/release/build/BuildSystem.java +++ b/release-tools/src/main/java/org/springframework/data/release/build/BuildSystem.java @@ -19,7 +19,6 @@ import org.springframework.data.release.deployment.DeploymentInformation; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Project; -import org.springframework.data.release.model.UpdateInformation; import org.springframework.plugin.core.Plugin; /** @@ -30,16 +29,35 @@ import org.springframework.plugin.core.Plugin; interface BuildSystem extends Plugin { /** - * @param iteration - * @param train - * @param phase - * @throws Exception + * Updates the project descriptors for the given {@link ModuleIteration} using the given {@link UpdateInformation}. + * + * @param iteration must not be {@literal null}. + * @param updateInformation must not be {@literal null}. */ ModuleIteration updateProjectDescriptors(ModuleIteration iteration, UpdateInformation updateInformation); + /** + * Prepares the project descriptor of the {@link ModuleIteration} for the given release {@link Phase}. + * + * @param module must not be {@literal null}. + * @param phase must not be {@literal null}. + * @return + */ ModuleIteration prepareVersion(ModuleIteration module, Phase phase); - ModuleIteration triggerDistributionBuild(ModuleIteration module); - + /** + * Deploy artifacts for the given {@link ModuleIteration} and return the {@link DeploymentInformation}. + * + * @param module must not be {@literal null}. + * @return + */ DeploymentInformation deploy(ModuleIteration module); + + /** + * Runs the distribution build. + * + * @param module must not be {@literal null}. + * @return + */ + ModuleIteration triggerDistributionBuild(ModuleIteration module); } diff --git a/release-tools/src/main/java/org/springframework/data/release/build/GradleBuildSystem.java b/release-tools/src/main/java/org/springframework/data/release/build/GradleBuildSystem.java index 42ebb6c..19acb64 100644 --- a/release-tools/src/main/java/org/springframework/data/release/build/GradleBuildSystem.java +++ b/release-tools/src/main/java/org/springframework/data/release/build/GradleBuildSystem.java @@ -29,7 +29,6 @@ import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.TrainIteration; -import org.springframework.data.release.model.UpdateInformation; import org.springframework.data.release.utils.Logger; import org.springframework.stereotype.Component; @@ -61,7 +60,7 @@ class GradleBuildSystem implements BuildSystem { */ public void updateProject(TrainIteration iteration, final Phase phase) throws Exception { - UpdateInformation updateInformation = new UpdateInformation(iteration, phase); + UpdateInformation updateInformation = UpdateInformation.of(iteration, phase); for (ModuleIteration module : iteration.getModulesExcept(BUILD)) { updateProjectDescriptors(module, updateInformation); diff --git a/release-tools/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java b/release-tools/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java index c798061..eb1524f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java +++ b/release-tools/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java @@ -36,7 +36,6 @@ import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.Train; import org.springframework.data.release.model.TrainIteration; -import org.springframework.data.release.model.UpdateInformation; import org.springframework.data.release.utils.ExecutionUtils; import org.springframework.data.release.utils.Logger; import org.springframework.stereotype.Component; @@ -218,7 +217,7 @@ class MavenBuildSystem implements BuildSystem { public ModuleIteration prepareVersion(ModuleIteration module, Phase phase) { Project project = module.getProject(); - UpdateInformation information = new UpdateInformation(module.getTrainIteration(), phase); + UpdateInformation information = UpdateInformation.of(module.getTrainIteration(), phase); mvn.execute(project, "versions:set", "versions:commit", "-DnewVersion=".concat(information.getProjectVersionToSet(project).toString())); diff --git a/release-tools/src/main/java/org/springframework/data/release/build/PomUpdater.java b/release-tools/src/main/java/org/springframework/data/release/build/PomUpdater.java index 56e2e04..b50c17d 100644 --- a/release-tools/src/main/java/org/springframework/data/release/build/PomUpdater.java +++ b/release-tools/src/main/java/org/springframework/data/release/build/PomUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2016 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. @@ -23,7 +23,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.Project; -import org.springframework.data.release.model.UpdateInformation; import org.springframework.data.release.utils.Logger; import org.springframework.util.Assert; diff --git a/release-tools/src/main/java/org/springframework/data/release/model/UpdateInformation.java b/release-tools/src/main/java/org/springframework/data/release/build/UpdateInformation.java similarity index 71% rename from release-tools/src/main/java/org/springframework/data/release/model/UpdateInformation.java rename to release-tools/src/main/java/org/springframework/data/release/build/UpdateInformation.java index 0e40d90..135fa94 100644 --- a/release-tools/src/main/java/org/springframework/data/release/model/UpdateInformation.java +++ b/release-tools/src/main/java/org/springframework/data/release/build/UpdateInformation.java @@ -1,4 +1,19 @@ -package org.springframework.data.release.model; +/* + * Copyright 2015-2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.release.build; import static org.springframework.data.release.model.Projects.*; @@ -6,7 +21,10 @@ import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import org.springframework.data.release.build.Repository; +import org.springframework.data.release.model.ArtifactVersion; +import org.springframework.data.release.model.Phase; +import org.springframework.data.release.model.Project; +import org.springframework.data.release.model.TrainIteration; import org.springframework.util.Assert; /** @@ -14,7 +32,7 @@ import org.springframework.util.Assert; * * @author Oliver Gierke */ -@RequiredArgsConstructor +@RequiredArgsConstructor(staticName = "of") public class UpdateInformation { private final @NonNull @Getter TrainIteration iteration; diff --git a/release-tools/src/main/java/org/springframework/data/release/git/Commit.java b/release-tools/src/main/java/org/springframework/data/release/git/Commit.java index b063881..7706954 100644 --- a/release-tools/src/main/java/org/springframework/data/release/git/Commit.java +++ b/release-tools/src/main/java/org/springframework/data/release/git/Commit.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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. @@ -20,7 +20,7 @@ import lombok.RequiredArgsConstructor; import java.util.Optional; -import org.springframework.data.release.jira.Ticket; +import org.springframework.data.release.issues.Ticket; /** * @author Oliver Gierke diff --git a/release-tools/src/main/java/org/springframework/data/release/git/GitCommands.java b/release-tools/src/main/java/org/springframework/data/release/git/GitCommands.java index 56ce187..c5efbde 100644 --- a/release-tools/src/main/java/org/springframework/data/release/git/GitCommands.java +++ b/release-tools/src/main/java/org/springframework/data/release/git/GitCommands.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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. @@ -24,8 +24,7 @@ import java.util.stream.Stream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.release.CliComponent; -import org.springframework.data.release.jira.Ticket; -import org.springframework.data.release.jira.TicketBranches; +import org.springframework.data.release.issues.Ticket; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.ReleaseTrains; import org.springframework.data.release.model.Train; @@ -118,8 +117,9 @@ public class GitCommands implements CommandMarker { public void backportChangelogs(@CliOption(key = "", mandatory = true) TrainIteration iteration, // @CliOption(key = "target", mandatory = true) String trains) { - List targets = Stream.of(trains.split(",")).map(it -> ReleaseTrains.getTrainByName(it)) - .collect(Collectors.toList()); + List targets = Stream.of(trains.split(",")).// + map(it -> ReleaseTrains.getTrainByName(it)).// + collect(Collectors.toList()); git.backportChangelogs(iteration, targets); } @@ -149,7 +149,7 @@ public class GitCommands implements CommandMarker { filter(branch -> ticketBranches.hasTicketFor(branch, resolved)).// forEachOrdered(branch -> { - Optional ticket = ticketBranches.getTicket(branch); + Optional ticket = ticketBranches.findTicket(branch); table.addRow(branch.toString(), // ticket.map(t -> t.getTicketStatus().getLabel()).orElse(""), // diff --git a/release-tools/src/main/java/org/springframework/data/release/git/GitOperations.java b/release-tools/src/main/java/org/springframework/data/release/git/GitOperations.java index 410e927..46f8d0c 100644 --- a/release-tools/src/main/java/org/springframework/data/release/git/GitOperations.java +++ b/release-tools/src/main/java/org/springframework/data/release/git/GitOperations.java @@ -15,7 +15,9 @@ */ package org.springframework.data.release.git; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; import java.io.File; import java.io.IOException; @@ -41,9 +43,8 @@ import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.TagOpt; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.release.io.Workspace; -import org.springframework.data.release.jira.IssueTracker; -import org.springframework.data.release.jira.Ticket; -import org.springframework.data.release.jira.TicketBranches; +import org.springframework.data.release.issues.IssueTracker; +import org.springframework.data.release.issues.Ticket; import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; @@ -62,13 +63,14 @@ import org.springframework.util.Assert; */ @Component @RequiredArgsConstructor(onConstructor = @__(@Autowired) ) +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class GitOperations { - private final GitServer server = new GitServer(); - private final Workspace workspace; - private final Logger logger; - private final PluginRegistry issueTracker; - private final GitProperties gitProperties; + GitServer server = new GitServer(); + Workspace workspace; + Logger logger; + PluginRegistry issueTracker; + GitProperties gitProperties; /** * Returns the {@link GitProject} for the given {@link Project}. @@ -297,8 +299,8 @@ public class GitOperations { Collection tickets = tracker.findTickets(project, ticketIds.keySet()); - return TicketBranches.from(tickets.stream() - .collect(Collectors.toMap(ticket -> ticketIds.get(ticket.getId()), ticket -> ticket))); + return TicketBranches + .from(tickets.stream().collect(Collectors.toMap(ticket -> ticketIds.get(ticket.getId()), ticket -> ticket))); }); } @@ -659,12 +661,10 @@ public class GitOperations { } private static interface GitCallback { - T doWithGit(Git git) throws Exception; } private static interface VoidGitCallback { - void doWithGit(Git git) throws Exception; } } diff --git a/release-tools/src/main/java/org/springframework/data/release/git/GitProperties.java b/release-tools/src/main/java/org/springframework/data/release/git/GitProperties.java index 3a96fa2..576472a 100644 --- a/release-tools/src/main/java/org/springframework/data/release/git/GitProperties.java +++ b/release-tools/src/main/java/org/springframework/data/release/git/GitProperties.java @@ -23,7 +23,6 @@ import javax.annotation.PostConstruct; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.data.release.utils.HttpBasicCredentials; import org.springframework.stereotype.Component; @@ -43,8 +42,6 @@ public class GitProperties { private @Getter(AccessLevel.PRIVATE) String password; private String username, author, email; - @Value("${github.api.url}") private String githubApiBaseUrl; - @PostConstruct public void init() { @@ -52,7 +49,6 @@ public class GitProperties { Assert.hasText(password, "No GitHub password (git.password) configured!"); Assert.hasText(author, "No Git author (git.author) configured!"); Assert.hasText(email, "No Git email (git.email) configured!"); - Assert.hasText(githubApiBaseUrl, "No GitHub API base url configured!"); } /** diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/TicketBranches.java b/release-tools/src/main/java/org/springframework/data/release/git/TicketBranches.java similarity index 93% rename from release-tools/src/main/java/org/springframework/data/release/jira/TicketBranches.java rename to release-tools/src/main/java/org/springframework/data/release/git/TicketBranches.java index 36c8fe0..d84af9f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/TicketBranches.java +++ b/release-tools/src/main/java/org/springframework/data/release/git/TicketBranches.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.git; import java.util.Iterator; import java.util.Map; @@ -22,7 +22,7 @@ import java.util.Optional; import java.util.stream.Collectors; import org.springframework.data.release.Streamable; -import org.springframework.data.release.git.Branch; +import org.springframework.data.release.issues.Ticket; import org.springframework.util.Assert; import lombok.EqualsAndHashCode; @@ -53,7 +53,7 @@ public class TicketBranches implements Streamable { Assert.notNull(branch, "Branch must not be null!"); - return getTicket(branch).// + return findTicket(branch).// map(ticket -> requireResolved ? ticket.getTicketStatus().isResolved() : true).// orElse(false); } @@ -76,7 +76,7 @@ public class TicketBranches implements Streamable { * @param branch must not be {@literal null}. * @return */ - public Optional getTicket(Branch branch) { + public Optional findTicket(Branch branch) { Assert.notNull(branch, "Branch must not be null!"); return Optional.ofNullable(ticketBranches.get(branch)); diff --git a/release-tools/src/main/java/org/springframework/data/release/io/WorkspaceCommands.java b/release-tools/src/main/java/org/springframework/data/release/io/WorkspaceCommands.java index e4c49f8..12425fa 100644 --- a/release-tools/src/main/java/org/springframework/data/release/io/WorkspaceCommands.java +++ b/release-tools/src/main/java/org/springframework/data/release/io/WorkspaceCommands.java @@ -21,7 +21,6 @@ import java.io.IOException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.release.CliComponent; -import org.springframework.data.release.build.BuildOperations; import org.springframework.data.release.utils.Logger; import org.springframework.shell.core.CommandMarker; import org.springframework.shell.core.annotation.CliCommand; @@ -34,7 +33,6 @@ import org.springframework.shell.core.annotation.CliCommand; public class WorkspaceCommands implements CommandMarker { private final Workspace workspace; - private final BuildOperations build; private final Logger logger; @CliCommand("workspace cleanup") @@ -45,19 +43,4 @@ public class WorkspaceCommands implements CommandMarker { workspace.cleanup(); } - - /** - * Removes all Spring Data artifacts from the local repository. - * - * @throws IOException - */ - @CliCommand("workspace purge artifacts") - public void purge() throws IOException { - - logger.log("Workspace", "Cleaning up workspace directory at %s.", - workspace.getWorkingDirectory().getAbsolutePath()); - - workspace.purge(build.getLocalRepository(), - path -> build.getLocalRepository().relativize(path).startsWith("org/springframework/data")); - } } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/Changelog.java b/release-tools/src/main/java/org/springframework/data/release/issues/Changelog.java similarity index 91% rename from release-tools/src/main/java/org/springframework/data/release/jira/Changelog.java rename to release-tools/src/main/java/org/springframework/data/release/issues/Changelog.java index 5c28990..61336ca 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/Changelog.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/Changelog.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; import java.util.Date; import java.util.Locale; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; - import org.springframework.data.release.model.ArtifactVersion; import org.springframework.data.release.model.ModuleIteration; import org.springframework.format.datetime.DateFormatter; @@ -30,7 +29,7 @@ import org.springframework.shell.support.util.OsUtils; /** * @author Oliver Gierke */ -@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +@RequiredArgsConstructor(staticName = "of") @EqualsAndHashCode public class Changelog { diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/IssueTracker.java b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTracker.java similarity index 65% rename from release-tools/src/main/java/org/springframework/data/release/jira/IssueTracker.java rename to release-tools/src/main/java/org/springframework/data/release/issues/IssueTracker.java index 58b311a..344127f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/IssueTracker.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTracker.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues; import java.util.Collection; @@ -25,13 +25,15 @@ import org.springframework.data.release.model.TrainIteration; import org.springframework.plugin.core.Plugin; /** + * Interface for issue tracker operations. + * * @author Oliver Gierke * @author Mark Paluch */ public interface IssueTracker extends Plugin { /** - * Reset internal state (cache, ...). + * Reset internal state (cache, etc). */ void reset(); @@ -55,7 +57,7 @@ public interface IssueTracker extends Plugin { /** * Returns the {@link Ticket} that tracks modifications in the context of a release. * - * @param module the module to lookup the {@link Ticket} for. + * @param module the module to lookup the {@link Ticket} for, must not be {@literal null}. * @return */ Ticket getReleaseTicketFor(ModuleIteration module); @@ -64,8 +66,8 @@ public interface IssueTracker extends Plugin { * Query the issue tracker for multiple {@link Ticket#id ticket Ids}. Tickets that are not found are not returned * within the result. * - * @param project - * @param ticketIds collection of {@link Ticket#id ticket Ids} + * @param project must not be {@literal null}. + * @param ticketIds collection of {@link Ticket#id ticket Ids}, must not be {@literal null}. * @return */ Collection findTickets(Project project, Collection ticketIds); @@ -73,18 +75,40 @@ public interface IssueTracker extends Plugin { /** * Creates a release version if release version is missing. * - * @param moduleIteration must not be {@literal null}. - * @param credentials must not be {@literal null}. + * @param module must not be {@literal null}. */ - void createReleaseVersion(ModuleIteration moduleIteration); + void createReleaseVersion(ModuleIteration module); /** * Create release ticket if release ticket is missing. + *

+ * TODO: Return created ticket * - * @param iteration must not be {@literal null}. + * @param module must not be {@literal null}. + */ + void createReleaseTicket(ModuleIteration module); + + /** + * Assigns the ticket to the current user. + * + * @param ticket must not be {@literal null}. * @param credentials must not be {@literal null}. */ - void createReleaseTicket(ModuleIteration moduleIteration); + void assignTicketToMe(Ticket ticket); - Changelog getChangelogFor(ModuleIteration iteration); + /** + * Assigns the release ticket for the given {@link ModuleIteration} to the current user. + * + * @param module must not be {@literal null}. + * @return + */ + Ticket assignReleaseTicketToMe(ModuleIteration module); + + /** + * Returns the {@link Changelog} for the given {@link ModuleIteration}. + * + * @param module must not be {@literal null}. + * @return + */ + Changelog getChangelogFor(ModuleIteration module); } diff --git a/release-tools/src/main/java/org/springframework/data/release/cli/IssueTrackerCommands.java b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerCommands.java similarity index 63% rename from release-tools/src/main/java/org/springframework/data/release/cli/IssueTrackerCommands.java rename to release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerCommands.java index 6e19e5b..d702f7f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/cli/IssueTrackerCommands.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerCommands.java @@ -13,17 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.cli; +package org.springframework.data.release.issues; +import static org.springframework.data.release.utils.ExecutionUtils.*; + +import lombok.AccessLevel; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.experimental.FieldDefaults; + +import java.util.function.BiFunction; import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.stream.StreamSupport; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.release.CliComponent; -import org.springframework.data.release.jira.Changelog; -import org.springframework.data.release.jira.IssueTracker; -import org.springframework.data.release.jira.JiraConnector; -import org.springframework.data.release.jira.Tickets; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.TrainIteration; @@ -39,56 +44,38 @@ import org.springframework.util.StringUtils; * @author Mark Paluch */ @CliComponent +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +@RequiredArgsConstructor(onConstructor = @__(@Autowired) ) public class IssueTrackerCommands implements CommandMarker { - private final PluginRegistry tracker; - private final JiraConnector jira; - - /** - * @param tracker must not be {@literal null}. - * @param jira must not be {@literal null}. - * @param environment must not be {@literal null}. - */ - @Autowired - public IssueTrackerCommands(PluginRegistry tracker, JiraConnector jira) { - - this.tracker = tracker; - this.jira = jira; - } + @NonNull PluginRegistry tracker; @CliCommand("tracker evict") public void evict() { StreamSupport.stream(tracker.spliterator(), false).forEach(IssueTracker::reset); } - @CliCommand(value = "jira tickets") + @CliCommand(value = "tracker tickets") public String jira(@CliOption(key = "", mandatory = true) TrainIteration iteration, // @CliOption(key = "for-current-user", specifiedDefaultValue = "true", unspecifiedDefaultValue = "false") boolean forCurrentUser) { - Tickets tickets = StreamSupport.stream(tracker.spliterator(), false). // - flatMap(issueTracker -> issueTracker. // - getTicketsFor(iteration, forCurrentUser).stream()) - . // - collect(Tickets.toTicketsCollector()); - return tickets.toString(); + return tracker.getPlugins().stream().// + flatMap(it -> it.getTicketsFor(iteration, forCurrentUser).stream()).// + collect(Tickets.toTicketsCollector()).toString(); } @CliCommand(value = "tracker releasetickets") public String releaseTickets(@CliOption(key = "", mandatory = true) TrainIteration iteration) { - - Tickets tickets = StreamSupport.stream(tracker.spliterator(), false). // - flatMap(issueTracker -> issueTracker.getTicketsFor(iteration).stream()). // - collect(Tickets.toTicketsCollector()); - return tickets.getReleaseTickets(iteration).toString(); + return runAndReturn(iteration, module -> getTrackerFor(module).getReleaseTicketFor(module), + Tickets.toTicketsCollector()).toString(); } - @CliCommand(value = "jira self-assign releasetickets") + @CliCommand(value = "tracker self-assign releasetickets") public String jiraSelfAssignReleaseTickets(@CliOption(key = "", mandatory = true) TrainIteration iteration) { - Tickets releaseTickets = jira.getTicketsFor(iteration).getReleaseTickets(iteration); - releaseTickets.forEach(ticket -> jira.assignTicketToMe(ticket)); - return releaseTickets(iteration); + return runAndReturn(iteration, module -> getTrackerFor(module).assignReleaseTicketToMe(module), + Tickets.toTicketsCollector()).toString(); } @CliCommand(value = "tracker create releaseversions") @@ -99,21 +86,14 @@ public class IssueTrackerCommands implements CommandMarker { @CliCommand(value = "tracker create releasetickets") public String createReleaseTickets(@CliOption(key = "", mandatory = true) TrainIteration iteration) { - iteration.forEach(this::createReleaseVersion); + iteration.stream().// + forEach(module -> getTrackerFor(module).createReleaseTicket(module)); evict(); return releaseTickets(iteration); } - private void createReleaseVersion(ModuleIteration moduleIteration) { - getPluginFor(moduleIteration).createReleaseVersion(moduleIteration); - } - - private IssueTracker getPluginFor(ModuleIteration moduleIteration) { - return tracker.getPluginFor(moduleIteration.getProject()); - } - @CliCommand("tracker changelog") public String changelog(@CliOption(key = "", mandatory = true) TrainIteration iteration, // @CliOption(key = "module") String moduleName) { @@ -121,7 +101,7 @@ public class IssueTrackerCommands implements CommandMarker { if (StringUtils.hasText(moduleName)) { ModuleIteration module = iteration.getModule(moduleName); - return tracker.getPluginFor(module.getProject()).getChangelogFor(module).toString(); + return getTrackerFor(module).getChangelogFor(module).toString(); } return ExecutionUtils.runAndReturn(iteration, this::getChangelog).// @@ -129,6 +109,18 @@ public class IssueTrackerCommands implements CommandMarker { } private Changelog getChangelog(ModuleIteration module) { - return tracker.getPluginFor(module.getProject()).getChangelogFor(module); + return getTrackerFor(module).getChangelogFor(module); + } + + private void createReleaseVersion(ModuleIteration moduleIteration) { + getTrackerFor(moduleIteration).createReleaseVersion(moduleIteration); + } + + private Stream doWithBuildSystem(TrainIteration train, BiFunction function) { + return train.stream().map(module -> function.apply(getTrackerFor(module), module)); + } + + private IssueTracker getTrackerFor(ModuleIteration moduleIteration) { + return tracker.getPluginFor(moduleIteration.getProject()); } } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/IssueTrackerConfiguration.java b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java similarity index 58% rename from release-tools/src/main/java/org/springframework/data/release/jira/IssueTrackerConfiguration.java rename to release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java index 78f69b7..9008de4 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/IssueTrackerConfiguration.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/IssueTrackerConfiguration.java @@ -13,60 +13,63 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues; import java.util.ArrayList; import java.util.List; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.release.git.GitProperties; import org.springframework.data.release.model.Project; -import org.springframework.data.release.utils.Logger; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.plugin.core.OrderAwarePluginRegistry; import org.springframework.plugin.core.PluginRegistry; import org.springframework.web.client.RestTemplate; +import com.fasterxml.jackson.annotation.JsonCreator.Mode; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; +import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; /** * @author Oliver Gierke * @author Mark Paluch */ @Configuration -@EnableCaching +@EnableCaching(proxyTargetClass = true) class IssueTrackerConfiguration { @Bean - public CacheManager cacheManager() { + CacheManager cacheManager() { return new ConcurrentMapCacheManager(); } @Bean - public PluginRegistry issueTrackers(List plugins) { - return OrderAwarePluginRegistry.create(plugins); - } - - @Bean - public ObjectMapper jacksonObjectMapper() { + ObjectMapper jacksonObjectMapper() { ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setSerializationInclusion(Include.NON_NULL); + mapper.registerModule(new ParameterNamesModule(Mode.PROPERTIES)); + mapper.registerModule(new SyntheticLambdaFactoryMethodIgnoringModule()); return mapper; } @Bean - public RestTemplate restTemplate() { + @Qualifier("tracker") + RestTemplate restTemplate() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(jacksonObjectMapper()); @@ -81,12 +84,36 @@ class IssueTrackerConfiguration { } @Bean - public Jira jira(Logger logger, JiraProperties jiraProperties) { - return new Jira(restTemplate(), logger, jiraProperties); + PluginRegistry issueTrackers(List plugins) { + return OrderAwarePluginRegistry.create(plugins); } - @Bean - public GitHubIssueTracker github(Logger logger, GitProperties properties) { - return new GitHubIssueTracker(restTemplate(), logger, properties); + /** + * @author Oliver Gierke + */ + static class SyntheticLambdaFactoryMethodIgnoringModule extends SimpleModule { + + private static final long serialVersionUID = -3075786389813846512L; + + @Override + public void setupModule(SetupContext context) { + + context.insertAnnotationIntrospector(new NopAnnotationIntrospector() { + + private static final long serialVersionUID = 479313244908256455L; + + @Override + public boolean hasIgnoreMarker(AnnotatedMember m) { + + if (!(m instanceof AnnotatedMethod)) { + return super.hasIgnoreMarker(m); + } + + AnnotatedMethod method = (AnnotatedMethod) m; + + return method.getName().startsWith("lambda$") ? true : super.hasIgnoreMarker(m); + } + }); + } } } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/Ticket.java b/release-tools/src/main/java/org/springframework/data/release/issues/Ticket.java similarity index 54% rename from release-tools/src/main/java/org/springframework/data/release/jira/Ticket.java rename to release-tools/src/main/java/org/springframework/data/release/issues/Ticket.java index ed15a72..ccbbead 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/Ticket.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/Ticket.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues; + +import lombok.Value; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Tracker; import org.springframework.data.release.model.TrainIteration; - -import lombok.Value; +import org.springframework.util.Assert; /** * Value object to represent a {@link Ticket}. @@ -29,9 +30,8 @@ import lombok.Value; @Value public class Ticket { - private final String id; - private final String summary; - private final TicketStatus ticketStatus; + String id, summary; + TicketStatus ticketStatus; /* * (non-Javadoc) @@ -39,18 +39,32 @@ public class Ticket { */ @Override public String toString() { - return String.format("%13s - %s", id, summary); + return String.format("%14s - %s", id, summary); } public boolean isResolved() { return ticketStatus.isResolved(); } - public boolean isReleaseTicketFor(ModuleIteration moduleIteration) { - return summary.equals(Tracker.releaseTicketSummary(moduleIteration)); + /** + * Returns whether the current {@link Ticket} is the release ticket for the given {@link ModuleIteration}. + * + * @param module must not be {@literal null}. + * @return + */ + public boolean isReleaseTicketFor(ModuleIteration module) { + + Assert.notNull(module, "Module must not be null!"); + return summary.equals(Tracker.releaseTicketSummary(module)); } - public boolean isReleaseTicketFor(TrainIteration iteration) { - return iteration.stream().filter(this::isReleaseTicketFor).findFirst().isPresent(); + /** + * Returns whether the current {@link Ticket} is a release ticket for the given {@link TrainIteration}. + * + * @param train must not be {@literal null}. + * @return + */ + public boolean isReleaseTicketFor(TrainIteration train) { + return train.stream().anyMatch(this::isReleaseTicketFor); } } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/TicketStatus.java b/release-tools/src/main/java/org/springframework/data/release/issues/TicketStatus.java similarity index 81% rename from release-tools/src/main/java/org/springframework/data/release/jira/TicketStatus.java rename to release-tools/src/main/java/org/springframework/data/release/issues/TicketStatus.java index 081a122..90dabcc 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/TicketStatus.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/TicketStatus.java @@ -14,14 +14,24 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues; /** * @author Mark Paluch */ public interface TicketStatus { + /** + * Returns + * + * @return + */ String getLabel(); + /** + * Returns whether the ticket is marked as resolved. + * + * @return + */ boolean isResolved(); } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/Tickets.java b/release-tools/src/main/java/org/springframework/data/release/issues/Tickets.java similarity index 84% rename from release-tools/src/main/java/org/springframework/data/release/jira/Tickets.java rename to release-tools/src/main/java/org/springframework/data/release/issues/Tickets.java index 8c1d746..9b74234 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/Tickets.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/Tickets.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues; + +import lombok.RequiredArgsConstructor; +import lombok.Value; import java.util.ArrayList; import java.util.Collections; @@ -33,9 +36,6 @@ import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.TrainIteration; import org.springframework.util.StringUtils; -import lombok.RequiredArgsConstructor; -import lombok.Value; - /** * Value object to represent a list of {@link Ticket}s. * @@ -46,8 +46,8 @@ import lombok.Value; @RequiredArgsConstructor public class Tickets implements Streamable { - private final List tickets; - private final int overallTotal; + List tickets; + int overallTotal; public Tickets(List tickets) { this(Collections.unmodifiableList(tickets), tickets.size()); @@ -68,9 +68,7 @@ public class Tickets implements Streamable { public Ticket getReleaseTicket(ModuleIteration moduleIteration) { - Optional releaseTicket = findReleaseTicket(moduleIteration); - - return releaseTicket.orElseThrow( + return findReleaseTicket(moduleIteration).orElseThrow( () -> new IllegalStateException(String.format("Did not find a release ticket for %s!", moduleIteration))); } @@ -84,19 +82,26 @@ public class Tickets implements Streamable { return stream().// filter(ticket -> ticket.isReleaseTicketFor(iteration)).// + distinct().// collect(toTicketsCollector()); } private Optional findReleaseTicket(ModuleIteration moduleIteration) { + return stream().// filter(ticket -> ticket.isReleaseTicketFor(moduleIteration)).// findFirst(); } + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { StringBuilder builder = new StringBuilder(); + builder.append(String.format("Train only tickets: %s of %s", tickets.size(), overallTotal)); builder.append("\n"); builder.append(StringUtils.collectionToDelimitedString(tickets, "\n")); @@ -112,16 +117,29 @@ public class Tickets implements Streamable { public static Collector toTicketsCollector() { return new Collector, Tickets>() { + + /* + * (non-Javadoc) + * @see java.util.stream.Collector#supplier() + */ @Override public Supplier> supplier() { return ArrayList::new; } + /* + * (non-Javadoc) + * @see java.util.stream.Collector#accumulator() + */ @Override public BiConsumer, Ticket> accumulator() { return List::add; } + /* + * (non-Javadoc) + * @see java.util.stream.Collector#combiner() + */ @Override public BinaryOperator> combiner() { return (left, right) -> { @@ -130,16 +148,23 @@ public class Tickets implements Streamable { }; } + /* + * (non-Javadoc) + * @see java.util.stream.Collector#finisher() + */ @Override public Function, Tickets> finisher() { return tickets -> new Tickets(tickets); } + /* + * (non-Javadoc) + * @see java.util.stream.Collector#characteristics() + */ @Override public Set characteristics() { return Collections.emptySet(); } - }; } } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/GitHubIssueTracker.java b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHub.java similarity index 73% rename from release-tools/src/main/java/org/springframework/data/release/jira/GitHubIssueTracker.java rename to release-tools/src/main/java/org/springframework/data/release/issues/github/GitHub.java index 2c085db..8afaf25 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/GitHubIssueTracker.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHub.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.github; import java.net.URI; import java.util.ArrayList; @@ -23,19 +23,21 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Stream; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.release.git.GitProject; -import org.springframework.data.release.git.GitProperties; -import org.springframework.data.release.model.Iteration; +import org.springframework.data.release.issues.Changelog; +import org.springframework.data.release.issues.IssueTracker; +import org.springframework.data.release.issues.Ticket; +import org.springframework.data.release.issues.Tickets; +import org.springframework.data.release.issues.github.GitHubIssue.Milestone; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; -import org.springframework.data.release.model.Projects; -import org.springframework.data.release.model.ReleaseTrains; import org.springframework.data.release.model.Tracker; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.Logger; @@ -43,19 +45,18 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.RestOperations; import org.springframework.web.util.UriTemplate; -import lombok.RequiredArgsConstructor; - /** * @author Oliver Gierke * @author Mark Paluch */ -@RequiredArgsConstructor -class GitHubIssueTracker implements IssueTracker { +@Component +class GitHub implements IssueTracker { private static final String MILESTONE_URI = "{githubBaseUrl}/repos/spring-projects/{repoName}/milestones?state={state}"; private static final String ISSUES_BY_MILESTONE_AND_ASSIGNEE_URI_TEMPLATE = "{githubBaseUrl}/repos/spring-projects/{repoName}/issues?milestone={id}&state=all&assignee={assignee}"; @@ -64,13 +65,26 @@ class GitHubIssueTracker implements IssueTracker { private static final String ISSUE_BY_ID_URI_TEMPLATE = "{githubBaseUrl}/repos/spring-projects/{repoName}/issues/{id}"; private static final String ISSUES_URI_TEMPLATE = "{githubBaseUrl}/repos/spring-projects/{repoName}/issues"; - private static final ParameterizedTypeReference> MILESTONES_TYPE = new ParameterizedTypeReference>() {}; + private static final ParameterizedTypeReference> MILESTONES_TYPE = new ParameterizedTypeReference>() {}; private static final ParameterizedTypeReference> ISSUES_TYPE = new ParameterizedTypeReference>() {}; private static final ParameterizedTypeReference ISSUE_TYPE = new ParameterizedTypeReference() {}; private final RestOperations operations; private final Logger logger; - private final GitProperties properties; + private final GitHubProperties properties; + + /** + * @param operations + * @param logger + * @param properties + */ + @Autowired + public GitHub(@Qualifier("tracker") RestOperations operations, Logger logger, GitHubProperties properties) { + + this.operations = operations; + this.logger = logger; + this.properties = properties; + } /* * (non-Javadoc) @@ -103,24 +117,29 @@ class GitHubIssueTracker implements IssueTracker { String repositoryName = GitProject.of(project).getRepositoryName(); List tickets = new ArrayList<>(); - for (String ticketId : ticketIds) { + + ticketIds.forEach(ticketId -> { Map parameters = newUrlTemplateVariables(); parameters.put("repoName", repositoryName); parameters.put("id", ticketId); try { + GitHubIssue gitHubIssue = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.GET, new HttpEntity<>(newUserScopedHttpHeaders()), ISSUE_TYPE, parameters).getBody(); tickets.add(toTicket(gitHubIssue)); + } catch (HttpStatusCodeException e) { + if (e.getStatusCode() == HttpStatus.NOT_FOUND) { - continue; + return; } + throw e; } - } + }); return tickets; } @@ -133,13 +152,13 @@ class GitHubIssueTracker implements IssueTracker { @Cacheable("changelogs") public Changelog getChangelogFor(ModuleIteration moduleIteration) { - Tickets tickets = getIssuesFor(moduleIteration, false).stream().// + Tickets tickets = getIssuesFor(moduleIteration, false).// map(issue -> toTicket(issue)).// collect(Tickets.toTicketsCollector()); logger.log(moduleIteration, "Created changelog with %s entries.", tickets.getOverallTotal()); - return new Changelog(moduleIteration, tickets); + return Changelog.of(moduleIteration, tickets); } /* @@ -151,11 +170,6 @@ class GitHubIssueTracker implements IssueTracker { return project.uses(Tracker.GITHUB); } - @Cacheable("tickets") - public Tickets getTicketsFor(ModuleIteration iteration) { - return getTicketsFor(iteration, false); - } - @Override public Tickets getTicketsFor(TrainIteration iteration) { return getTicketsFor(iteration, false); @@ -182,14 +196,17 @@ class GitHubIssueTracker implements IssueTracker { return tickets; } + /* + * (non-Javadoc) + * @see org.springframework.data.release.tracker.IssueTracker#createReleaseVersion(org.springframework.data.release.model.ModuleIteration) + */ @Override public void createReleaseVersion(ModuleIteration moduleIteration) { Assert.notNull(moduleIteration, "ModuleIteration must not be null."); String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); - - Optional milestone = findMilestone(moduleIteration, repositoryName); + Optional milestone = findMilestone(moduleIteration, repositoryName); if (milestone.isPresent()) { return; @@ -206,13 +223,17 @@ class GitHubIssueTracker implements IssueTracker { new HttpEntity(githubMilestone.toMilestone(), httpHeaders), GitHubIssue.Milestone.class, parameters); } + /* + * + * (non-Javadoc) + * @see org.springframework.data.release.tracker.IssueTracker#createReleaseTicket(org.springframework.data.release.model.ModuleIteration) + */ @Override public void createReleaseTicket(ModuleIteration moduleIteration) { Assert.notNull(moduleIteration, "ModuleIteration must not be null."); HttpHeaders httpHeaders = newUserScopedHttpHeaders(); - Tickets tickets = getTicketsFor(moduleIteration); if (tickets.hasReleaseTicket(moduleIteration)) { @@ -220,59 +241,61 @@ class GitHubIssueTracker implements IssueTracker { } String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); + Milestone milestone = getMilestone(moduleIteration, repositoryName); + GitHubIssue gitHubIssue = GitHubIssue.of(Tracker.releaseTicketSummary(moduleIteration), milestone); Map parameters = newUrlTemplateVariables(); parameters.put("repoName", repositoryName); - GitHubIssue.Milestone milestone = getMilestone(moduleIteration, repositoryName); - logger.log(moduleIteration, "Creating release ticket…"); - GitHubIssue gitHubIssue = new GitHubIssue(Tracker.releaseTicketSummary(moduleIteration), milestone); - operations.exchange(ISSUES_URI_TEMPLATE, HttpMethod.POST, new HttpEntity(gitHubIssue, httpHeaders), GitHubIssue.class, parameters).getBody(); - } - private Tickets getTicketsFor(ModuleIteration moduleIteration, boolean forCurrentUser) { - - List issues = getIssuesFor(moduleIteration, forCurrentUser); - return issues.stream().map(this::toTicket).collect(Tickets.toTicketsCollector()); + @Cacheable("tickets") + public Tickets getTicketsFor(ModuleIteration iteration) { + return getTicketsFor(iteration, false); } - private List getIssuesFor(ModuleIteration moduleIteration, boolean forCurrentUser) { - - String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); - - GitHubIssue.Milestone milestone = getMilestone(moduleIteration, repositoryName); - - Map parameters = newUrlTemplateVariables(); - parameters.put("repoName", repositoryName); - parameters.put("id", milestone.getNumber()); - - if (forCurrentUser) { - parameters.put("assignee", properties.getUsername()); - - return operations.exchange(ISSUES_BY_MILESTONE_AND_ASSIGNEE_URI_TEMPLATE, HttpMethod.GET, - new HttpEntity<>(newUserScopedHttpHeaders()), ISSUES_TYPE, parameters).getBody(); - } - - return operations.exchange(ISSUES_BY_MILESTONE_URI_TEMPLATE, HttpMethod.GET, - new HttpEntity<>(newUserScopedHttpHeaders()), ISSUES_TYPE, parameters).getBody(); + /* + * + * (non-Javadoc) + * @see org.springframework.data.release.jira.IssueTracker#assignTicketToMe(org.springframework.data.release.jira.Ticket) + */ + @Override + public void assignTicketToMe(Ticket ticket) { + logger.log("Ticket", "Skipping ticket assignment for %s", ticket); } - private GitHubIssue.Milestone getMilestone(ModuleIteration moduleIteration, String repositoryName) { + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.IssueTracker#assignReleaseTicketToMe(org.springframework.data.release.model.ModuleIteration) + */ + @Override + public Ticket assignReleaseTicketToMe(ModuleIteration module) { - Optional milestone = findMilestone(moduleIteration, repositoryName); - return milestone - .orElseThrow(() -> new IllegalStateException(String.format("No milestone for %s found containing %s!", // - moduleIteration.getProject().getFullName(), // - moduleIteration.getShortVersionString()))); + logger.log("Ticket", "Skipping ticket assignment for %s", module); + return null; } - @Cacheable("milestone") - protected Optional findMilestone(ModuleIteration moduleIteration, String repositoryName) { + private HttpHeaders newUserScopedHttpHeaders() { + + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", properties.getHttpCredentials().toString()); + + return headers; + } + + private Map newUrlTemplateVariables() { + + Map parameters = new HashMap<>(); + parameters.put("githubBaseUrl", properties.getApiUrl()); + + return parameters; + } + + private Optional findMilestone(ModuleIteration moduleIteration, String repositoryName) { for (String state : Arrays.asList("close", "open")) { @@ -288,7 +311,7 @@ class GitHubIssueTracker implements IssueTracker { new HttpEntity<>(newUserScopedHttpHeaders()), MILESTONES_TYPE, parameters).getBody(); Optional milestone = milestones.stream(). // - filter(m -> m.matchesIteration(moduleIteration)). // + filter(m -> m.matches(moduleIteration)). // findFirst(). // map(m -> { logger.log(moduleIteration, "Found milestone %s.", m); @@ -303,38 +326,50 @@ class GitHubIssueTracker implements IssueTracker { return Optional.empty(); } - private HttpHeaders newUserScopedHttpHeaders() { + private Tickets getTicketsFor(ModuleIteration moduleIteration, boolean forCurrentUser) { - HttpHeaders headers = new HttpHeaders(); - headers.set("Authorization", properties.getHttpCredentials().toString()); - - return headers; + return getIssuesFor(moduleIteration, forCurrentUser).// + map(GitHub::toTicket).// + collect(Tickets.toTicketsCollector()); } - private Map newUrlTemplateVariables() { - Map parameters = new HashMap<>(); - parameters.put("githubBaseUrl", properties.getGithubApiBaseUrl()); - return parameters; + private Stream getIssuesFor(ModuleIteration moduleIteration, boolean forCurrentUser) { + + String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName(); + + GitHubIssue.Milestone milestone = getMilestone(moduleIteration, repositoryName); + + Map parameters = newUrlTemplateVariables(); + parameters.put("repoName", repositoryName); + parameters.put("id", milestone.getNumber()); + + if (forCurrentUser) { + parameters.put("assignee", properties.getUsername()); + + return getForIssues(ISSUES_BY_MILESTONE_AND_ASSIGNEE_URI_TEMPLATE, parameters); + } + + return getForIssues(ISSUES_BY_MILESTONE_URI_TEMPLATE, parameters); } - private Ticket toTicket(GitHubIssue issue) { + private Stream getForIssues(String template, Map parameters) { + + return operations + .exchange(template, HttpMethod.GET, new HttpEntity<>(newUserScopedHttpHeaders()), ISSUES_TYPE, parameters) + .getBody().stream(); + } + + private Milestone getMilestone(ModuleIteration moduleIteration, String repositoryName) { + + Optional milestone = findMilestone(moduleIteration, repositoryName); + + return milestone + .orElseThrow(() -> new IllegalStateException(String.format("No milestone for %s found containing %s!", // + moduleIteration.getProject().getFullName(), // + moduleIteration.getShortVersionString()))); + } + + private static Ticket toTicket(GitHubIssue issue) { return new Ticket(issue.getId(), issue.getTitle(), new GithubTicketStatus(issue.getState())); } - - public static void main(String[] args) { - - try (ConfigurableApplicationContext context = new ClassPathXmlApplicationContext( - "META-INF/spring/spring-shell-plugin.xml")) { - - IssueTracker tracker = context.getBean("gitHubIssueTracker", IssueTracker.class); - - TrainIteration iteration = new TrainIteration(ReleaseTrains.CODD, Iteration.SR2); - ModuleIteration module = iteration.getModule(Projects.BUILD); - - Changelog changelog = tracker.getChangelogFor(module); - System.out.println(changelog); - - System.out.println(tracker.getReleaseTicketFor(module)); - } - } } diff --git a/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java new file mode 100644 index 0000000..a5a8526 --- /dev/null +++ b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubIssue.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014-2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.release.issues.github; + +import lombok.RequiredArgsConstructor; +import lombok.Value; + +import org.springframework.data.release.model.ModuleIteration; + +/** + * @author Oliver Gierke + * @author Mark Paluch + */ +@Value +@RequiredArgsConstructor +class GitHubIssue { + + String number, title, state; + Object milestone; + + public static GitHubIssue of(String title, Milestone milestone) { + return new GitHubIssue(null, title, null, milestone.number); + } + + public String getId() { + return number == null ? null : "#".concat(number); + } + + /** + * @author Oliver Gierke + * @author Mark Paluch + */ + @Value + static class Milestone { + + Long number; + String title, description; + + public static Milestone of(String title, String description) { + return new Milestone(null, title, description); + } + + public boolean matches(ModuleIteration moduleIteration) { + return title.contains(moduleIteration.getShortVersionString()); + } + } +} diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/GitHubMilestone.java b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubMilestone.java similarity index 80% rename from release-tools/src/main/java/org/springframework/data/release/jira/GitHubMilestone.java rename to release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubMilestone.java index 166b816..6aa995b 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/GitHubMilestone.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubMilestone.java @@ -13,19 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; - -import org.springframework.data.release.model.ModuleIteration; +package org.springframework.data.release.issues.github; import lombok.Value; +import org.springframework.data.release.issues.github.GitHubIssue.Milestone; +import org.springframework.data.release.model.ModuleIteration; + /** * @author Mark Paluch */ @Value class GithubMilestone { - private ModuleIteration module; + ModuleIteration module; + + public String getDescription() { + return module.getTrain().getName() + " " + module.getIteration().getName(); + } + + public Milestone toMilestone() { + return Milestone.of(toString(), getDescription()); + } /* * (non-Javadoc) @@ -35,12 +44,4 @@ class GithubMilestone { public String toString() { return module.getMediumVersionString(); } - - public String getDescription() { - return module.getTrain().getName() + " " + module.getIteration().getName(); - } - - public GitHubIssue.Milestone toMilestone() { - return new GitHubIssue.Milestone(toString(), getDescription()); - } } diff --git a/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubProperties.java b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubProperties.java new file mode 100644 index 0000000..fda66d9 --- /dev/null +++ b/release-tools/src/main/java/org/springframework/data/release/issues/github/GitHubProperties.java @@ -0,0 +1,57 @@ +/* + * Copyright 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.release.issues.github; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.data.release.git.GitProperties; +import org.springframework.data.release.utils.HttpBasicCredentials; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +/** + * @author Oliver Gierke + */ +@Data +@Component +@ConfigurationProperties(prefix = "github") +@RequiredArgsConstructor(onConstructor = @__(@Autowired) ) +public class GitHubProperties { + + private final @Getter(AccessLevel.NONE) GitProperties gitProperties; + + private String apiUrl; + + public String getUsername() { + return gitProperties.getUsername(); + } + + public HttpBasicCredentials getHttpCredentials() { + return gitProperties.getHttpCredentials(); + } + + @PostConstruct + public void init() { + Assert.hasText(apiUrl, "No GitHub API base url configured!"); + } +} diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/GithubTicketStatus.java b/release-tools/src/main/java/org/springframework/data/release/issues/github/GithubTicketStatus.java similarity index 60% rename from release-tools/src/main/java/org/springframework/data/release/jira/GithubTicketStatus.java rename to release-tools/src/main/java/org/springframework/data/release/issues/github/GithubTicketStatus.java index c39ef51..81de37f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/GithubTicketStatus.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/github/GithubTicketStatus.java @@ -14,25 +14,42 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.github; -import lombok.AllArgsConstructor; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import lombok.experimental.FieldDefaults; + +import org.springframework.data.release.issues.TicketStatus; /** * Value object for a GitHub ticket status. * * @author Mark Paluch */ -@AllArgsConstructor +@EqualsAndHashCode +@ToString +@RequiredArgsConstructor +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) class GithubTicketStatus implements TicketStatus { private final String status; + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.TicketStatus#getLabel() + */ @Override public String getLabel() { return status; } + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.TicketStatus#isResolved() + */ @Override public boolean isResolved() { return "closed".equalsIgnoreCase(status); diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/CreatedJiraIssue.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/CreatedJiraIssue.java similarity index 77% rename from release-tools/src/main/java/org/springframework/data/release/jira/CreatedJiraIssue.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/CreatedJiraIssue.java index 85521a3..c6eccf4 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/CreatedJiraIssue.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/CreatedJiraIssue.java @@ -14,19 +14,17 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; -import lombok.Data; +import lombok.Value; /** - * Value object for a created Jira issue. + * Value object for a created JIRA issue. * * @author Mark Paluch + * @author Oliver Gierke */ -@Data -public class CreatedJiraIssue { - - private String id; - private String key; - +@Value +class CreatedJiraIssue { + String id, key; } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/Credentials.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/Credentials.java similarity index 82% rename from release-tools/src/main/java/org/springframework/data/release/jira/Credentials.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/Credentials.java index 56dc81a..c1cae96 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/Credentials.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/Credentials.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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,19 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; - -import javax.xml.bind.DatatypeConverter; +package org.springframework.data.release.issues.jira; import lombok.Value; +import javax.xml.bind.DatatypeConverter; + /** * @author Oliver Gierke */ @Value -public class Credentials { +class Credentials { - private final String username, password; + String username, password; public String asBase64() { return DatatypeConverter.printBase64Binary(String.format("%s:%s", username, password).getBytes()); diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/Jira.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/Jira.java similarity index 86% rename from release-tools/src/main/java/org/springframework/data/release/jira/Jira.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/Jira.java index 4130ece..82fe8df 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/Jira.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/Jira.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; import java.net.URI; import java.util.ArrayList; @@ -25,19 +25,21 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; -import org.springframework.boot.SpringApplication; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.ParameterizedTypeReference; -import org.springframework.data.release.Application; -import org.springframework.data.release.jira.JiraIssue.Component; -import org.springframework.data.release.jira.JiraIssue.Fields; -import org.springframework.data.release.model.Iteration; +import org.springframework.data.release.issues.Changelog; +import org.springframework.data.release.issues.Ticket; +import org.springframework.data.release.issues.Tickets; +import org.springframework.data.release.issues.jira.JiraIssue.Component; +import org.springframework.data.release.issues.jira.JiraIssue.Fields; +import org.springframework.data.release.issues.jira.JiraIssue.Resolution; +import org.springframework.data.release.issues.jira.JiraIssue.Status; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; import org.springframework.data.release.model.ProjectKey; -import org.springframework.data.release.model.ReleaseTrains; import org.springframework.data.release.model.Tracker; import org.springframework.data.release.model.TrainIteration; import org.springframework.data.release.utils.Logger; @@ -48,13 +50,11 @@ import org.springframework.util.Assert; import org.springframework.web.client.RestOperations; import org.springframework.web.util.UriTemplate; -import lombok.RequiredArgsConstructor; - /** * @author Oliver Gierke * @author Mark Paluch */ -@RequiredArgsConstructor +@org.springframework.stereotype.Component class Jira implements JiraConnector { private static final String BASE_URI = "{jiraBaseUrl}/rest/api/2"; @@ -69,9 +69,21 @@ class Jira implements JiraConnector { private final RestOperations operations; private final Logger logger; - private final JiraProperties jiraProperties; + /** + * @param operations + * @param logger + * @param jiraProperties + */ + @Autowired + public Jira(@Qualifier("tracker") RestOperations operations, Logger logger, JiraProperties jiraProperties) { + + this.operations = operations; + this.logger = logger; + this.jiraProperties = jiraProperties; + } + /* * (non-Javadoc) * @see org.springframework.data.release.jira.JiraConnector#reset() @@ -93,13 +105,11 @@ class Jira implements JiraConnector { JiraIssues issues = getJiraIssues(query, new HttpHeaders(), 0); - if (issues.getIssues().isEmpty()) { + if (!issues.hasIssues()) { throw new IllegalArgumentException(String.format("Did not find a release ticket for %s!", moduleIteration)); } - JiraIssue issue = issues.getIssues().get(0); - - return toTicket(issue); + return toTicket(issues.stream().findFirst().get()); } /* @@ -125,19 +135,27 @@ class Jira implements JiraConnector { JiraIssues issues = operations.exchange(SEARCH_TEMPLATE, HttpMethod.GET, null, JiraIssues.class, parameters) .getBody(); - return issues.getIssues().stream().// + return issues.stream().// map(this::toTicket).// collect(Collectors.toList()); } - @Cacheable("tickets") + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.IssueTracker#getTicketsFor(org.springframework.data.release.model.TrainIteration) + */ @Override + @Cacheable("tickets") public Tickets getTicketsFor(TrainIteration iteration) { return getTicketsFor(iteration, false); } - @Cacheable("tickets") + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.IssueTracker#getTicketsFor(org.springframework.data.release.model.TrainIteration, boolean) + */ @Override + @Cacheable("tickets") public Tickets getTicketsFor(TrainIteration trainIteration, boolean forCurrentUser) { JqlQuery query = JqlQuery @@ -208,7 +226,7 @@ class Jira implements JiraConnector { JiraVersion jiraVersion = new JiraVersion(moduleIteration); logger.log(moduleIteration, "Creating Jira release version %s", jiraVersion); - JiraReleaseVersion jiraReleaseVersion = new JiraReleaseVersion(moduleIteration, jiraVersion); + JiraReleaseVersion jiraReleaseVersion = JiraReleaseVersion.of(moduleIteration, jiraVersion); operations.exchange(VERSIONS_TEMPLATE, HttpMethod.POST, new HttpEntity(jiraReleaseVersion, httpHeaders), JiraReleaseVersion.class, parameters).getBody(); @@ -235,6 +253,10 @@ class Jira implements JiraConnector { return versionsForModuleIteration.stream().findFirst(); } + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.IssueTracker#createReleaseTicket(org.springframework.data.release.model.ModuleIteration) + */ @Override public void createReleaseTicket(ModuleIteration moduleIteration) { @@ -250,8 +272,7 @@ class Jira implements JiraConnector { return; } - Optional jiraReleaseVersion = findJiraReleaseVersion(moduleIteration); - jiraReleaseVersion.orElseThrow( + findJiraReleaseVersion(moduleIteration).orElseThrow( () -> new IllegalStateException(String.format("Did not find a release version for %s", moduleIteration))); JiraComponents jiraComponents = getJiraComponents(moduleIteration.getProjectKey()); @@ -264,6 +285,10 @@ class Jira implements JiraConnector { CreatedJiraIssue.class, parameters).getBody(); } + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.JiraConnector#assignTicketToMe(org.springframework.data.release.jira.Ticket) + */ @Override public void assignTicketToMe(Ticket ticket) { @@ -280,19 +305,16 @@ class Jira implements JiraConnector { String.class, parameters).getBody(); } - private JiraIssue prepareJiraIssueToCreate(ModuleIteration moduleIteration, JiraComponents jiraComponents) { + /* + * (non-Javadoc) + * @see org.springframework.data.release.jira.IssueTracker#assignReleaseTicketToMe(org.springframework.data.release.model.ModuleIteration) + */ + @Override + public Ticket assignReleaseTicketToMe(ModuleIteration module) { - JiraIssue jiraIssue = JiraIssue.createTask(); - jiraIssue.project(moduleIteration.getProjectKey()).summary(Tracker.releaseTicketSummary(moduleIteration)) - .fixVersion(moduleIteration); - - Fields fields = jiraIssue.getFields(); - - Optional component = jiraComponents.findComponent(INFRASTRUCTURE_COMPONENT_NAME); - component.ifPresent( - jiraComponent -> fields.setComponents(Collections.singletonList(Component.from(jiraComponent.getName())))); - - return jiraIssue; + Ticket ticket = getReleaseTicketFor(module); + assignTicketToMe(ticket); + return ticket; } /* @@ -304,8 +326,8 @@ class Jira implements JiraConnector { // for each module for (ModuleIteration moduleIteration : trainIteration) { - Tickets tickets = getTicketsFor(moduleIteration); + Tickets tickets = getTicketsFor(moduleIteration); Ticket releaseTicket = tickets.getReleaseTicket(moduleIteration); if (releaseTicket.isResolved()) { @@ -366,7 +388,7 @@ class Jira implements JiraConnector { Tickets tickets = issues.stream().map(this::toTicket).collect(Tickets.toTicketsCollector()); logger.log(moduleIteration, "Created changelog with %s entries.", tickets.getOverallTotal()); - return new Changelog(moduleIteration, tickets); + return Changelog.of(moduleIteration, tickets); } /* @@ -391,6 +413,21 @@ class Jira implements JiraConnector { return JiraComponents.of(components); } + private JiraIssue prepareJiraIssueToCreate(ModuleIteration moduleIteration, JiraComponents jiraComponents) { + + JiraIssue jiraIssue = JiraIssue.createTask(); + jiraIssue.project(moduleIteration.getProjectKey()).summary(Tracker.releaseTicketSummary(moduleIteration)) + .fixVersion(moduleIteration); + + Fields fields = jiraIssue.getFields(); + + Optional component = jiraComponents.findComponent(INFRASTRUCTURE_COMPONENT_NAME); + component.ifPresent( + jiraComponent -> fields.setComponents(Collections.singletonList(Component.of(jiraComponent.getName())))); + + return jiraIssue; + } + private JiraIssues execute(String context, JqlQuery query, HttpHeaders headers, JiraIssuesCallback callback) { JiraIssues issues; @@ -458,15 +495,16 @@ class Jira implements JiraConnector { private Ticket toTicket(JiraIssue issue) { - JiraIssue.Fields fields = issue.getFields(); - + Fields fields = issue.getFields(); JiraTicketStatus jiraTicketStatus; - if (fields.getStatus() != null && fields.getResolution() != null) { - JiraIssue.Status status = fields.getStatus(); - boolean resolved = status.getStatusCategory().getKey().equals("done"); - JiraIssue.Resolution resolution = fields.getResolution(); - jiraTicketStatus = new JiraTicketStatus(resolved, status.getName(), resolution.getName()); + if (fields.hasStatusAndResolution()) { + + Status status = fields.getStatus(); + boolean resolved = status.getStatusCategory().getKey().equals("done"); + Resolution resolution = fields.getResolution(); + + jiraTicketStatus = JiraTicketStatus.of(resolved, status.getName(), resolution.getName()); } else { jiraTicketStatus = JiraTicketStatus.UNKNOWN; } @@ -486,24 +524,9 @@ class Jira implements JiraConnector { return headers; } - public static void main(String[] args) { - - try (ConfigurableApplicationContext context = SpringApplication.run(Application.class, args)) { - - JiraConnector tracker = context.getBean(JiraConnector.class); - TrainIteration iteration = new TrainIteration(ReleaseTrains.GOSLING, Iteration.SR1); - ModuleIteration module = iteration.getModule("JPA"); - - // Changelog changelog = tracker.getChangelogFor(module); - // System.out.println(changelog); - - System.out.println(tracker.getReleaseTicketFor(module)); - } - } - private Map newUrlTemplateVariables() { Map parameters = new HashMap<>(); - parameters.put("jiraBaseUrl", jiraProperties.getUrl()); + parameters.put("jiraBaseUrl", jiraProperties.getApiUrl()); return parameters; } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraComponent.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraComponent.java similarity index 70% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraComponent.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraComponent.java index d41fdf0..cdd066d 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraComponent.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraComponent.java @@ -13,30 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.springframework.data.release.jira; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; +package org.springframework.data.release.issues.jira; import lombok.Value; -/* +/** * Value object to bind REST responses to. * * @author Mark Paluch + * @author Oliver Gierke */ @Value class JiraComponent { - private String id; - private String name; - - @JsonCreator - public JiraComponent(@JsonProperty("id") String id, @JsonProperty("name") String name) { - this.id = id; - this.name = name; - } + String id, name; public boolean hasName(String name) { return this.name.equals(name); diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraComponents.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraComponents.java similarity index 71% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraComponents.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraComponents.java index c3285b7..b803bcc 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraComponents.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraComponents.java @@ -14,28 +14,25 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; + +import lombok.NonNull; +import lombok.Value; import java.util.Collection; import java.util.Iterator; import java.util.Optional; -import org.springframework.util.Assert; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NonNull; - -/* +/** * Value object to represent a list of {@link JiraComponent}s. + * * @author Mark Paluch + * @author Oliver Gierke */ -@Data -@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Value(staticConstructor = "of") class JiraComponents implements Iterable { - @NonNull private Collection jiraComponents; + @NonNull Collection jiraComponents; /** * Try to find a component by its {@code name}. @@ -47,12 +44,10 @@ class JiraComponents implements Iterable { return jiraComponents.stream().filter(jiraComponent -> jiraComponent.hasName(name)).findFirst(); } - public static JiraComponents of(Collection jiraComponents) { - - Assert.notNull(jiraComponents, "JiraComponents must not be null!"); - return new JiraComponents(jiraComponents); - } - + /* + * (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ @Override public Iterator iterator() { return jiraComponents.iterator(); diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraConnector.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraConnector.java similarity index 76% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraConnector.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraConnector.java index 7137581..61a9f0f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraConnector.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraConnector.java @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; import java.util.Optional; +import org.springframework.data.release.issues.IssueTracker; +import org.springframework.data.release.issues.Tickets; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.TrainIteration; @@ -24,32 +26,28 @@ import org.springframework.data.release.model.TrainIteration; * @author Oliver Gierke * @author Mark Paluch */ -public interface JiraConnector extends IssueTracker { +interface JiraConnector extends IssueTracker { /** * Verifies the state of all {@link Tickets} before releasing. In particular: Check whether the release ticket exists, * check whether all other issue tickets are in a resolved state. * - * @param iteration + * @param iteration must not be {@literal null}. */ void verifyBeforeRelease(TrainIteration iteration); + /** + * Closes the given {@link TrainIteration}. + * + * @param iteration must not be {@literal null}. + */ void closeIteration(TrainIteration iteration); /** - * Lookup a Jira release version. + * Lookup a JIRA release version. * * @param moduleIteration must not be {@literal null}. * @return */ Optional findJiraReleaseVersion(ModuleIteration moduleIteration); - - /** - * Assigns the ticket to the current user. - * - * @param ticket must not be {@literal null}. - * @param credentials must not be {@literal null}. - */ - void assignTicketToMe(Ticket ticket); - } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraIssue.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraIssue.java similarity index 77% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraIssue.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraIssue.java index 9adfc4f..b92a59a 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraIssue.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraIssue.java @@ -13,69 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; + +import lombok.Data; +import lombok.Value; import java.util.Collections; import java.util.List; +import org.springframework.data.release.issues.Ticket; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.ProjectKey; import org.springframework.data.release.model.Tracker; import org.springframework.data.release.model.Train; import org.springframework.util.Assert; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - /** * Value object to bind REST responses to. * * @author Oliver Gierke * @author Mark Paluch */ -@Data +@Value class JiraIssue { - private String key; - private Fields fields; - - /** - * Returns whether the ticket is only fixed in the given {@link Train}. {@literal false} indicates the {@link Ticket} - * has been resolved for - * - * @param train - * @return - */ - public boolean wasBackportedFrom(Train train) { - - List fixVersions = fields.getFixVersions(); - return fixVersions != null && wasBackportedFrom(train, fixVersions); - } - - private boolean wasBackportedFrom(Train train, List fixVersions) { - return fixVersions.size() > 1 && isPresent(train, fixVersions); - } - - private boolean isPresent(Train train, List fixVersions) { - return fixVersions.stream().// - filter(fixVersion -> fixVersion.isTrain(train)).// - findFirst().// - isPresent(); - } - - /** - * Returns whether the ticket is a release ticket. - * - * @param moduleIteration - * @return - */ - public boolean isReleaseTicket(ModuleIteration moduleIteration) { - - List fixVersions = fields.getFixVersions(); - return fixVersions.size() == 1 && isPresent(moduleIteration.getTrain(), fixVersions) - && fields.hasSummary(Tracker.releaseTicketSummary(moduleIteration)); - } + String key; + Fields fields; /** * Creates a new Jira issue value object. @@ -83,10 +46,7 @@ class JiraIssue { * @return */ public static JiraIssue create() { - - JiraIssue jiraIssue = new JiraIssue(); - jiraIssue.setFields(new Fields()); - return jiraIssue; + return new JiraIssue(null, new Fields()); } /** @@ -100,6 +60,32 @@ class JiraIssue { return jiraIssue; } + /** + * Returns whether the ticket is only fixed in the given {@link Train}. {@literal false} indicates the {@link Ticket} + * has been resolved for + * + * @param train + * @return + */ + public boolean wasBackportedFrom(Train train) { + + List fixVersions = fields.getFixVersions(); + return fixVersions != null && wasBackportedFrom(train, fixVersions); + } + + /** + * Returns whether the ticket is a release ticket. + * + * @param moduleIteration + * @return + */ + public boolean isReleaseTicket(ModuleIteration moduleIteration) { + + List fixVersions = fields.getFixVersions(); + return fixVersions.size() == 1 && isPresent(moduleIteration.getTrain(), fixVersions) + && fields.hasSummary(Tracker.releaseTicketSummary(moduleIteration)); + } + /** * Assign to the user specified in {@link Credentials}. * @@ -131,7 +117,7 @@ class JiraIssue { */ public JiraIssue project(ProjectKey projectKey) { - getFields().setProject(new Project(projectKey)); + getFields().setProject(Project.from(projectKey)); return this; } @@ -156,18 +142,29 @@ class JiraIssue { public JiraIssue fixVersion(ModuleIteration moduleIteration) { Assert.notNull(moduleIteration, "ModuleIteration must not be null!"); - getFields().setFixVersions(Collections.singletonList(new JiraVersion(moduleIteration).toFixVersions())); + getFields().setFixVersions(Collections.singletonList(new JiraVersion(moduleIteration).toFixVersion())); return this; } + private static boolean wasBackportedFrom(Train train, List fixVersions) { + return fixVersions.size() > 1 && isPresent(train, fixVersions); + } + + private static boolean isPresent(Train train, List fixVersions) { + return fixVersions.stream().// + filter(fixVersion -> fixVersion.isTrain(train)).// + findFirst().// + isPresent(); + } + @Data static class Fields { Project project; IssueType issuetype; String summary; - List fixVersions; + List fixVersions; List components; Status status; Resolution resolution; @@ -176,33 +173,31 @@ class JiraIssue { public boolean hasSummary(String other) { return summary.equals(other); } + + public boolean hasStatusAndResolution() { + return status != null && resolution != null; + } } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Value static class Component { - String id; - String name; + String id, name; - public static Component from(String name) { + public static Component of(String name) { Assert.hasText(name, "Name must not be empty!"); return new Component(null, name); } } - @Data - @NoArgsConstructor - @AllArgsConstructor - static class FixVersions { + @Value + static class FixVersion { - String id; - String name; + String id, name; /** - * Returns whether this {@link FixVersions} matches the given {@link Train}. + * Returns whether this {@link FixVersion} matches the given {@link Train}. * * @param train * @return @@ -212,9 +207,7 @@ class JiraIssue { } } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Value static class IssueType { public final static IssueType TASK = new IssueType("Task"); @@ -222,50 +215,39 @@ class JiraIssue { String name; } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Value static class Status { String name; StatusCategory statusCategory; } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Value static class Project { String key; - public Project(ProjectKey projectKey) { - this.key = projectKey.getKey(); + public static Project from(ProjectKey projectKey) { + return new Project(projectKey.getKey()); } } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Value static class Resolution { String name; } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Value static class StatusCategory { String key; } - @Data - @NoArgsConstructor - @AllArgsConstructor + @Value static class JiraUser { - String name; - String displayName; + String name, displayName; static JiraUser from(String username) { return new JiraUser(username, null); diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraIssues.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraIssues.java similarity index 75% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraIssues.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraIssues.java index 3413527..47fbfaf 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraIssues.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraIssues.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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,26 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; +import lombok.Getter; +import lombok.Value; + +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.springframework.data.release.Streamable; -import lombok.Data; - /** * @author Oliver Gierke */ -@Data +@Value class JiraIssues implements Streamable { - private int startAt; - private int maxResults; - private int total; - - private List issues; + int startAt, maxResult; + @Getter int total; + List issues = new ArrayList<>(); public int getNextStartAt() { return startAt + issues.size(); @@ -42,6 +42,10 @@ class JiraIssues implements Streamable { return startAt + issues.size() < total; } + public boolean hasIssues() { + return !issues.isEmpty(); + } + /* * (non-Javadoc) * @see java.lang.Iterable#iterator() diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraProperties.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraProperties.java similarity index 88% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraProperties.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraProperties.java index c4ac05c..bf8c71f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraProperties.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraProperties.java @@ -14,7 +14,11 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; import javax.annotation.PostConstruct; @@ -22,12 +26,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import org.springframework.util.Assert; -import lombok.AccessLevel; -import lombok.Data; -import lombok.Getter; - /** - * Configurable properties for Git. + * Configurable properties for JIRA. * * @author Mark Paluch */ @@ -37,14 +37,14 @@ import lombok.Getter; class JiraProperties { private @Getter(AccessLevel.PRIVATE) String password; - private String username, url; + private String username, apiUrl; @PostConstruct public void init() { Assert.hasText(username, "No Jira username (jira.username) configured!"); Assert.hasText(password, "No Jira password (jira.password) configured!"); - Assert.hasText(url, "No Jira url (jira.url) configured!"); + Assert.hasText(apiUrl, "No Jira url (jira.api-url) configured!"); } /** @@ -55,5 +55,4 @@ class JiraProperties { public Credentials getCredentials() { return new Credentials(username, password); } - } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraReleaseVersion.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraReleaseVersion.java similarity index 55% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraReleaseVersion.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraReleaseVersion.java index 7ce3942..fa2b164 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraReleaseVersion.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraReleaseVersion.java @@ -14,46 +14,30 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; -import lombok.Data; +import lombok.Value; import org.springframework.data.release.model.ModuleIteration; import org.springframework.util.Assert; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - /** * Value object to bind REST responses to. * * @author Mark Paluch */ -@Data -public class JiraReleaseVersion { +@Value +class JiraReleaseVersion { - private String id; - private String name; - private String project; - private String description; + String id, name, project, description; - @JsonCreator - public JiraReleaseVersion(@JsonProperty("id") String id, @JsonProperty("name") String name, - @JsonProperty("string") String project, @JsonProperty("description") String description) { - this.id = id; - this.name = name; - this.project = project; - this.description = description; - } - - public JiraReleaseVersion(ModuleIteration moduleIteration, JiraVersion jiraVersion) { + public static JiraReleaseVersion of(ModuleIteration moduleIteration, JiraVersion jiraVersion) { Assert.notNull(moduleIteration, "ModuleIteration must not be null."); Assert.notNull(jiraVersion, "JiraVersion must not be null."); - project = moduleIteration.getProjectKey().getKey(); - name = jiraVersion.toString(); - description = jiraVersion.getDescription(); + return new JiraReleaseVersion(null, jiraVersion.toString(), moduleIteration.getProjectKey().getKey(), + jiraVersion.getDescription()); } public boolean hasSameNameAs(JiraVersion jiraVersion) { diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraReleaseVersions.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraReleaseVersions.java similarity index 85% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraReleaseVersions.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraReleaseVersions.java index 75b1c60..8694603 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraReleaseVersions.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraReleaseVersions.java @@ -13,28 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; +import lombok.Value; + +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.springframework.data.release.Streamable; -import lombok.Data; - /** * Value object to bind REST responses to. * * @author Mark Paluch */ -@Data +@Value class JiraReleaseVersions implements Streamable { - private int startAt; - private int maxResults; - private int total; - - private List values; + int startAt, maxResults, total; + List values = new ArrayList<>(); public int getNextStartAt() { return startAt + values.size(); diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraTicketStatus.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraTicketStatus.java similarity index 70% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraTicketStatus.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraTicketStatus.java index 3ba953b..5cbb88b 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraTicketStatus.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraTicketStatus.java @@ -14,21 +14,25 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; -import lombok.RequiredArgsConstructor; +import lombok.NonNull; +import lombok.Value; + +import org.springframework.data.release.issues.TicketStatus; /** * @author Mark Paluch + * @author Oliver Gierke */ -@RequiredArgsConstructor -public class JiraTicketStatus implements TicketStatus { +@Value(staticConstructor = "of") +class JiraTicketStatus implements TicketStatus { - public static final JiraTicketStatus UNKNOWN = new JiraTicketStatus(false, "unknown", null); + public static final JiraTicketStatus UNKNOWN = JiraTicketStatus.of(false, "unknown", null); - private final boolean resolved; - private final String status; - private final String resolution; + boolean resolved; + @NonNull String status; + String resolution; /* * (non-Javadoc) diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JiraVersion.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraVersion.java similarity index 81% rename from release-tools/src/main/java/org/springframework/data/release/jira/JiraVersion.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraVersion.java index 99a761d..dd2169a 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JiraVersion.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JiraVersion.java @@ -13,20 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; - -import org.springframework.data.release.jira.JiraIssue.FixVersions; -import org.springframework.data.release.model.ModuleIteration; +package org.springframework.data.release.issues.jira; import lombok.Value; +import org.springframework.data.release.issues.jira.JiraIssue.FixVersion; +import org.springframework.data.release.model.ModuleIteration; + /** * @author Oliver Gierke */ @Value class JiraVersion { - private ModuleIteration module; + ModuleIteration module; /* * (non-Javadoc) @@ -41,7 +41,7 @@ class JiraVersion { return module.getTrain().getName() + " " + module.getIteration().getName(); } - public FixVersions toFixVersions() { - return new FixVersions(null, toString()); + public FixVersion toFixVersion() { + return new FixVersion(null, toString()); } } diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/JqlQuery.java b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JqlQuery.java similarity index 83% rename from release-tools/src/main/java/org/springframework/data/release/jira/JqlQuery.java rename to release-tools/src/main/java/org/springframework/data/release/issues/jira/JqlQuery.java index 40d0b26..95ef22f 100644 --- a/release-tools/src/main/java/org/springframework/data/release/jira/JqlQuery.java +++ b/release-tools/src/main/java/org/springframework/data/release/issues/jira/JqlQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; + +import lombok.Value; import java.util.ArrayList; import java.util.Collection; @@ -22,10 +24,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.springframework.data.release.model.ModuleIteration; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import lombok.Value; - /** * @author Oliver Gierke * @author Mark Paluch @@ -38,16 +39,16 @@ class JqlQuery { private final String query; - public JqlQuery and(String clause) { - return new JqlQuery(String.format("(%s) AND %s", query, clause)); - } - - public JqlQuery orderBy(String orderBy) { - return new JqlQuery(String.format("%s ORDER BY %s", query, orderBy)); - } - + /** + * Creates a new {@link JqlQuery} for the given {@link ModuleIteration}. + * + * @param iteration must not be {@literal null}. + * @return + */ public static JqlQuery from(ModuleIteration iteration) { + Assert.notNull(iteration, "Module iteration must not be null!"); + JiraVersion version = new JiraVersion(iteration); return new JqlQuery(String.format(PROJECT_VERSION_TEMPLATE, iteration.getProjectKey(), version)); @@ -72,6 +73,18 @@ class JqlQuery { return new JqlQuery(StringUtils.collectionToDelimitedString(parts, " OR ")); } + public JqlQuery and(String clause) { + return new JqlQuery(String.format("(%s) AND %s", query, clause)); + } + + public JqlQuery orderBy(String orderBy) { + return new JqlQuery(String.format("%s ORDER BY %s", query, orderBy)); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { return query; diff --git a/release-tools/src/main/java/org/springframework/data/release/jira/GitHubIssue.java b/release-tools/src/main/java/org/springframework/data/release/jira/GitHubIssue.java deleted file mode 100644 index 6a9c211..0000000 --- a/release-tools/src/main/java/org/springframework/data/release/jira/GitHubIssue.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2014-2016 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.release.jira; - -import org.springframework.data.release.model.ModuleIteration; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -import lombok.Value; - -/** - * @author Oliver Gierke - * @author Mark Paluch - */ -@Value -class GitHubIssue { - - private String number; - private String title; - private String state; - private Object milestone; - - @JsonCreator - public GitHubIssue(@JsonProperty("number") String number, @JsonProperty("title") String title, - @JsonProperty("state") String state, @JsonProperty("milestone") Object milestone) { - this.number = number; - this.title = title; - this.state = state; - this.milestone = milestone; - } - - public GitHubIssue(String title, Milestone milestone) { - - this.title = title; - this.milestone = milestone.getNumber(); - this.number = null; - this.state = null; - } - - public String getId() { - - if (number == null) { - return null; - } - return "#".concat(number); - } - - /** - * @author Oliver Gierke - * @author Mark Paluch - */ - @Value - static class Milestone { - - private final String title; - private final Long number; - private final String description; - - @JsonCreator - public Milestone(@JsonProperty("title") String title, @JsonProperty("number") Long number, - @JsonProperty("description") String description) { - this.title = title; - this.number = number; - this.description = description; - } - - public Milestone(String title, String description) { - this.number = null; - this.title = title; - this.description = description; - } - - public boolean matchesIteration(ModuleIteration moduleIteration) { - return title.contains(moduleIteration.getShortVersionString()); - } - } -} diff --git a/release-tools/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java b/release-tools/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java index b270720..222e286 100644 --- a/release-tools/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java +++ b/release-tools/src/main/java/org/springframework/data/release/misc/ReleaseOperations.java @@ -24,8 +24,8 @@ import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.release.git.GitOperations; import org.springframework.data.release.io.Workspace; -import org.springframework.data.release.jira.Changelog; -import org.springframework.data.release.jira.IssueTracker; +import org.springframework.data.release.issues.Changelog; +import org.springframework.data.release.issues.IssueTracker; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.Project; diff --git a/release-tools/src/main/java/org/springframework/data/release/utils/ExecutionUtils.java b/release-tools/src/main/java/org/springframework/data/release/utils/ExecutionUtils.java index 4708427..3f0598a 100644 --- a/release-tools/src/main/java/org/springframework/data/release/utils/ExecutionUtils.java +++ b/release-tools/src/main/java/org/springframework/data/release/utils/ExecutionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2016 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,6 +18,7 @@ package org.springframework.data.release.utils; import java.util.Collection; import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import java.util.stream.Collector; import java.util.stream.Collectors; import org.springframework.data.release.Streamable; @@ -62,16 +63,22 @@ public class ExecutionUtils { * @return */ public static Collection runAndReturn(Streamable streamable, Function function) { + return runAndReturn(streamable, function, Collectors.toList()); + } + + public static R runAndReturn(Streamable streamable, Function function, + Collector collector) { Assert.notNull(streamable, "Iterable must not be null!"); Assert.notNull(function, "Consumer must not be null!"); return streamable.stream().// map(it -> CompletableFuture.supplyAsync(() -> function.apply(it))).// + filter(it -> it != null).// collect(Collectors.toList()).// stream().// map(future -> future.join()).// - collect(Collectors.toList()); + collect(collector); } public static interface ConsumerWithException { diff --git a/release-tools/src/main/resources/application.properties b/release-tools/src/main/resources/application.properties index 08e8d40..7def374 100644 --- a/release-tools/src/main/resources/application.properties +++ b/release-tools/src/main/resources/application.properties @@ -1,7 +1,7 @@ io.work-dir=~/temp/spring-data-shell/workspace # Maven setup -maven.localRepository=~/temp/spring-data-shell/repository +maven.local-repository=~/temp/spring-data-shell/repository maven.plugins.versions=org.codehaus.mojo:versions-maven-plugin:2.2 deployment.server.uri=https://repo.spring.io @@ -12,4 +12,10 @@ deployment.username=buildmaster # GPG setup deployment.gpg.executable=/usr/local/bin/gpg2 # deployment.gpg.keyname -# deployment.gpg.password \ No newline at end of file +# deployment.gpg.password + +# JIRA +jira.api-url=https://jira.spring.io + +# GitHub +github.api-url=https://api.github.com \ No newline at end of file diff --git a/release-tools/src/test/java/org/springframework/data/release/build/MavenIntegrationTests.java b/release-tools/src/test/java/org/springframework/data/release/build/MavenIntegrationTests.java index aaa8d8e..177d9d1 100644 --- a/release-tools/src/test/java/org/springframework/data/release/build/MavenIntegrationTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/build/MavenIntegrationTests.java @@ -30,7 +30,6 @@ import org.springframework.data.release.model.Phase; import org.springframework.data.release.model.Projects; import org.springframework.data.release.model.ReleaseTrains; import org.springframework.data.release.model.TrainIteration; -import org.springframework.data.release.model.UpdateInformation; import org.xmlbeam.ProjectionFactory; import org.xmlbeam.io.XBFileIO; @@ -75,7 +74,7 @@ public class MavenIntegrationTests extends AbstractIntegrationTests { TrainIteration iteration = new TrainIteration(ReleaseTrains.HOPPER, Iteration.M1); ModuleIteration build = iteration.getModule(Projects.BUILD); - UpdateInformation information = new UpdateInformation(iteration, Phase.PREPARE); + UpdateInformation information = UpdateInformation.of(iteration, Phase.PREPARE); maven.updateProjectDescriptors(build, information); maven.prepareVersion(build, Phase.PREPARE); diff --git a/release-tools/src/test/java/org/springframework/data/release/model/UpdateInformationUnitTests.java b/release-tools/src/test/java/org/springframework/data/release/build/UpdateInformationUnitTests.java similarity index 66% rename from release-tools/src/test/java/org/springframework/data/release/model/UpdateInformationUnitTests.java rename to release-tools/src/test/java/org/springframework/data/release/build/UpdateInformationUnitTests.java index 5284f7d..247794a 100644 --- a/release-tools/src/test/java/org/springframework/data/release/model/UpdateInformationUnitTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/build/UpdateInformationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2016 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,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.model; +package org.springframework.data.release.build; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; @@ -21,6 +21,11 @@ import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Test; +import org.springframework.data.release.model.Iteration; +import org.springframework.data.release.model.Phase; +import org.springframework.data.release.model.Projects; +import org.springframework.data.release.model.ReleaseTrains; +import org.springframework.data.release.model.TrainIteration; /** * Unit tests for {@link UpdateInformation}. @@ -33,17 +38,17 @@ public class UpdateInformationUnitTests { @Test(expected = IllegalArgumentException.class) public void rejectsNullTrainIteration() { - new UpdateInformation(null, Phase.CLEANUP); + UpdateInformation.of(null, Phase.CLEANUP); } @Test(expected = IllegalArgumentException.class) public void rejectsNullPhase() { - new UpdateInformation(hopperM1, null); + UpdateInformation.of(hopperM1, null); } @Test public void exposesMilestoneRepositoryForMilestone() { - assertThat(new UpdateInformation(hopperM1, Phase.PREPARE).getRepository().getId(), is("spring-libs-milestone")); + assertThat(UpdateInformation.of(hopperM1, Phase.PREPARE).getRepository().getId(), is("spring-libs-milestone")); } @Test @@ -51,7 +56,7 @@ public class UpdateInformationUnitTests { Arrays.asList(Iteration.GA, Iteration.SR1).forEach(iteration -> { TrainIteration trainIteration = new TrainIteration(ReleaseTrains.HOPPER, iteration); - assertThat(new UpdateInformation(trainIteration, Phase.PREPARE).getRepository().getId(), + assertThat(UpdateInformation.of(trainIteration, Phase.PREPARE).getRepository().getId(), is("spring-libs-release")); }); } @@ -59,10 +64,10 @@ public class UpdateInformationUnitTests { @Test public void calculatesProjectVersionToSetCorrectly() { - UpdateInformation updateInformation = new UpdateInformation(hopperM1, Phase.PREPARE); + UpdateInformation updateInformation = UpdateInformation.of(hopperM1, Phase.PREPARE); assertThat(updateInformation.getProjectVersionToSet(Projects.JPA).toString(), is("1.10.0.M1")); - updateInformation = new UpdateInformation(hopperM1, Phase.CLEANUP); + updateInformation = UpdateInformation.of(hopperM1, Phase.CLEANUP); assertThat(updateInformation.getProjectVersionToSet(Projects.JPA).toString(), is("1.10.0.BUILD-SNAPSHOT")); } } diff --git a/release-tools/src/test/java/org/springframework/data/release/jira/GitHubIssueTrackerIntegrationTests.java b/release-tools/src/test/java/org/springframework/data/release/issues/github/GitHubIssueTrackerIntegrationTests.java similarity index 90% rename from release-tools/src/test/java/org/springframework/data/release/jira/GitHubIssueTrackerIntegrationTests.java rename to release-tools/src/test/java/org/springframework/data/release/issues/github/GitHubIssueTrackerIntegrationTests.java index f4167e7..1fbcbf0 100644 --- a/release-tools/src/test/java/org/springframework/data/release/jira/GitHubIssueTrackerIntegrationTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/issues/github/GitHubIssueTrackerIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.github; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.*; @@ -25,25 +25,31 @@ import java.util.Arrays; import java.util.Collection; import org.hamcrest.Matchers; +import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; 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; import org.springframework.data.release.model.ReleaseTrains; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; import com.github.tomakehurst.wiremock.common.ClasspathFileSource; import com.github.tomakehurst.wiremock.junit.WireMockRule; /** - * Integration Tests for {@link GitHubIssueTracker} using a local {@link WireMockRule} server. + * Integration Tests for {@link GitHub} using a local {@link WireMockRule} server. * * @author Mark Paluch */ @@ -59,11 +65,17 @@ public class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests @Rule public ExpectedException expectedException = ExpectedException.none(); - @Autowired IssueTracker github; + @Autowired GitHub github; + @Autowired GitHubProperties properties; @Before public void before() throws Exception { + + UriComponents uriComponents = UriComponentsBuilder.fromUriString(properties.getApiUrl()).build(); + Assume.assumeThat(uriComponents.getHost(), is("localhost")); + github.reset(); + } /** diff --git a/release-tools/src/test/java/org/springframework/data/release/jira/GithubMilestoneUnitTests.java b/release-tools/src/test/java/org/springframework/data/release/issues/github/GithubMilestoneUnitTests.java similarity index 95% rename from release-tools/src/test/java/org/springframework/data/release/jira/GithubMilestoneUnitTests.java rename to release-tools/src/test/java/org/springframework/data/release/issues/github/GithubMilestoneUnitTests.java index 4260219..c76139e 100644 --- a/release-tools/src/test/java/org/springframework/data/release/jira/GithubMilestoneUnitTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/issues/github/GithubMilestoneUnitTests.java @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.github; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Test; +import org.springframework.data.release.issues.github.GithubMilestone; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.ReleaseTrains; diff --git a/release-tools/src/test/java/org/springframework/data/release/jira/JiraComponentsUnitTests.java b/release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraComponentsUnitTests.java similarity index 90% rename from release-tools/src/test/java/org/springframework/data/release/jira/JiraComponentsUnitTests.java rename to release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraComponentsUnitTests.java index edf5092..24eced6 100644 --- a/release-tools/src/test/java/org/springframework/data/release/jira/JiraComponentsUnitTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraComponentsUnitTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; import static org.hamcrest.core.Is.*; import static org.junit.Assert.*; @@ -22,6 +22,8 @@ import static org.junit.Assert.*; import java.util.Collections; import org.junit.Test; +import org.springframework.data.release.issues.jira.JiraComponent; +import org.springframework.data.release.issues.jira.JiraComponents; /** * Unit tests for {@link JiraComponents}. diff --git a/release-tools/src/test/java/org/springframework/data/release/jira/JiraIntegrationTests.java b/release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraConnectorIntegrationTests.java similarity index 92% rename from release-tools/src/test/java/org/springframework/data/release/jira/JiraIntegrationTests.java rename to release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraConnectorIntegrationTests.java index 6b55437..6a4090a 100644 --- a/release-tools/src/test/java/org/springframework/data/release/jira/JiraIntegrationTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraConnectorIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.*; @@ -26,12 +26,18 @@ import java.util.Collection; import java.util.Optional; import org.hamcrest.Matchers; +import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; 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.jira.Jira; +import org.springframework.data.release.issues.jira.JiraConnector; +import org.springframework.data.release.issues.jira.JiraProperties; +import org.springframework.data.release.issues.jira.JiraReleaseVersion; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.ProjectKey; @@ -39,6 +45,8 @@ import org.springframework.data.release.model.Projects; import org.springframework.data.release.model.ReleaseTrains; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; import com.github.tomakehurst.wiremock.common.ClasspathFileSource; @@ -49,7 +57,7 @@ import com.github.tomakehurst.wiremock.junit.WireMockRule; * * @author Mark Paluch */ -public class JiraIntegrationTests extends AbstractIntegrationTests { +public class JiraConnectorIntegrationTests extends AbstractIntegrationTests { public static final String CREATE_ISSUE_URI = "/rest/api/2/issue"; public static final String CREATE_VERSION_URI = "/rest/api/2/version"; @@ -64,9 +72,14 @@ public class JiraIntegrationTests extends AbstractIntegrationTests { @Rule public ExpectedException expectedException = ExpectedException.none(); @Autowired JiraConnector jira; + @Autowired JiraProperties properties; @Before public void before() throws Exception { + + UriComponents uriComponents = UriComponentsBuilder.fromUriString(properties.getApiUrl()).build(); + Assume.assumeThat(uriComponents.getHost(), is("localhost")); + jira.reset(); } diff --git a/release-tools/src/test/java/org/springframework/data/release/jira/JiraVersionUnitTests.java b/release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraVersionUnitTests.java similarity index 95% rename from release-tools/src/test/java/org/springframework/data/release/jira/JiraVersionUnitTests.java rename to release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraVersionUnitTests.java index 2c02e09..afbe1b8 100644 --- a/release-tools/src/test/java/org/springframework/data/release/jira/JiraVersionUnitTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/issues/jira/JiraVersionUnitTests.java @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Test; +import org.springframework.data.release.issues.jira.JiraVersion; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ModuleIteration; import org.springframework.data.release.model.ReleaseTrains; diff --git a/release-tools/src/test/java/org/springframework/data/release/jira/TicketsUnitTests.java b/release-tools/src/test/java/org/springframework/data/release/issues/jira/TicketsUnitTests.java similarity index 93% rename from release-tools/src/test/java/org/springframework/data/release/jira/TicketsUnitTests.java rename to release-tools/src/test/java/org/springframework/data/release/issues/jira/TicketsUnitTests.java index 424eb0e..e981326 100644 --- a/release-tools/src/test/java/org/springframework/data/release/jira/TicketsUnitTests.java +++ b/release-tools/src/test/java/org/springframework/data/release/issues/jira/TicketsUnitTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.data.release.jira; +package org.springframework.data.release.issues.jira; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; @@ -23,6 +23,9 @@ import static org.springframework.test.util.AssertionErrors.fail; import java.util.Collections; import org.junit.Test; +import org.springframework.data.release.issues.Ticket; +import org.springframework.data.release.issues.Tickets; +import org.springframework.data.release.issues.jira.JiraTicketStatus; import org.springframework.data.release.model.Iteration; import org.springframework.data.release.model.ReleaseTrains; @@ -93,5 +96,4 @@ public class TicketsUnitTests { .getReleaseTickets(ReleaseTrains.HOPPER.getModuleIteration(Iteration.GA, "JPA").getTrainIteration()); assertThat(result.getTickets().contains(ticket), is(true)); } - } diff --git a/release-tools/src/test/resources/application-test.properties b/release-tools/src/test/resources/application-test.properties index 4dfd272..8acb6a1 100644 --- a/release-tools/src/test/resources/application-test.properties +++ b/release-tools/src/test/resources/application-test.properties @@ -2,11 +2,12 @@ logging.level.org.springframework=WARN logging.level.org.springframework.data.release=INFO logging.level.org.springframework.web.client=TRACE +logging.level.org.springframework.http=DEBUG # Deployment deployment.repository-prefix=test- jira.username=dummy jira.password=dummy -jira.url=http://localhost:8888 -github.api.url=http://localhost:8888 \ No newline at end of file +jira.api-url=http://localhost:8888 +github.api-url=http://localhost:8888 \ No newline at end of file