Update git changelog command to use issue tracker.

See #166
This commit is contained in:
Mark Paluch
2021-01-12 14:49:58 +01:00
parent ebadf0a5ea
commit 7cf21144cd
7 changed files with 69 additions and 27 deletions

View File

@@ -18,6 +18,7 @@ package org.springframework.data.release.git;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -28,14 +29,18 @@ import java.util.stream.Stream;
import org.springframework.data.release.CliComponent;
import org.springframework.data.release.TimedCommand;
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.TicketReference;
import org.springframework.data.release.issues.Tickets;
import org.springframework.data.release.model.ArtifactVersion;
import org.springframework.data.release.model.ModuleIteration;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.ReleaseTrains;
import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
import org.springframework.data.release.utils.ExecutionUtils;
import org.springframework.plugin.core.PluginRegistry;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.shell.support.table.Table;
@@ -50,6 +55,7 @@ import org.springframework.util.StringUtils;
@RequiredArgsConstructor
class GitCommands extends TimedCommand {
private final PluginRegistry<IssueTracker, Project> trackers;
private final @NonNull GitOperations git;
private final @NonNull Executor executor;
@@ -87,23 +93,33 @@ class GitCommands extends TimedCommand {
TrainIteration previousIteration = git.getPreviousIteration(iteration);
return ExecutionUtils.runAndReturn(executor, iteration, moduleIteration -> {
return ExecutionUtils.runAndReturn(executor, iteration, module -> {
List<TicketReference> ticketRefs = git.getTicketReferencesBetween(moduleIteration.getProject(), previousIteration,
List<TicketReference> ticketRefs = git.getTicketReferencesBetween(module.getProject(), previousIteration,
iteration);
return Changelog.of(moduleIteration, toTickets(ticketRefs));
return Changelog.of(module, toTickets(module, ticketRefs));
}).stream() //
.map(Changelog::toString) //
.map(changelog -> {
ModuleIteration module = changelog.getModule();
return String.format("%s %s%n%s", module.getModule().getProject().getFullName(), ArtifactVersion.of(module),
changelog.toString(false, " "));
}) //
.collect(Collectors.joining("\n"));
}
private Tickets toTickets(List<TicketReference> ticketRefs) {
private Tickets toTickets(ModuleIteration module, List<TicketReference> ticketReferences) {
return new Tickets(
ticketRefs.stream().map(it -> new Ticket(it.getId(), it.getMessage(), "", null, null))
.collect(Collectors.toList()));
// TODO: Use only associated tracker
List<Ticket> tickets = new ArrayList<>();
for (IssueTracker tracker : trackers) {
tickets.addAll(tracker.findTickets(module, ticketReferences).getTickets());
}
return new Tickets(tickets);
}
/**

View File

@@ -54,10 +54,10 @@ class ParsedCommitMessage {
.compile(String.format("(%s|%s)", JIRA_TICKET.pattern(), GITHUB_TICKET.pattern()));
private static final Pattern ORIGINAL_PULL_REQUEST = Pattern
.compile("Original (?>pull request|PR|pullrequest):(?>\\s+)?" + A_TICKET.pattern(), Pattern.CASE_INSENSITIVE);
.compile("Original (?>pull request|PR|pullrequest)[:]*(?>\\s+)?" + A_TICKET.pattern(), Pattern.CASE_INSENSITIVE);
private static final Pattern RELATED_TICKET = Pattern.compile(
"Related (?>tickets|ticket):(?>\\s+)?((" + A_TICKET.pattern() + "(?>[\\s,]*))+)", Pattern.CASE_INSENSITIVE);
"Related (?>tickets|ticket)[:]*(?>\\s+)?((" + A_TICKET.pattern() + "(?>[\\s,]*))+)", Pattern.CASE_INSENSITIVE);
private final String summary;
private final @Nullable String body;

View File

@@ -16,6 +16,7 @@
package org.springframework.data.release.issues;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Date;
@@ -34,7 +35,7 @@ import org.springframework.format.datetime.DateFormatter;
@EqualsAndHashCode
public class Changelog {
private final ModuleIteration module;
@Getter private final ModuleIteration module;
private final Tickets tickets;
/*
@@ -43,25 +44,35 @@ public class Changelog {
*/
@Override
public String toString() {
return toString(true, "");
}
public String toString(boolean header, String indentation) {
ArtifactVersion version = ArtifactVersion.of(module);
String headline = String.format("Changes in version %s (%s)", version,
new DateFormatter("YYYY-MM-dd").print(new Date(), Locale.US));
StringBuilder builder = new StringBuilder(headline).append(IOUtils.LINE_SEPARATOR);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < headline.length(); i++) {
builder.append("-");
if (header) {
builder.append(indentation).append(headline).append(IOUtils.LINE_SEPARATOR).append(indentation);
for (int i = 0; i < headline.length(); i++) {
builder.append("-");
}
builder.append(IOUtils.LINE_SEPARATOR);
}
builder.append(IOUtils.LINE_SEPARATOR);
for (Ticket ticket : tickets) {
String summary = ticket.getSummary();
builder.append("* ").append(ticket.getId()).append(" - ").append(summary != null ? summary.trim() : "");
builder.append(indentation).append("* ").append(ticket.getId()).append(" - ")
.append(summary != null ? summary.trim() : "");
if (!summary.endsWith(".")) {
builder.append(".");

View File

@@ -136,8 +136,8 @@ class IssueTrackerCommands extends TimedCommand {
.toString();
}
@CliCommand("tracker changelog")
public String changelog(@CliOption(key = "", mandatory = true) TrainIteration iteration, //
@CliCommand("tracker open-tickets")
public String openTickets(@CliOption(key = "", mandatory = true) TrainIteration iteration, //
@CliOption(key = "module") String moduleName) {
if (StringUtils.hasText(moduleName)) {
@@ -145,11 +145,15 @@ class IssueTrackerCommands extends TimedCommand {
Project project = Projects.requiredByName(moduleName);
ModuleIteration module = iteration.getModule(project);
return getTrackerFor(module).getChangelogFor(module).toString();
String tickets = getTrackerFor(module).getTicketsFor(module).stream().filter(it -> !it.isResolved())
.collect(Tickets.toTicketsCollector()).toString(false);
return String.format("%s - %s%n%s%n", project.getFullName(), module.getFullVersionString(), tickets);
}
return ExecutionUtils.runAndReturn(executor, iteration, this::getChangelog).//
stream().map(it -> it.toString()).collect(Collectors.joining("\n"));
return ExecutionUtils.runAndReturn(executor, iteration,
moduleIteration -> openTickets(iteration, moduleIteration.getModule().getProject().getName())).//
stream().collect(Collectors.joining("\n"));
}
@CliCommand("tracker close")

View File

@@ -98,11 +98,17 @@ public class Tickets implements Streamable<Ticket> {
*/
@Override
public String toString() {
return toString(true);
}
public String toString(boolean header) {
StringBuilder builder = new StringBuilder();
builder.append(String.format("Train only tickets: %s of %s", tickets.size(), overallTotal));
builder.append(IOUtils.LINE_SEPARATOR);
if (header) {
builder.append(String.format("Train only tickets: %s of %s", tickets.size(), overallTotal));
builder.append(IOUtils.LINE_SEPARATOR);
}
builder.append(tickets.stream().map(it -> "\t" + it).collect(Collectors.joining(IOUtils.LINE_SEPARATOR)));
return builder.toString();

View File

@@ -593,6 +593,10 @@ class Jira implements JiraConnector {
.filter(it -> it.getId().startsWith(moduleIteration.getProjectKey().getKey())).map(TicketReference::getId)
.collect(Collectors.toList());
if (ids.isEmpty()) {
return new Tickets(Collections.emptyList());
}
Map<String, Object> parameters = newUrlTemplateVariables();
parameters.put("jql", JqlQuery.from(ids));
parameters.put("fields", "summary,status,resolution,fixVersions");

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
@@ -131,9 +132,9 @@ public class Projects {
public static Optional<Project> byName(String name) {
return PROJECTS.stream().//
filter(project -> project.getName().equalsIgnoreCase(name) || project.getKey().toString().equals(name)).//
findFirst();
return Stream.concat(Stream.of(BOM), PROJECTS.stream()) //
.filter(project -> project.getName().equalsIgnoreCase(name) || project.getKey().toString().equals(name))//
.findFirst();
}
public static Project requiredByName(String name) {