-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow format issue output text within individual sections and in general #103
base: main
Are you sure you want to change the base?
Changes from all commits
8bc6091
5a7d7c1
4ac4357
dd532d3
7daeaf8
deb5610
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,24 +16,26 @@ | |
|
||
package io.spring.githubchangeloggenerator; | ||
|
||
import static io.spring.githubchangeloggenerator.ApplicationProperties.FormatPlaceholder.*; | ||
import static io.spring.githubchangeloggenerator.ApplicationProperties.FormatPlaceholder.TITLE; | ||
|
||
import io.spring.githubchangeloggenerator.github.service.Repository; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.regex.Pattern; | ||
|
||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.boot.context.properties.bind.DefaultValue; | ||
import org.springframework.util.Assert; | ||
|
||
import io.spring.githubchangeloggenerator.github.service.Repository; | ||
|
||
/** | ||
* Configuration properties for the GitHub repo. | ||
* | ||
* @author Madhura Bhave | ||
* @author Phillip Webb | ||
* @author Mahendra Bishnoi | ||
* @author Gary Russell | ||
* @author Dinar Shagaliev | ||
*/ | ||
@ConfigurationProperties(prefix = "changelog") | ||
public class ApplicationProperties { | ||
|
@@ -75,12 +77,13 @@ public class ApplicationProperties { | |
|
||
public ApplicationProperties(Repository repository, @DefaultValue("title") MilestoneReference milestoneReference, | ||
List<Section> sections, Issues issues, Contributors contributors, List<ExternalLink> externalLinks, | ||
@DefaultValue("false") boolean addSections) { | ||
@DefaultValue("false") boolean addSections) { | ||
|
||
Comment on lines
+80
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like a whitespace-only change. Please revert. |
||
Assert.notNull(repository, "Repository must not be null"); | ||
this.repository = repository; | ||
this.milestoneReference = milestoneReference; | ||
this.sections = (sections != null) ? sections : Collections.emptyList(); | ||
this.issues = (issues != null) ? issues : new Issues(null, null, null, true); | ||
this.issues = (issues != null) ? issues : new Issues(null, null, null, true, null); | ||
this.contributors = (contributors != null) ? contributors : new Contributors(null, null); | ||
this.externalLinks = (externalLinks != null) ? externalLinks : Collections.emptyList(); | ||
this.addSections = addSections; | ||
|
@@ -140,11 +143,25 @@ public static class Section { | |
*/ | ||
private final Set<String> labels; | ||
|
||
public Section(String title, @DefaultValue("default") String group, IssueSort sort, Set<String> labels) { | ||
|
||
/** | ||
* Whether to generate a link to each issue in the changelog. | ||
*/ | ||
private final boolean generateLinks; | ||
Comment on lines
+147
to
+150
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need a second property for this? The |
||
|
||
/** | ||
* Format used to customize an output of issues in the section. | ||
*/ | ||
private final String format; | ||
|
||
public Section(String title, @DefaultValue("default") String group, IssueSort sort, | ||
boolean generateLinks, String format, Set<String> labels) { | ||
this.title = title; | ||
this.group = (group != null) ? group : "default"; | ||
this.group = group; | ||
this.sort = sort; | ||
this.labels = labels; | ||
this.generateLinks = generateLinks; | ||
this.format = format; | ||
this.labels = labels; | ||
} | ||
|
||
public String getTitle() { | ||
|
@@ -159,6 +176,14 @@ public IssueSort getSort() { | |
return this.sort; | ||
} | ||
|
||
public String getFormat() { | ||
return format; | ||
} | ||
|
||
public boolean isGenerateLinks() { | ||
return generateLinks; | ||
} | ||
|
||
public Set<String> getLabels() { | ||
return this.labels; | ||
} | ||
|
@@ -190,12 +215,20 @@ public static class Issues { | |
*/ | ||
private final boolean generateLinks; | ||
|
||
/** | ||
* Default format used to customize an output of issues in the section. | ||
*/ | ||
private final String defaultFormat; | ||
|
||
public Issues(IssueSort sort, IssuesExclude exclude, Set<PortedIssue> ports, | ||
@DefaultValue("true") boolean generateLinks) { | ||
@DefaultValue("true") Boolean generateLinks, String defaultFormat) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why has |
||
this.sort = sort; | ||
this.exclude = (exclude != null) ? exclude : new IssuesExclude(null); | ||
this.ports = (ports != null) ? ports : Collections.emptySet(); | ||
this.generateLinks = generateLinks; | ||
this.generateLinks = (defaultFormat != null) || generateLinks; | ||
this.defaultFormat = (defaultFormat != null) ? defaultFormat | ||
: String.format("%s [#%s](%s)", TITLE.placeholder, NUMBER.placeholder, | ||
URL.placeholder); | ||
} | ||
|
||
public IssueSort getSort() { | ||
|
@@ -214,7 +247,11 @@ public boolean isGenerateLinks() { | |
return this.generateLinks; | ||
} | ||
|
||
} | ||
public String getDefaultFormat() { | ||
return this.defaultFormat; | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Issues exclude. | ||
|
@@ -361,4 +398,18 @@ public enum IssueSort { | |
|
||
} | ||
|
||
public enum FormatPlaceholder { | ||
|
||
TITLE("${title}"), | ||
URL("${url}"), | ||
NUMBER("${number}"); | ||
|
||
public final String placeholder; | ||
|
||
FormatPlaceholder(String placeholder) { | ||
this.placeholder = placeholder; | ||
} | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,18 @@ | |
|
||
package io.spring.githubchangeloggenerator; | ||
|
||
import static io.spring.githubchangeloggenerator.ApplicationProperties.FormatPlaceholder.NUMBER; | ||
import static io.spring.githubchangeloggenerator.ApplicationProperties.FormatPlaceholder.TITLE; | ||
import static io.spring.githubchangeloggenerator.ApplicationProperties.FormatPlaceholder.URL; | ||
|
||
import io.spring.githubchangeloggenerator.ApplicationProperties.ExternalLink; | ||
import io.spring.githubchangeloggenerator.ApplicationProperties.IssueSort; | ||
import io.spring.githubchangeloggenerator.ApplicationProperties.PortedIssue; | ||
import io.spring.githubchangeloggenerator.github.payload.Issue; | ||
import io.spring.githubchangeloggenerator.github.payload.Label; | ||
import io.spring.githubchangeloggenerator.github.payload.User; | ||
import io.spring.githubchangeloggenerator.github.service.GitHubService; | ||
import io.spring.githubchangeloggenerator.github.service.Repository; | ||
Comment on lines
+19
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please correct the imports as per the problems reported by Checkstyle when you run |
||
import java.io.File; | ||
import java.io.FileWriter; | ||
import java.io.IOException; | ||
|
@@ -29,26 +41,17 @@ | |
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
|
||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.FileCopyUtils; | ||
|
||
import io.spring.githubchangeloggenerator.ApplicationProperties.ExternalLink; | ||
import io.spring.githubchangeloggenerator.ApplicationProperties.IssueSort; | ||
import io.spring.githubchangeloggenerator.ApplicationProperties.PortedIssue; | ||
import io.spring.githubchangeloggenerator.github.payload.Issue; | ||
import io.spring.githubchangeloggenerator.github.payload.Label; | ||
import io.spring.githubchangeloggenerator.github.payload.User; | ||
import io.spring.githubchangeloggenerator.github.service.GitHubService; | ||
import io.spring.githubchangeloggenerator.github.service.Repository; | ||
|
||
/** | ||
* Generates a changelog markdown file which includes bug fixes, enhancements and | ||
* contributors for a given milestone. | ||
* | ||
* @author Madhura Bhave | ||
* @author Phillip Webb | ||
* @author Mahendra Bishnoi | ||
* @author Dinar Shagaliev | ||
*/ | ||
@Component | ||
public class ChangelogGenerator { | ||
|
@@ -80,6 +83,8 @@ public class ChangelogGenerator { | |
|
||
private final boolean generateLinks; | ||
|
||
private final String defaultFormat; | ||
|
||
public ChangelogGenerator(GitHubService service, ApplicationProperties properties) { | ||
this.service = service; | ||
this.repository = properties.getRepository(); | ||
|
@@ -92,6 +97,7 @@ public ChangelogGenerator(GitHubService service, ApplicationProperties propertie | |
this.portedIssues = properties.getIssues().getPorts(); | ||
this.externalLinks = properties.getExternalLinks(); | ||
this.generateLinks = properties.getIssues().isGenerateLinks(); | ||
this.defaultFormat = properties.getIssues().getDefaultFormat(); | ||
} | ||
|
||
/** | ||
|
@@ -142,14 +148,17 @@ private String generateContent(List<Issue> issues) { | |
return content.toString(); | ||
} | ||
|
||
private void addSectionContent(StringBuilder content, Map<ChangelogSection, List<Issue>> sectionIssues) { | ||
sectionIssues.forEach((section, issues) -> { | ||
sort(section.getSort(), issues); | ||
content.append((content.length() != 0) ? String.format("%n") : ""); | ||
content.append("## ").append(section).append(String.format("%n%n")); | ||
issues.stream().map(this::getFormattedIssue).forEach(content::append); | ||
}); | ||
} | ||
private void addSectionContent(StringBuilder content, | ||
Map<ChangelogSection, List<Issue>> sectionIssues) { | ||
sectionIssues.forEach((section, issues) -> { | ||
sort(section.getSort(), issues); | ||
content.append((!content.isEmpty()) ? String.format("%n") : ""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switching to |
||
content.append("## ").append(section).append(String.format("%n%n")); | ||
|
||
issues.stream().map(issue -> this.getFormattedIssue(issue, section)) | ||
.forEach(content::append); | ||
}); | ||
} | ||
|
||
private void sort(IssueSort sort, List<Issue> issues) { | ||
sort = (sort != null) ? sort : this.sort; | ||
|
@@ -158,18 +167,36 @@ private void sort(IssueSort sort, List<Issue> issues) { | |
} | ||
} | ||
|
||
private String getFormattedIssue(Issue issue) { | ||
String title = issue.getTitle(); | ||
for (Escape escape : escapes) { | ||
title = escape.apply(title); | ||
private String getFormattedIssue(Issue issue, ChangelogSection section) { | ||
String format = getFormat(section); | ||
|
||
String formattedIssueStr = "- " + format + "\n"; | ||
String title = escape(issue.getTitle()); | ||
|
||
formattedIssueStr = formattedIssueStr.replace(TITLE.placeholder, title); | ||
formattedIssueStr = formattedIssueStr.replace(NUMBER.placeholder, issue.getNumber()); | ||
formattedIssueStr = formattedIssueStr.replace(URL.placeholder, issue.getUrl()); | ||
|
||
return formattedIssueStr; | ||
} | ||
|
||
private String getFormat(ChangelogSection section) { | ||
if (section.getFormat() != null) { | ||
return section.getFormat(); | ||
} else if (!generateLinks) { | ||
return "${title}"; | ||
} | ||
return (this.generateLinks) ? String.format("- %s %s%n", title, getLinkToIssue(issue)) | ||
: String.format("- %s%n", title); | ||
return defaultFormat; | ||
} | ||
|
||
private String getLinkToIssue(Issue issue) { | ||
return "[#" + issue.getNumber() + "]" + "(" + issue.getUrl() + ")"; | ||
} | ||
private String escape(String text) { | ||
String escaped = text; | ||
for (Escape escape : escapes) { | ||
escaped = escape.apply(escaped); | ||
} | ||
|
||
return escaped; | ||
} | ||
|
||
private Set<User> getContributors(List<Issue> issues) { | ||
if (this.excludeContributors.contains("*")) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't re-order the imports. It adds noise to the diff, making the changes harder to review. If you run
./gradlew build
, you will see failures from both Checkstyle and Spring Java Format that should be corrected please.