Include contributors from pull request references in GitHub release notes.
Closes #78
This commit is contained in:
@@ -119,8 +119,7 @@ class GitCommands extends TimedCommand {
|
||||
IssueTracker issueTracker = trackers.getRequiredPluginFor(module.getSupportedProject(),
|
||||
() -> String.format("No issue tracker found for project %s!", module.getSupportedProject()));
|
||||
|
||||
List<String> ticketIds = ticketReferences.stream().map(TicketReference::getId).collect(Collectors.toList());
|
||||
|
||||
List<TicketReference> ticketIds = ticketReferences.stream().filter(TicketReference::isIssue).collect(Collectors.toList());
|
||||
List<Ticket> tickets = new ArrayList<>(issueTracker.findTickets(module, ticketIds).getTickets());
|
||||
|
||||
return new Tickets(tickets);
|
||||
|
||||
@@ -68,7 +68,6 @@ import org.springframework.data.release.issues.Ticket;
|
||||
import org.springframework.data.release.issues.TicketReference;
|
||||
import org.springframework.data.release.issues.TicketStatus;
|
||||
import org.springframework.data.release.model.*;
|
||||
import org.springframework.data.release.model.Module;
|
||||
import org.springframework.data.release.utils.ExecutionUtils;
|
||||
import org.springframework.data.release.utils.Logger;
|
||||
import org.springframework.data.util.Pair;
|
||||
@@ -435,7 +434,10 @@ public class GitOperations {
|
||||
.filter(branch -> branch.isIssueBranch(project.getProject().getTracker()))//
|
||||
.collect(Collectors.toMap(Branch::toString, branch -> branch));
|
||||
|
||||
Collection<Ticket> tickets = tracker.findTickets(project, ticketIds.keySet());
|
||||
Collection<Ticket> tickets = tracker.findTickets(project,
|
||||
ticketIds.keySet().stream()
|
||||
.map(it -> TicketReference.ofTicket(it, TicketReference.Style.GitHub))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
return TicketBranches
|
||||
.from(tickets.stream().collect(Collectors.toMap(ticket -> ticketIds.get(ticket.getId()), ticket -> ticket)));
|
||||
@@ -495,7 +497,7 @@ public class GitOperations {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
return Stream.of(message.getTicketReference());
|
||||
return message.getTicketReferences().stream();
|
||||
|
||||
}).collect(Collectors.toList());
|
||||
});
|
||||
|
||||
@@ -19,6 +19,8 @@ import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
@@ -45,7 +47,10 @@ class ParsedCommitMessage {
|
||||
private static final Pattern GITHUB_TICKET = Pattern.compile("((?>#|gh-)\\d+)");
|
||||
|
||||
private static final Pattern GITHUB_CLOSE_SYNTAX = Pattern.compile(
|
||||
"(?>closes|closed|close|fixes|fixed|fix|resolves|resolved|resolve|see|related to)[\\s:]*((?>#|gh-)\\d+)",
|
||||
"(?>closes|closed|close|fixes|fixed|fix|resolves|resolved|resolve)[\\s:]*((?>#|gh-)\\d+)",
|
||||
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
|
||||
|
||||
private static final Pattern GITHUB_SEE_SYNTAX = Pattern.compile("(?>see|related to)[\\s:]*((?>#|gh-)\\d+)",
|
||||
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
|
||||
|
||||
private static final Pattern GITHUB_PREFIX_SYNTAX = Pattern.compile("^(#\\d+)");
|
||||
@@ -82,7 +87,8 @@ class ParsedCommitMessage {
|
||||
}
|
||||
|
||||
// Closes (gh-nnn|#nnn) syntax
|
||||
Matcher gitHubMatcher = GITHUB_CLOSE_SYNTAX.matcher(summary + "\n" + body);
|
||||
Matcher gitHubCloseMatcher = GITHUB_CLOSE_SYNTAX.matcher(summary + "\n" + body);
|
||||
Matcher gitHubSeeMatcher = GITHUB_SEE_SYNTAX.matcher(summary + "\n" + body);
|
||||
|
||||
// #nnn syntax
|
||||
Optional<TicketReference> gitHubTicket = tryParseGitHubTicketReference(summary);
|
||||
@@ -90,12 +96,17 @@ class ParsedCommitMessage {
|
||||
if (gitHubTicket.isPresent()) {
|
||||
ticketReference = gitHubTicket.get();
|
||||
} else {
|
||||
if (gitHubMatcher.find()) {
|
||||
ticketReference = new TicketReference(gitHubMatcher.group(1), summary, TicketReference.Style.GitHub);
|
||||
if (gitHubCloseMatcher.find()) {
|
||||
ticketReference = new TicketReference(gitHubCloseMatcher.group(1), summary, TicketReference.Style.GitHub,
|
||||
TicketReference.Reference.Ticket);
|
||||
} else if (gitHubSeeMatcher.find()) {
|
||||
ticketReference = new TicketReference(gitHubSeeMatcher.group(1), summary, TicketReference.Style.GitHub,
|
||||
TicketReference.Reference.Ticket);
|
||||
}
|
||||
}
|
||||
|
||||
List<TicketReference> relatedTickets = parseRelatedTickets(body, gitHubMatcher);
|
||||
List<TicketReference> relatedTickets = parseRelatedTickets(body,
|
||||
Arrays.asList(gitHubCloseMatcher, gitHubSeeMatcher));
|
||||
Optional<TicketReference> optionalOriginalPr = parsePullRequestReference(body);
|
||||
|
||||
if (optionalOriginalPr.isPresent()) {
|
||||
@@ -148,7 +159,8 @@ class ParsedCommitMessage {
|
||||
int summaryStart = findSummaryIndex(summary, mr.end(1));
|
||||
|
||||
return Optional.of(new TicketReference(gitHubPrefixMatcher.group(1).toUpperCase(Locale.ROOT),
|
||||
summaryStart > -1 ? summary.substring(summaryStart) : summary, TicketReference.Style.GitHub));
|
||||
summaryStart > -1 ? summary.substring(summaryStart) : summary, TicketReference.Style.GitHub,
|
||||
TicketReference.Reference.Ticket));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +180,8 @@ class ParsedCommitMessage {
|
||||
int summaryStart = findSummaryIndex(summary, mr.end(1));
|
||||
|
||||
return Optional.of(new TicketReference(jiraMatcher.group(1).toUpperCase(Locale.ROOT),
|
||||
summaryStart > -1 ? summary.substring(summaryStart) : summary, TicketReference.Style.Jira));
|
||||
summaryStart > -1 ? summary.substring(summaryStart) : summary, TicketReference.Style.Jira,
|
||||
TicketReference.Reference.Ticket));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,14 +195,14 @@ class ParsedCommitMessage {
|
||||
Matcher prMatcher = ORIGINAL_PULL_REQUEST.matcher(body);
|
||||
|
||||
if (prMatcher.find()) {
|
||||
return extractTicket(prMatcher.group(1));
|
||||
return extractTicket(prMatcher.group(1), TicketReference.Reference.PullRequest);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
protected static List<TicketReference> parseRelatedTickets(String body, Matcher gitHubMatcher) {
|
||||
protected static List<TicketReference> parseRelatedTickets(String body, Collection<Matcher> gitHubMatcher) {
|
||||
|
||||
List<TicketReference> relatedTickets = new ArrayList<>();
|
||||
if (body != null) {
|
||||
@@ -200,26 +213,30 @@ class ParsedCommitMessage {
|
||||
String ticketIds[] = relatedTicketsMatcher.group(1).split(",");
|
||||
|
||||
for (String ticketId : ticketIds) {
|
||||
extractTicket(ticketId).ifPresent(relatedTickets::add);
|
||||
extractTicket(ticketId, TicketReference.Reference.Related).ifPresent(relatedTickets::add);
|
||||
}
|
||||
}
|
||||
|
||||
while (gitHubMatcher.find()) {
|
||||
extractTicket(gitHubMatcher.group(1)).ifPresent(relatedTickets::add);
|
||||
for (Matcher matcher : gitHubMatcher) {
|
||||
|
||||
while (matcher.find()) {
|
||||
extractTicket(matcher.group(1), TicketReference.Reference.Related).ifPresent(relatedTickets::add);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return relatedTickets;
|
||||
}
|
||||
|
||||
protected static Optional<TicketReference> extractTicket(String ticketId) {
|
||||
protected static Optional<TicketReference> extractTicket(String ticketId, TicketReference.Reference reference) {
|
||||
|
||||
if (JIRA_TICKET.matcher(ticketId.trim()).matches()) {
|
||||
return Optional.of(new TicketReference(ticketId.trim(), null, TicketReference.Style.Jira));
|
||||
return Optional.of(new TicketReference(ticketId.trim(), null, TicketReference.Style.Jira, reference));
|
||||
}
|
||||
|
||||
if (GITHUB_TICKET.matcher(ticketId.trim()).matches()) {
|
||||
return Optional.of(new TicketReference(ticketId.trim(), null, TicketReference.Style.GitHub));
|
||||
return Optional.of(new TicketReference(ticketId.trim(), null, TicketReference.Style.GitHub, reference));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
@@ -242,4 +259,19 @@ class ParsedCommitMessage {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public List<TicketReference> getTicketReferences() {
|
||||
|
||||
List<TicketReference> references = new ArrayList<>();
|
||||
if (getTicketReference() != null) {
|
||||
references.add(getTicketReference());
|
||||
}
|
||||
|
||||
references.addAll(getRelatedTickets());
|
||||
|
||||
if (getPullRequestReference() != null) {
|
||||
references.add(getPullRequestReference());
|
||||
}
|
||||
|
||||
return references;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,11 @@ package org.springframework.data.release.issues;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.SupportedProject;
|
||||
import org.springframework.data.release.model.Train;
|
||||
import org.springframework.data.release.model.TrainIteration;
|
||||
import org.springframework.plugin.core.Plugin;
|
||||
|
||||
@@ -78,7 +79,7 @@ public interface IssueTracker extends Plugin<SupportedProject> {
|
||||
* @param ticketIds collection of {@link Ticket#id ticket Ids}, must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Collection<Ticket> findTickets(SupportedProject project, Collection<String> ticketIds);
|
||||
Collection<Ticket> findTickets(SupportedProject project, Collection<TicketReference> ticketIds);
|
||||
|
||||
/**
|
||||
* Query the issue tracker for multiple {@link Ticket#id ticket Ids}. Tickets that are not found are not returned. The
|
||||
@@ -89,7 +90,7 @@ public interface IssueTracker extends Plugin<SupportedProject> {
|
||||
* @param ticketReferences must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Tickets findTickets(ModuleIteration moduleIteration, Collection<String> ticketIds);
|
||||
Tickets findTickets(ModuleIteration moduleIteration, Collection<TicketReference> ticketIds);
|
||||
|
||||
/**
|
||||
* Creates a release version if release version is missing.
|
||||
@@ -165,8 +166,7 @@ public interface IssueTracker extends Plugin<SupportedProject> {
|
||||
*/
|
||||
default Changelog getChangelogFor(ModuleIteration module, List<TicketReference> ticketReferences) {
|
||||
|
||||
Tickets tickets = findTickets(module,
|
||||
ticketReferences.stream().map(TicketReference::getId).collect(Collectors.toList()));
|
||||
Tickets tickets = findTickets(module, ticketReferences);
|
||||
return Changelog.of(module, tickets);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,11 +26,17 @@ public class TicketReference implements Comparable<TicketReference> {
|
||||
String id;
|
||||
String message;
|
||||
Style style;
|
||||
Reference reference;
|
||||
|
||||
public TicketReference(String id, String message, Style style) {
|
||||
public TicketReference(String id, String message, Style style, Reference reference) {
|
||||
this.id = normalize(id);
|
||||
this.message = message;
|
||||
this.style = style;
|
||||
this.reference = reference;
|
||||
}
|
||||
|
||||
public static TicketReference ofTicket(String number, Style style) {
|
||||
return new TicketReference(number, "", style, Reference.Ticket);
|
||||
}
|
||||
|
||||
private static String normalize(String id) {
|
||||
@@ -52,7 +58,19 @@ public class TicketReference implements Comparable<TicketReference> {
|
||||
return id.compareToIgnoreCase(o.id);
|
||||
}
|
||||
|
||||
public boolean isIssue() {
|
||||
return getReference() == Reference.Ticket;
|
||||
}
|
||||
|
||||
public boolean isPullRequest() {
|
||||
return getReference() == Reference.PullRequest;
|
||||
}
|
||||
|
||||
public enum Style {
|
||||
GitHub, Jira;
|
||||
GitHub, Jira
|
||||
}
|
||||
|
||||
public enum Reference {
|
||||
Ticket, Related, PullRequest
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2024 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.Value;
|
||||
|
||||
import org.springframework.data.release.issues.Ticket;
|
||||
import org.springframework.data.release.issues.TicketReference;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Value
|
||||
public class ChangeItem {
|
||||
TicketReference reference;
|
||||
GitHubReadIssue issue;
|
||||
}
|
||||
@@ -38,7 +38,6 @@ import org.springframework.stereotype.Component;
|
||||
* @author Madhura Bhave
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Component
|
||||
public class ChangelogGenerator {
|
||||
|
||||
private static final Pattern ghUserMentionPattern = Pattern.compile("(^|[^\\w`])(@[\\w-]+)");
|
||||
@@ -52,7 +51,7 @@ public class ChangelogGenerator {
|
||||
private final ChangelogSections sections;
|
||||
|
||||
public ChangelogGenerator() {
|
||||
this.excludeLabels = new HashSet<>(Arrays.asList("type: task"));
|
||||
this.excludeLabels = new HashSet<>(Collections.singletonList("type: task"));
|
||||
this.excludeContributors = new LinkedHashSet<>();
|
||||
this.contributorsTitle = null;
|
||||
this.sections = new ChangelogSections();
|
||||
@@ -65,7 +64,7 @@ public class ChangelogGenerator {
|
||||
* @param sectionContentPostProcessor the postprocessor for a changelog section
|
||||
* @param includeIssueNumbers whether to include issue numbers
|
||||
*/
|
||||
public String generate(List<GitHubReadIssue> issues,
|
||||
public String generate(List<ChangeItem> issues,
|
||||
BiFunction<ChangelogSection, String, String> sectionContentPostProcessor, boolean includeIssueNumbers) {
|
||||
return generateContent(issues, sectionContentPostProcessor, includeIssueNumbers);
|
||||
}
|
||||
@@ -78,10 +77,12 @@ public class ChangelogGenerator {
|
||||
return this.excludeLabels.contains(label.getName());
|
||||
}
|
||||
|
||||
private String generateContent(List<GitHubReadIssue> issues,
|
||||
private String generateContent(List<ChangeItem> issues,
|
||||
BiFunction<ChangelogSection, String, String> sectionContentPostProcessor, boolean includeIssueNumbers) {
|
||||
StringBuilder content = new StringBuilder();
|
||||
addSectionContent(content, this.sections.collate(issues), sectionContentPostProcessor, includeIssueNumbers);
|
||||
addSectionContent(content,
|
||||
this.sections.collate(issues.stream().filter(it -> it.getReference().isIssue()).map(ChangeItem::getIssue).collect(Collectors.toList())),
|
||||
sectionContentPostProcessor, includeIssueNumbers);
|
||||
Set<GitHubUser> contributors = getContributors(issues);
|
||||
if (!contributors.isEmpty()) {
|
||||
addContributorsContent(content, contributors);
|
||||
@@ -98,10 +99,10 @@ public class ChangelogGenerator {
|
||||
|
||||
StringBuilder content = new StringBuilder();
|
||||
|
||||
content.append((content.length() != 0) ? String.format("%n") : "");
|
||||
content.append("## ").append(section).append(String.format("%n%n"));
|
||||
content.append("## ").append(section).append(String.format("%n"));
|
||||
issues.stream().map(issue -> getFormattedIssue(issue, includeIssueNumbers)).forEach(content::append);
|
||||
|
||||
result.append((result.length() != 0) ? String.format("%n") : "");
|
||||
result.append(sectionContentPostProcessor.apply(section, content.toString()));
|
||||
});
|
||||
}
|
||||
@@ -117,12 +118,16 @@ public class ChangelogGenerator {
|
||||
return "[" + issue.getId() + "]" + "(" + issue.getUrl() + ")";
|
||||
}
|
||||
|
||||
private Set<GitHubUser> getContributors(List<GitHubReadIssue> issues) {
|
||||
private Set<GitHubUser> getContributors(List<ChangeItem> issues) {
|
||||
if (this.excludeContributors.contains("*")) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return issues.stream().filter((issue) -> issue.getPullRequest() != null).map(GitHubReadIssue::getUser)
|
||||
.filter(this::isIncludedContributor).collect(Collectors.toSet());
|
||||
return issues.stream()
|
||||
.filter(item -> item.getReference().isPullRequest() || item.getIssue().getPullRequest() != null) //
|
||||
.map(ChangeItem::getIssue) //
|
||||
.map(GitHubReadIssue::getUser) //
|
||||
.filter(this::isIncludedContributor) //
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private boolean isIncludedContributor(GitHubUser user) {
|
||||
@@ -132,7 +137,7 @@ public class ChangelogGenerator {
|
||||
private void addContributorsContent(StringBuilder content, Set<GitHubUser> contributors) {
|
||||
content.append(String.format("%n## "));
|
||||
content.append((this.contributorsTitle != null) ? this.contributorsTitle : ":heart: Contributors");
|
||||
content.append(String.format("%n%nWe'd like to thank all the contributors who worked on this release!%n%n"));
|
||||
content.append(String.format("%nWe'd like to thank all the contributors who worked on this release!%n%n"));
|
||||
contributors.stream().map(this::formatContributors).forEach(content::append);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.util.CollectionUtils;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ChangelogSection {
|
||||
public class ChangelogSection {
|
||||
|
||||
private final String title;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.data.release.git.VersionTags;
|
||||
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.issues.github.GitHubWorkflows.GitHubWorkflow;
|
||||
import org.springframework.data.release.model.ArtifactVersion;
|
||||
@@ -130,14 +131,14 @@ public class GitHub extends GitHubSupport implements IssueTracker {
|
||||
*/
|
||||
@Override
|
||||
@Cacheable("tickets")
|
||||
public Collection<Ticket> findTickets(SupportedProject project, Collection<String> ticketIds) {
|
||||
public Collection<Ticket> findTickets(SupportedProject project, Collection<TicketReference> ticketIds) {
|
||||
|
||||
String repositoryName = GitProject.of(project).getRepositoryName();
|
||||
List<Ticket> tickets = new ArrayList<>();
|
||||
|
||||
ticketIds.forEach(ticketId -> {
|
||||
|
||||
GitHubReadIssue ticket = findTicket(repositoryName, ticketId);
|
||||
GitHubReadIssue ticket = findTicket(repositoryName, ticketId.getId());
|
||||
if (ticket != null) {
|
||||
tickets.add(toTicket(ticket));
|
||||
}
|
||||
@@ -147,9 +148,9 @@ public class GitHub extends GitHubSupport implements IssueTracker {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tickets findTickets(ModuleIteration moduleIteration, Collection<String> ticketIds) {
|
||||
public Tickets findTickets(ModuleIteration moduleIteration, Collection<TicketReference> ticketIds) {
|
||||
|
||||
return findGitHubIssues(moduleIteration, ticketIds).stream().map(GitHub::toTicket)
|
||||
return findGitHubIssues(moduleIteration, ticketIds).stream().map(ChangeItem::getIssue).map(GitHub::toTicket)
|
||||
.collect(Tickets.toTicketsCollector());
|
||||
}
|
||||
|
||||
@@ -491,7 +492,7 @@ public class GitHub extends GitHubSupport implements IssueTracker {
|
||||
close(module, ticket);
|
||||
}
|
||||
|
||||
List<GitHubReadIssue> findGitHubIssues(ModuleIteration moduleIteration, Collection<String> ticketIds) {
|
||||
List<ChangeItem> findGitHubIssues(ModuleIteration moduleIteration, Collection<TicketReference> ticketIds) {
|
||||
|
||||
logger.log(moduleIteration, "Looking up GitHub issues from milestone …");
|
||||
|
||||
@@ -501,19 +502,19 @@ public class GitHub extends GitHubSupport implements IssueTracker {
|
||||
String repositoryName = GitProject.of(moduleIteration).getRepositoryName();
|
||||
|
||||
logger.log(moduleIteration, "Looking up GitHub issues …");
|
||||
Collection<GitHubReadIssue> foundIssues = ticketIds.stream().filter(it -> it.startsWith("#")).flatMap(it -> {
|
||||
Collection<ChangeItem> foundIssues = ticketIds.stream().filter(it -> it.getId().startsWith("#")).flatMap(it -> {
|
||||
|
||||
GitHubReadIssue ticket = getTicket(issues, repositoryName, it);
|
||||
GitHubReadIssue ticket = getTicket(issues, repositoryName, it.getId());
|
||||
|
||||
if (ticket != null) {
|
||||
return Stream.of(ticket);
|
||||
return Stream.of(new ChangeItem(it, ticket));
|
||||
}
|
||||
|
||||
return Stream.empty();
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
List<GitHubReadIssue> gitHubIssues = foundIssues.stream().filter(it -> {
|
||||
Ticket ticket = toTicket(it);
|
||||
List<ChangeItem> gitHubIssues = foundIssues.stream().filter(it -> {
|
||||
Ticket ticket = toTicket(it.getIssue());
|
||||
return !ticket.isReleaseTicketFor(moduleIteration) && !ticket.isReleaseTicket();
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
@@ -563,16 +564,20 @@ public class GitHub extends GitHubSupport implements IssueTracker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iteration
|
||||
* @param module
|
||||
* @param ticketIds
|
||||
*/
|
||||
public void createOrUpdateRelease(TrainIteration iteration, ModuleIteration module, List<String> ticketIds) {
|
||||
public void createOrUpdateRelease(ModuleIteration module, List<TicketReference> ticketIds) {
|
||||
|
||||
logger.log(module, "Preparing GitHub Release …");
|
||||
|
||||
List<GitHubReadIssue> gitHubIssues = findGitHubIssues(module, ticketIds);
|
||||
String releaseMarkdown = createReleaseMarkdown(module, ticketIds);
|
||||
|
||||
createOrUpdateRelease(module, releaseMarkdown);
|
||||
|
||||
logger.log(module, "GitHub Release up to date");
|
||||
}
|
||||
|
||||
public String createReleaseMarkdown(ModuleIteration module, List<TicketReference> ticketIds) {
|
||||
|
||||
List<ChangeItem> gitHubIssues = findGitHubIssues(module, ticketIds);
|
||||
|
||||
ArtifactVersion version = ArtifactVersion.of(module);
|
||||
DocumentationMetadata documentation = DocumentationMetadata.of(module, version, false);
|
||||
@@ -580,26 +585,26 @@ public class GitHub extends GitHubSupport implements IssueTracker {
|
||||
ChangelogGenerator generator = new ChangelogGenerator();
|
||||
generator.getExcludeContributors().addAll(properties.getTeam());
|
||||
|
||||
boolean generateLinks = !iteration.isCommercial();
|
||||
boolean generateLinks = !module.isCommercial();
|
||||
String releaseBody = generator.generate(gitHubIssues, (changelogSection, s) -> s, generateLinks);
|
||||
String documentationLinks = getDocumentationLinks(module, documentation);
|
||||
|
||||
String releaseMarkdown;
|
||||
if (module.getProject() == Projects.BOM || module.getProject() == Projects.BUILD) {
|
||||
// We don't ship Javadoc/reference doc for build and BOM
|
||||
|
||||
if (module.getProject() == Projects.BOM) {
|
||||
String participatingModules = createParticipatingModules(iteration);
|
||||
String participatingModules = createParticipatingModules(module.getTrainIteration());
|
||||
|
||||
createOrUpdateRelease(module,
|
||||
String.format("## :shipit: Participating Modules%n%n%s%n%s%n", participatingModules, releaseBody));
|
||||
releaseMarkdown = String.format("## :shipit: Participating Modules%n%n%s%n%s%n", participatingModules,
|
||||
releaseBody);
|
||||
} else {
|
||||
createOrUpdateRelease(module, String.format("%s%n", documentationLinks, releaseBody));
|
||||
releaseMarkdown = String.format("%s%n", documentationLinks);
|
||||
}
|
||||
} else {
|
||||
createOrUpdateRelease(module, String.format("## :green_book: Links%n%s%n%s%n", documentationLinks, releaseBody));
|
||||
releaseMarkdown = String.format("## :green_book: Links%n%s%n%s%n", documentationLinks, releaseBody);
|
||||
}
|
||||
|
||||
logger.log(module, "GitHub Release up to date");
|
||||
return releaseMarkdown;
|
||||
}
|
||||
|
||||
private String createParticipatingModules(TrainIteration iteration) {
|
||||
@@ -696,8 +701,7 @@ public class GitHub extends GitHubSupport implements IssueTracker {
|
||||
String referenceDocUrl = documentation.getReferenceDocUrl();
|
||||
String apiDocUrl = documentation.getApiDocUrl();
|
||||
|
||||
String reference = String.format("* [%s %s Reference documentation](%s)",
|
||||
module.getProject().getFullName(),
|
||||
String reference = String.format("* [%s %s Reference documentation](%s)", module.getProject().getFullName(),
|
||||
module.getVersion().toString(), referenceDocUrl);
|
||||
|
||||
String apidoc = String.format("* [%s %s Javadoc](%s)", module.getProject().getFullName(),
|
||||
|
||||
@@ -22,7 +22,6 @@ import lombok.experimental.FieldDefaults;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.release.CliComponent;
|
||||
import org.springframework.data.release.TimedCommand;
|
||||
@@ -30,6 +29,7 @@ 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.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Project;
|
||||
import org.springframework.data.release.model.SupportStatus;
|
||||
import org.springframework.data.release.model.SupportedProject;
|
||||
@@ -59,8 +59,8 @@ public class GitHubCommands extends TimedCommand {
|
||||
@CliCommand(value = "github update labels")
|
||||
public void createOrUpdateLabels(@CliOption(key = "", mandatory = true) Project project,
|
||||
@CliOption(key = "commercial", mandatory = false) Boolean commercial) {
|
||||
gitHubLabels.createOrUpdateLabels(SupportedProject.of(project,
|
||||
commercial == null || !commercial ? SupportStatus.OSS : SupportStatus.COMMERCIAL));
|
||||
gitHubLabels.createOrUpdateLabels(
|
||||
SupportedProject.of(project, commercial == null || !commercial ? SupportStatus.OSS : SupportStatus.COMMERCIAL));
|
||||
}
|
||||
|
||||
@CliCommand(value = "github push")
|
||||
@@ -74,27 +74,50 @@ public class GitHubCommands extends TimedCommand {
|
||||
git.push(new TrainIteration(iteration.getTrain(), Iteration.SR1));
|
||||
}
|
||||
|
||||
createOrUpdateRelease(iteration);
|
||||
createOrUpdateRelease(iteration, null);
|
||||
}, 2);
|
||||
}
|
||||
|
||||
@CliCommand(value = "github create release")
|
||||
public void createOrUpdateRelease(@CliOption(key = "", mandatory = true) TrainIteration iteration) {
|
||||
public void createOrUpdateRelease(@CliOption(key = "", mandatory = true) TrainIteration iteration,
|
||||
@CliOption(key = "project") Project project) {
|
||||
|
||||
TrainIteration previousIteration = git.getPreviousIteration(iteration);
|
||||
|
||||
if (project != null) {
|
||||
|
||||
ModuleIteration module = iteration.getModule(project);
|
||||
createOrUpdateRelease(module, previousIteration);
|
||||
return;
|
||||
}
|
||||
|
||||
ExecutionUtils.run(executor, iteration, it -> {
|
||||
|
||||
if (it.getSupportedProject().getProject().getTracker() == Tracker.GITHUB) {
|
||||
|
||||
List<String> ticketReferences = git
|
||||
.getTicketReferencesBetween(it.getSupportedProject(), previousIteration, iteration).stream()
|
||||
.map(TicketReference::getId).collect(Collectors.toList());
|
||||
gitHub.createOrUpdateRelease(iteration, it, ticketReferences);
|
||||
createOrUpdateRelease(it, previousIteration);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@CliCommand(value = "github preview release")
|
||||
public String previewRelease(@CliOption(key = "", mandatory = true) TrainIteration iteration,
|
||||
@CliOption(key = "project", mandatory = true) Project project) {
|
||||
|
||||
TrainIteration previousIteration = git.getPreviousIteration(iteration);
|
||||
ModuleIteration module = iteration.getModule(project);
|
||||
|
||||
List<TicketReference> ticketReferences = git.getTicketReferencesBetween(module.getSupportedProject(),
|
||||
previousIteration, module.getTrainIteration());
|
||||
|
||||
return gitHub.createReleaseMarkdown(module, ticketReferences);
|
||||
}
|
||||
|
||||
private void createOrUpdateRelease(ModuleIteration module, TrainIteration previousIteration) {
|
||||
List<TicketReference> ticketReferences = git.getTicketReferencesBetween(module.getSupportedProject(),
|
||||
previousIteration, module.getTrainIteration());
|
||||
gitHub.createOrUpdateRelease(module, ticketReferences);
|
||||
}
|
||||
|
||||
public void triggerAntoraWorkflow(Project project) {
|
||||
gitHub.triggerAntoraWorkflow(project);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.release.AbstractIntegrationTests;
|
||||
import org.springframework.data.release.WireMockExtension;
|
||||
import org.springframework.data.release.issues.Ticket;
|
||||
import org.springframework.data.release.issues.TicketReference;
|
||||
import org.springframework.data.release.model.Iteration;
|
||||
import org.springframework.data.release.model.ModuleIteration;
|
||||
import org.springframework.data.release.model.Projects;
|
||||
@@ -80,7 +81,7 @@ class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests {
|
||||
mockGetIssueWith("issue.json", 233);
|
||||
|
||||
Collection<Ticket> tickets = github.findTickets(LATEST.getSupportedProject(Projects.BUILD),
|
||||
Collections.singletonList("233"));
|
||||
Collections.singletonList(TicketReference.ofTicket("233", TicketReference.Style.GitHub)));
|
||||
|
||||
assertThat(tickets).hasSize(1);
|
||||
}
|
||||
@@ -89,7 +90,7 @@ class GitHubIssueTrackerIntegrationTests extends AbstractIntegrationTests {
|
||||
void ignoresUnknownTicketsByTicketId() {
|
||||
|
||||
Collection<Ticket> tickets = github.findTickets(LATEST.getSupportedProject(Projects.BUILD),
|
||||
Collections.singletonList("123"));
|
||||
Collections.singletonList(TicketReference.ofTicket("233", TicketReference.Style.GitHub)));
|
||||
assertThat(tickets).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ package org.springframework.data.release.misc;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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;
|
||||
@@ -58,8 +58,7 @@ class ReleaseOperationsIntegrationTests extends AbstractIntegrationTests {
|
||||
List<TicketReference> ticketReferences = gitOperations.getTicketReferencesBetween(project, from, to);
|
||||
IssueTracker tracker = trackers.getRequiredPluginFor(project);
|
||||
|
||||
Tickets tickets = tracker.findTickets(to.getModule(Projects.MONGO_DB),
|
||||
ticketReferences.stream().map(TicketReference::getId).collect(Collectors.toList()));
|
||||
Tickets tickets = tracker.findTickets(to.getModule(Projects.MONGO_DB), ticketReferences);
|
||||
|
||||
assertThat(tickets).hasSize(15);
|
||||
}
|
||||
@@ -75,8 +74,7 @@ class ReleaseOperationsIntegrationTests extends AbstractIntegrationTests {
|
||||
List<TicketReference> ticketReferences = gitOperations.getTicketReferencesBetween(project, from, to);
|
||||
IssueTracker tracker = trackers.getRequiredPluginFor(project);
|
||||
|
||||
Tickets tickets = tracker.findTickets(to.getModule(Projects.R2DBC),
|
||||
ticketReferences.stream().map(TicketReference::getId).collect(Collectors.toList()));
|
||||
Tickets tickets = tracker.findTickets(to.getModule(Projects.R2DBC), ticketReferences);
|
||||
|
||||
assertThat(tickets).hasSize(22);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user