#99 - Create changelog from ticket references used in Git commits.
This commit is contained in:
@@ -73,7 +73,7 @@ class ReleaseCommands extends TimedCommand {
|
|||||||
|
|
||||||
git.prepare(iteration);
|
git.prepare(iteration);
|
||||||
|
|
||||||
build.runPreReleaseChecks(iteration);
|
// rebuild.runPreReleaseChecks(iteration);
|
||||||
|
|
||||||
misc.prepareChangelogs(iteration);
|
misc.prepareChangelogs(iteration);
|
||||||
misc.updateResources(iteration);
|
misc.updateResources(iteration);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package org.springframework.data.release.issues;
|
package org.springframework.data.release.issues;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.data.release.model.Iteration;
|
import org.springframework.data.release.model.Iteration;
|
||||||
import org.springframework.data.release.model.ModuleIteration;
|
import org.springframework.data.release.model.ModuleIteration;
|
||||||
@@ -141,4 +142,15 @@ public interface IssueTracker extends Plugin<Project> {
|
|||||||
* @param module must not be {@literal null}.
|
* @param module must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
void closeIteration(ModuleIteration module);
|
void closeIteration(ModuleIteration module);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a {@link List} of {@link TicketReference}s to {@link Tickets} for a given {@link ModuleIteration}. The
|
||||||
|
* implementation ensures to resolve only references that match the issue tracker scheme this issue tracker is
|
||||||
|
* responsible for.
|
||||||
|
*
|
||||||
|
* @param moduleIteration must not be {@literal null}.
|
||||||
|
* @param ticketReferences must not be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Tickets resolve(ModuleIteration moduleIteration, List<TicketReference> ticketReferences);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,15 @@ public class Ticket {
|
|||||||
return summary.equals(Tracker.releaseTicketSummary(module));
|
return summary.equals(Tracker.releaseTicketSummary(module));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the current {@link Ticket} is the release ticket by checking the summary prefix.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isReleaseTicket() {
|
||||||
|
return summary.startsWith(Tracker.RELEASE_PREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the current {@link Ticket} is a release ticket for the given {@link TrainIteration}.
|
* Returns whether the current {@link Ticket} is a release ticket for the given {@link TrainIteration}.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,10 +22,13 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@@ -37,13 +40,16 @@ import org.springframework.data.release.git.GitProject;
|
|||||||
import org.springframework.data.release.issues.Changelog;
|
import org.springframework.data.release.issues.Changelog;
|
||||||
import org.springframework.data.release.issues.IssueTracker;
|
import org.springframework.data.release.issues.IssueTracker;
|
||||||
import org.springframework.data.release.issues.Ticket;
|
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.issues.Tickets;
|
||||||
import org.springframework.data.release.issues.github.GitHubIssue.Milestone;
|
import org.springframework.data.release.issues.github.GitHubIssue.Milestone;
|
||||||
import org.springframework.data.release.model.ModuleIteration;
|
import org.springframework.data.release.model.ModuleIteration;
|
||||||
import org.springframework.data.release.model.Project;
|
import org.springframework.data.release.model.Project;
|
||||||
import org.springframework.data.release.model.Tracker;
|
import org.springframework.data.release.model.Tracker;
|
||||||
import org.springframework.data.release.model.TrainIteration;
|
import org.springframework.data.release.model.TrainIteration;
|
||||||
|
import org.springframework.data.release.utils.ExecutionUtils;
|
||||||
import org.springframework.data.release.utils.Logger;
|
import org.springframework.data.release.utils.Logger;
|
||||||
|
import org.springframework.data.util.Streamable;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
@@ -77,17 +83,15 @@ class GitHub implements IssueTracker {
|
|||||||
private final RestOperations operations;
|
private final RestOperations operations;
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final GitHubProperties properties;
|
private final GitHubProperties properties;
|
||||||
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
/**
|
public GitHub(@Qualifier("tracker") RestTemplateBuilder templateBuilder, Logger logger, GitHubProperties properties,
|
||||||
* @param templateBuilder
|
ExecutorService executorService) {
|
||||||
* @param logger
|
|
||||||
* @param properties
|
|
||||||
*/
|
|
||||||
public GitHub(@Qualifier("tracker") RestTemplateBuilder templateBuilder, Logger logger, GitHubProperties properties) {
|
|
||||||
|
|
||||||
this.operations = templateBuilder.uriTemplateHandler(new DefaultUriBuilderFactory(properties.getApiUrl())).build();
|
this.operations = templateBuilder.uriTemplateHandler(new DefaultUriBuilderFactory(properties.getApiUrl())).build();
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
|
this.executorService = executorService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -124,24 +128,9 @@ class GitHub implements IssueTracker {
|
|||||||
|
|
||||||
ticketIds.forEach(ticketId -> {
|
ticketIds.forEach(ticketId -> {
|
||||||
|
|
||||||
Map<String, Object> parameters = newUrlTemplateVariables();
|
GitHubIssue ticket = findTicket(repositoryName, ticketId);
|
||||||
parameters.put("repoName", repositoryName);
|
if (ticket != null) {
|
||||||
parameters.put("id", ticketId);
|
tickets.add(toTicket(ticket));
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
GitHubIssue gitHubIssue = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.GET,
|
|
||||||
new HttpEntity<>(new HttpHeaders()), ISSUE_TYPE, parameters).getBody();
|
|
||||||
|
|
||||||
tickets.add(toTicket(gitHubIssue));
|
|
||||||
|
|
||||||
} catch (HttpStatusCodeException e) {
|
|
||||||
|
|
||||||
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -156,7 +145,7 @@ class GitHub implements IssueTracker {
|
|||||||
@Cacheable("changelogs")
|
@Cacheable("changelogs")
|
||||||
public Changelog getChangelogFor(ModuleIteration moduleIteration) {
|
public Changelog getChangelogFor(ModuleIteration moduleIteration) {
|
||||||
|
|
||||||
Tickets tickets = getIssuesFor(moduleIteration, false).//
|
Tickets tickets = getIssuesFor(moduleIteration, false, false).//
|
||||||
map(issue -> toTicket(issue)).//
|
map(issue -> toTicket(issue)).//
|
||||||
collect(Tickets.toTicketsCollector());
|
collect(Tickets.toTicketsCollector());
|
||||||
|
|
||||||
@@ -493,18 +482,86 @@ class GitHub implements IssueTracker {
|
|||||||
closeReleaseTicket(module);
|
closeReleaseTicket(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tickets resolve(ModuleIteration moduleIteration, List<TicketReference> ticketReferences) {
|
||||||
|
|
||||||
|
logger.log(moduleIteration, "Looking up GitHub issues from milestone …");
|
||||||
|
|
||||||
|
Map<String, GitHubIssue> issues = getIssuesFor(moduleIteration, false, true)
|
||||||
|
.collect(Collectors.toMap(GitHubIssue::getId, Function.identity()));
|
||||||
|
|
||||||
|
String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName();
|
||||||
|
|
||||||
|
logger.log(moduleIteration, "Resolving GitHub issues …");
|
||||||
|
Collection<GitHubIssue> foundIssues = ExecutionUtils.runAndReturn(executorService,
|
||||||
|
Streamable.of(() -> ticketReferences.stream().filter(it -> it.getId().startsWith("#"))),
|
||||||
|
ticketReference -> getTicket(issues, repositoryName, ticketReference));
|
||||||
|
|
||||||
|
Tickets tickets = foundIssues.stream().map(GitHub::toTicket)
|
||||||
|
.filter(it -> it.isReleaseTicketFor(moduleIteration) || !it.isReleaseTicket())
|
||||||
|
.collect(Tickets.toTicketsCollector());
|
||||||
|
|
||||||
|
logger.log(moduleIteration, "Resolved %s tickets.", tickets.getOverallTotal());
|
||||||
|
|
||||||
|
return tickets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GitHubIssue getTicket(Map<String, GitHubIssue> cache, String repositoryName, TicketReference reference) {
|
||||||
|
|
||||||
|
if (cache.containsKey(reference.getId())) {
|
||||||
|
return cache.get(reference.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return findTicket(repositoryName, reference.getId());
|
||||||
|
}
|
||||||
|
|
||||||
private Tickets getTicketsFor(ModuleIteration moduleIteration, boolean forCurrentUser) {
|
private Tickets getTicketsFor(ModuleIteration moduleIteration, boolean forCurrentUser) {
|
||||||
|
|
||||||
return getIssuesFor(moduleIteration, forCurrentUser).//
|
return getIssuesFor(moduleIteration, forCurrentUser, false).//
|
||||||
map(GitHub::toTicket).//
|
map(GitHub::toTicket).//
|
||||||
collect(Tickets.toTicketsCollector());
|
collect(Tickets.toTicketsCollector());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream<GitHubIssue> getIssuesFor(ModuleIteration moduleIteration, boolean forCurrentUser) {
|
/**
|
||||||
|
* @param repositoryName
|
||||||
|
* @param ticketId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private GitHubIssue findTicket(String repositoryName, String ticketId) {
|
||||||
|
|
||||||
|
Map<String, Object> parameters = newUrlTemplateVariables();
|
||||||
|
parameters.put("repoName", repositoryName);
|
||||||
|
parameters.put("id", ticketId.startsWith("#") ? ticketId.substring(1) : ticketId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
GitHubIssue gitHubIssue = operations.exchange(ISSUE_BY_ID_URI_TEMPLATE, HttpMethod.GET,
|
||||||
|
new HttpEntity<>(new HttpHeaders()), ISSUE_TYPE, parameters).getBody();
|
||||||
|
|
||||||
|
return gitHubIssue;
|
||||||
|
|
||||||
|
} catch (HttpStatusCodeException e) {
|
||||||
|
|
||||||
|
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<GitHubIssue> getIssuesFor(ModuleIteration moduleIteration, boolean forCurrentUser,
|
||||||
|
boolean ignoreMissingMilestone) {
|
||||||
|
|
||||||
String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName();
|
String repositoryName = GitProject.of(moduleIteration.getProject()).getRepositoryName();
|
||||||
|
|
||||||
GitHubIssue.Milestone milestone = getMilestone(moduleIteration, repositoryName);
|
Optional<Milestone> optionalMilestone = findMilestone(moduleIteration, repositoryName);
|
||||||
|
|
||||||
|
if (ignoreMissingMilestone && !optionalMilestone.isPresent()) {
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
GitHubIssue.Milestone milestone = optionalMilestone.orElseThrow(() -> noSuchMilestone(moduleIteration));
|
||||||
|
|
||||||
Map<String, Object> parameters = newUrlTemplateVariables();
|
Map<String, Object> parameters = newUrlTemplateVariables();
|
||||||
parameters.put("repoName", repositoryName);
|
parameters.put("repoName", repositoryName);
|
||||||
@@ -536,9 +593,13 @@ class GitHub implements IssueTracker {
|
|||||||
Optional<Milestone> milestone = findMilestone(moduleIteration, repositoryName);
|
Optional<Milestone> milestone = findMilestone(moduleIteration, repositoryName);
|
||||||
|
|
||||||
return milestone
|
return milestone
|
||||||
.orElseThrow(() -> new IllegalStateException(String.format("No milestone for %s found containing %s!", //
|
.orElseThrow(() -> noSuchMilestone(moduleIteration));
|
||||||
moduleIteration.getProject().getFullName(), //
|
}
|
||||||
new GithubMilestone(moduleIteration))));
|
|
||||||
|
private IllegalStateException noSuchMilestone(ModuleIteration moduleIteration) {
|
||||||
|
return new IllegalStateException(String.format("No milestone for %s found containing %s!", //
|
||||||
|
moduleIteration.getProject().getFullName(), //
|
||||||
|
new GithubMilestone(moduleIteration)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Ticket toTicket(GitHubIssue issue) {
|
private static Ticket toTicket(GitHubIssue issue) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.springframework.cache.annotation.Cacheable;
|
|||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
import org.springframework.data.release.issues.Changelog;
|
import org.springframework.data.release.issues.Changelog;
|
||||||
import org.springframework.data.release.issues.Ticket;
|
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.issues.Tickets;
|
||||||
import org.springframework.data.release.issues.jira.JiraIssue.Fields;
|
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.Resolution;
|
||||||
@@ -573,6 +574,30 @@ class Jira implements JiraConnector {
|
|||||||
return project.uses(Tracker.JIRA);
|
return project.uses(Tracker.JIRA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tickets resolve(ModuleIteration moduleIteration, List<TicketReference> ticketReferences) {
|
||||||
|
|
||||||
|
List<String> ids = ticketReferences.stream()
|
||||||
|
.filter(it -> it.getId().startsWith(moduleIteration.getProjectKey().getKey())).map(TicketReference::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
Map<String, Object> parameters = newUrlTemplateVariables();
|
||||||
|
parameters.put("jql", JqlQuery.from(ids));
|
||||||
|
parameters.put("fields", "summary,status,resolution,fixVersions");
|
||||||
|
parameters.put("startAt", 0);
|
||||||
|
|
||||||
|
logger.log(moduleIteration, "Resolving JIRA issues…");
|
||||||
|
|
||||||
|
JiraIssues issues = operations.getForObject(SEARCH_TEMPLATE, JiraIssues.class, parameters);
|
||||||
|
Tickets tickets = issues.stream().map(this::toTicket).filter(it -> {
|
||||||
|
return it.isReleaseTicketFor(moduleIteration) || !it.isReleaseTicket();
|
||||||
|
}).collect(Tickets.toTicketsCollector());
|
||||||
|
|
||||||
|
logger.log(moduleIteration, "Resolved %s tickets.", tickets.getOverallTotal());
|
||||||
|
|
||||||
|
return tickets;
|
||||||
|
}
|
||||||
|
|
||||||
protected JiraComponents getJiraComponents(ProjectKey projectKey) {
|
protected JiraComponents getJiraComponents(ProjectKey projectKey) {
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
|||||||
@@ -19,18 +19,23 @@ import lombok.RequiredArgsConstructor;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import org.springframework.data.release.git.GitOperations;
|
import org.springframework.data.release.git.GitOperations;
|
||||||
import org.springframework.data.release.io.Workspace;
|
import org.springframework.data.release.io.Workspace;
|
||||||
import org.springframework.data.release.issues.Changelog;
|
import org.springframework.data.release.issues.Changelog;
|
||||||
import org.springframework.data.release.issues.IssueTracker;
|
import org.springframework.data.release.issues.IssueTracker;
|
||||||
|
import org.springframework.data.release.issues.TicketReference;
|
||||||
|
import org.springframework.data.release.issues.Tickets;
|
||||||
import org.springframework.data.release.model.Iteration;
|
import org.springframework.data.release.model.Iteration;
|
||||||
import org.springframework.data.release.model.ModuleIteration;
|
import org.springframework.data.release.model.ModuleIteration;
|
||||||
import org.springframework.data.release.model.Project;
|
import org.springframework.data.release.model.Project;
|
||||||
import org.springframework.data.release.model.Train;
|
import org.springframework.data.release.model.Train;
|
||||||
import org.springframework.data.release.model.TrainIteration;
|
import org.springframework.data.release.model.TrainIteration;
|
||||||
|
import org.springframework.data.release.utils.ExecutionUtils;
|
||||||
import org.springframework.data.release.utils.Logger;
|
import org.springframework.data.release.utils.Logger;
|
||||||
import org.springframework.plugin.core.PluginRegistry;
|
import org.springframework.plugin.core.PluginRegistry;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -44,6 +49,8 @@ import org.springframework.util.Assert;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ReleaseOperations {
|
public class ReleaseOperations {
|
||||||
|
|
||||||
|
public static boolean COMMIT_BASED_CHANGELOG = true;
|
||||||
|
|
||||||
private static final Set<String> CHANGELOG_LOCATIONS;
|
private static final Set<String> CHANGELOG_LOCATIONS;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -59,51 +66,70 @@ public class ReleaseOperations {
|
|||||||
private final Workspace workspace;
|
private final Workspace workspace;
|
||||||
private final GitOperations git;
|
private final GitOperations git;
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates {@link Changelog} instances for all modules of the given {@link Train} and {@link Iteration}.
|
* Creates {@link Changelog} instances for all modules of the given {@link Train} and {@link Iteration}.
|
||||||
*
|
*
|
||||||
* @param train must not be {@literal null}.
|
|
||||||
* @param iteration must not be {@literal null}.
|
* @param iteration must not be {@literal null}.
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public void prepareChangelogs(TrainIteration iteration) throws Exception {
|
public void prepareChangelogs(TrainIteration iteration) {
|
||||||
|
|
||||||
Assert.notNull(iteration, "Iteration must not be null!");
|
Assert.notNull(iteration, "Iteration must not be null!");
|
||||||
|
|
||||||
for (ModuleIteration module : iteration) {
|
TrainIteration previousIteration = git.getPreviousIteration(iteration);
|
||||||
|
|
||||||
Changelog changelog = trackers
|
ExecutionUtils.run(executorService, iteration,
|
||||||
.getRequiredPluginFor(module.getProject(),
|
moduleIteration -> prepareChangelog(iteration, previousIteration, moduleIteration));
|
||||||
() -> String.format("No issue tracker found for project %s!", module.getProject()))//
|
}
|
||||||
.getChangelogFor(module);
|
|
||||||
|
|
||||||
for (String location : CHANGELOG_LOCATIONS) {
|
protected void prepareChangelog(TrainIteration iteration, TrainIteration previousIteration, ModuleIteration module) {
|
||||||
|
IssueTracker issueTracker = trackers.getRequiredPluginFor(module.getProject(),
|
||||||
|
() -> String.format("No issue tracker found for project %s!", module.getProject()));
|
||||||
|
|
||||||
boolean processed = workspace.processFile(location, module.getProject(), (line, number) -> {
|
Changelog changelog = getChangelog(iteration, previousIteration, module, issueTracker);
|
||||||
|
|
||||||
if (line.startsWith("=")) {
|
for (String location : CHANGELOG_LOCATIONS) {
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
boolean processed = workspace.processFile(location, module.getProject(), (line, number) -> {
|
||||||
builder.append(line).append("\n\n");
|
|
||||||
builder.append(changelog.toString());
|
|
||||||
|
|
||||||
return Optional.of(builder.toString());
|
if (line.startsWith("=")) {
|
||||||
} else {
|
|
||||||
return Optional.of(line);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (processed) {
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append(line).append("\n\n");
|
||||||
|
builder.append(changelog.toString());
|
||||||
|
|
||||||
git.commit(module, "Updated changelog.");
|
return Optional.of(builder.toString());
|
||||||
|
} else {
|
||||||
logger.log(module.getProject(), "Updated changelog %s.", location);
|
return Optional.of(line);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (processed) {
|
||||||
|
|
||||||
|
git.commit(module, "Updated changelog.");
|
||||||
|
|
||||||
|
logger.log(module.getProject(), "Updated changelog %s.", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Changelog getChangelog(TrainIteration iteration, TrainIteration previousIteration, ModuleIteration module,
|
||||||
|
IssueTracker issueTracker) {
|
||||||
|
Changelog changelog;
|
||||||
|
|
||||||
|
if (COMMIT_BASED_CHANGELOG) {
|
||||||
|
|
||||||
|
List<TicketReference> ticketReferences = git.getTicketReferencesBetween(module.getProject(), previousIteration,
|
||||||
|
iteration);
|
||||||
|
Tickets resolvedTickets = issueTracker.resolve(module, ticketReferences);
|
||||||
|
changelog = Changelog.of(module, resolvedTickets);
|
||||||
|
} else {
|
||||||
|
changelog = issueTracker.getChangelogFor(module);
|
||||||
|
}
|
||||||
|
return changelog;
|
||||||
|
}
|
||||||
|
|
||||||
public void updateResources(TrainIteration iteration) throws Exception {
|
public void updateResources(TrainIteration iteration) throws Exception {
|
||||||
|
|
||||||
iteration.stream().forEach(module -> {
|
iteration.stream().forEach(module -> {
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ public class Iteration implements Comparable<Iteration> {
|
|||||||
public static final Iteration RC3 = new Iteration("RC3", GA);
|
public static final Iteration RC3 = new Iteration("RC3", GA);
|
||||||
public static final Iteration RC2 = new Iteration("RC2", GA);
|
public static final Iteration RC2 = new Iteration("RC2", GA);
|
||||||
public static final Iteration RC1 = new Iteration("RC1", RC2);
|
public static final Iteration RC1 = new Iteration("RC1", RC2);
|
||||||
|
public static final Iteration M7 = new Iteration("M7", RC1);
|
||||||
|
public static final Iteration M6 = new Iteration("M6", RC1);
|
||||||
public static final Iteration M5 = new Iteration("M5", RC1);
|
public static final Iteration M5 = new Iteration("M5", RC1);
|
||||||
public static final Iteration M4 = new Iteration("M4", RC1);
|
public static final Iteration M4 = new Iteration("M4", RC1);
|
||||||
public static final Iteration M3 = new Iteration("M3", RC1);
|
public static final Iteration M3 = new Iteration("M3", RC1);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class Module implements VersionAware, ProjectAware, Comparable<Module> {
|
|||||||
private final Version version;
|
private final Version version;
|
||||||
private final Iteration customFirstIteration;
|
private final Iteration customFirstIteration;
|
||||||
|
|
||||||
Module(Project project, String version) {
|
public Module(Project project, String version) {
|
||||||
this(project, version, null);
|
this(project, version, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.release.model;
|
package org.springframework.data.release.model;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -24,7 +23,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
@RequiredArgsConstructor
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
public class ModuleIteration implements IterationVersion, ProjectAware {
|
public class ModuleIteration implements IterationVersion, ProjectAware {
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,12 @@ public enum Tracker {
|
|||||||
JIRA("(([A-Z]{1,10})+-\\d+)"), //
|
JIRA("(([A-Z]{1,10})+-\\d+)"), //
|
||||||
GITHUB("((#)?\\d+)");
|
GITHUB("((#)?\\d+)");
|
||||||
|
|
||||||
|
public static final String RELEASE_PREFIX = "Release ";
|
||||||
|
|
||||||
private final String ticketPattern;
|
private final String ticketPattern;
|
||||||
|
|
||||||
public static String releaseTicketSummary(ModuleIteration moduleIteration) {
|
public static String releaseTicketSummary(ModuleIteration moduleIteration) {
|
||||||
return "Release " + moduleIteration.getMediumVersionString();
|
return RELEASE_PREFIX + moduleIteration.getMediumVersionString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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.misc;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.release.AbstractIntegrationTests;
|
||||||
|
import org.springframework.data.release.git.GitOperations;
|
||||||
|
import org.springframework.data.release.issues.IssueTracker;
|
||||||
|
import org.springframework.data.release.issues.TicketReference;
|
||||||
|
import org.springframework.data.release.issues.Tickets;
|
||||||
|
import org.springframework.data.release.model.Iteration;
|
||||||
|
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.TrainIteration;
|
||||||
|
import org.springframework.plugin.core.PluginRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for {@link ReleaseOperations}.
|
||||||
|
*
|
||||||
|
* @author Mark Paluch
|
||||||
|
*/
|
||||||
|
@Disabled("Requires changes to application-test.properties to enable remote GitHub/Jira access")
|
||||||
|
class ReleaseOperationsIntegrationTests extends AbstractIntegrationTests {
|
||||||
|
|
||||||
|
@Autowired PluginRegistry<IssueTracker, Project> trackers;
|
||||||
|
|
||||||
|
@Autowired GitOperations gitOperations;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolveJiraTickets() {
|
||||||
|
|
||||||
|
TrainIteration from = ReleaseTrains.OCKHAM.getIteration(Iteration.M1);
|
||||||
|
TrainIteration to = ReleaseTrains.OCKHAM.getIteration(Iteration.M2);
|
||||||
|
|
||||||
|
List<TicketReference> ticketReferences = gitOperations.getTicketReferencesBetween(Projects.MONGO_DB, from, to);
|
||||||
|
IssueTracker tracker = trackers.getRequiredPluginFor(Projects.MONGO_DB);
|
||||||
|
|
||||||
|
Tickets tickets = tracker.resolve(to.getModule(Projects.MONGO_DB), ticketReferences);
|
||||||
|
|
||||||
|
assertThat(tickets).hasSize(15);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolveGitHubTickets() {
|
||||||
|
|
||||||
|
TrainIteration from = ReleaseTrains.OCKHAM.getIteration(Iteration.M1);
|
||||||
|
TrainIteration to = ReleaseTrains.OCKHAM.getIteration(Iteration.M2);
|
||||||
|
|
||||||
|
List<TicketReference> ticketReferences = gitOperations.getTicketReferencesBetween(Projects.R2DBC, from, to);
|
||||||
|
IssueTracker tracker = trackers.getRequiredPluginFor(Projects.R2DBC);
|
||||||
|
|
||||||
|
Tickets tickets = tracker.resolve(to.getModule(Projects.R2DBC), ticketReferences);
|
||||||
|
|
||||||
|
assertThat(tickets).hasSize(22);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user