Skip to content

Commit

Permalink
Merge pull request spring-io#55 from mahendrabishnoi2
Browse files Browse the repository at this point in the history
* pr/55:
  Add a property for configuring external links

Closes spring-iogh-55
  • Loading branch information
mbhave committed Dec 21, 2020
2 parents 5bbdbdc + 600c66d commit b49f1cb
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 13 deletions.
11 changes: 11 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ changelog:
title: "Contributors"
----

You can add external links such as release notes for quick access using:

[source,yaml]
----
changelog:
external_links:
- name: "Release Notes"
location: "https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes"
----




==== Showing Issues in Multiple Sections
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
*
* @author Madhura Bhave
* @author Phillip Webb
* @author Mahendra Bishnoi
*/
@ConfigurationProperties(prefix = "changelog")
@ConstructorBinding
Expand Down Expand Up @@ -63,14 +64,20 @@ public class ApplicationProperties {
*/
private final Contributors contributors;

/**
* Settings specific to external links.
*/
private final List<ExternalLink> externalLinks;

public ApplicationProperties(Repository repository, @DefaultValue("title") MilestoneReference milestoneReference,
List<Section> sections, Issues issues, Contributors contributors) {
List<Section> sections, Issues issues, Contributors contributors, List<ExternalLink> externalLinks) {
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);
this.contributors = (contributors != null) ? contributors : new Contributors(null, null);
this.externalLinks = (externalLinks != null) ? externalLinks : Collections.emptyList();
}

public Repository getRepository() {
Expand All @@ -93,6 +100,10 @@ public Contributors getContributors() {
return this.contributors;
}

public List<ExternalLink> getExternalLinks() {
return this.externalLinks;
}

/**
* Properties for a single changelog section.
*/
Expand Down Expand Up @@ -285,6 +296,36 @@ public Set<String> getNames() {

}

/**
* Properties for a single external link.
*/
public static class ExternalLink {

/**
* Name to be shown for an external link.
*/
private final String name;

/**
* URL for an external link.
*/
private final String location;

public ExternalLink(String name, String location) {
this.name = name;
this.location = location;
}

public String getName() {
return this.name;
}

public String getLocation() {
return this.location;
}

}

public enum IssueSort {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;

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;
Expand All @@ -46,6 +47,7 @@
*
* @author Madhura Bhave
* @author Phillip Webb
* @author Mahendra Bishnoi
*/
@Component
public class ChangelogGenerator {
Expand Down Expand Up @@ -73,6 +75,8 @@ public class ChangelogGenerator {

private final ChangelogSections sections;

private final List<ExternalLink> externalLinks;

public ChangelogGenerator(GitHubService service, ApplicationProperties properties) {
this.service = service;
this.repository = properties.getRepository();
Expand All @@ -83,6 +87,7 @@ public ChangelogGenerator(GitHubService service, ApplicationProperties propertie
this.contributorsTitle = properties.getContributors().getTitle();
this.sections = new ChangelogSections(properties);
this.portedIssues = properties.getIssues().getPorts();
this.externalLinks = properties.getExternalLinks();
}

/**
Expand Down Expand Up @@ -131,6 +136,9 @@ private String generateContent(List<Issue> issues) {
if (!contributors.isEmpty()) {
addContributorsContent(content, contributors);
}
if (!this.externalLinks.isEmpty()) {
addExternalLinksContent(content, this.externalLinks);
}
return content.toString();
}

Expand Down Expand Up @@ -201,6 +209,16 @@ private String formatContributors(User c) {
return String.format("- [@%s](%s)%n", c.getName(), c.getUrl());
}

private void addExternalLinksContent(StringBuilder content, List<ExternalLink> externalLinks) {
content.append(String.format("## "));
content.append(String.format("External Links%n%n"));
externalLinks.stream().map(this::formatExternalLinks).forEach(content::append);
}

private String formatExternalLinks(ExternalLink externalLink) {
return String.format("- [%s](%s)%n", externalLink.getName(), externalLink.getLocation());
}

private void writeContentToFile(String content, String path) throws IOException {
FileCopyUtils.copy(content, new FileWriter(new File(path)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ void loadYaml() throws Exception {
assertThat(properties.getIssues().getSort()).isEqualTo(IssueSort.TITLE);
assertThat(properties.getContributors().getTitle()).isEqualTo("Nice one!");
assertThat(properties.getContributors().getExclude().getNames()).containsExactly("philwebb");
assertThat(properties.getExternalLinks().get(0).getName()).isEqualTo("Release Notes 1");
assertThat(properties.getExternalLinks().get(0).getLocation()).isEqualTo("url1");
assertThat(properties.getExternalLinks().get(1).getName()).isEqualTo("Release Notes 2");
assertThat(properties.getExternalLinks().get(1).getLocation()).isEqualTo("url2");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import io.spring.githubchangeloggenerator.ApplicationProperties.Contributors;
import io.spring.githubchangeloggenerator.ApplicationProperties.ContributorsExclude;
import io.spring.githubchangeloggenerator.ApplicationProperties.ExternalLink;
import io.spring.githubchangeloggenerator.ApplicationProperties.IssueSort;
import io.spring.githubchangeloggenerator.ApplicationProperties.Issues;
import io.spring.githubchangeloggenerator.ApplicationProperties.IssuesExclude;
Expand Down Expand Up @@ -58,6 +59,7 @@
*
* @author Madhura Bhave
* @author Phillip Webb
* @author Mahendra Bishnoi
*/
class ChangelogGeneratorTests {

Expand Down Expand Up @@ -139,7 +141,7 @@ void generateWhenHasExcludedContributors() throws Exception {
issues.add(newPullRequest("Enhancement 2", "2", Type.ENHANCEMENT, "enhancement-2-url", contributor2));
given(this.service.getIssuesForMilestone(23, REPO)).willReturn(issues);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, null, null,
new Contributors(null, new ContributorsExclude(Collections.singleton("contributor1"))));
new Contributors(null, new ContributorsExclude(Collections.singleton("contributor1"))), null);
this.generator = new ChangelogGenerator(this.service, properties);
assertChangelog("23").hasContent(from("output-with-excluded-contributors"));
}
Expand All @@ -153,7 +155,7 @@ void generateWhenHasAllContributorsExcluded() throws Exception {
issues.add(newPullRequest("Enhancement 2", "2", Type.ENHANCEMENT, "enhancement-2-url", contributor2));
given(this.service.getIssuesForMilestone(23, REPO)).willReturn(issues);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, null, null,
new Contributors(null, new ContributorsExclude(Collections.singleton("*"))));
new Contributors(null, new ContributorsExclude(Collections.singleton("*"))), null);
this.generator = new ChangelogGenerator(this.service, properties);
assertChangelog("23").hasContent(from("output-with-all-contributors-excluded"));
}
Expand Down Expand Up @@ -223,7 +225,7 @@ void generateWhenSectionSortedByTitle() throws Exception {
Set<String> labels = Collections.singleton("type: enhancement");
sections.add(new Section("Enhancements", null, IssueSort.TITLE, labels));
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, sections,
new Issues(null, null, null), null);
new Issues(null, null, null), null, null);
this.generator = new ChangelogGenerator(this.service, properties);
List<Issue> issues = new ArrayList<>();
issues.add(newIssue("Enhancement c", "1", "enhancement-1-url", Type.ENHANCEMENT));
Expand All @@ -239,7 +241,7 @@ void generateWhenAllIssuesSortedByTitle() throws Exception {
Set<String> labels = Collections.singleton("type: enhancement");
sections.add(new Section("Enhancements", null, null, labels));
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, sections,
new Issues(IssueSort.TITLE, null, null), null);
new Issues(IssueSort.TITLE, null, null), null, null);
this.generator = new ChangelogGenerator(this.service, properties);
List<Issue> issues = new ArrayList<>();
issues.add(newIssue("Enhancement c", "1", "enhancement-1-url", Type.ENHANCEMENT));
Expand All @@ -256,18 +258,40 @@ void generateWhenHasCustomContributorsTitle() throws Exception {
issues.add(newPullRequest("Bug 1", "1", Type.BUG, "bug-1-url", contributor1));
given(this.service.getIssuesForMilestone(23, REPO)).willReturn(issues);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, null, null,
new Contributors(":heart: Teamwork", null));
new Contributors(":heart: Teamwork", null), null);
this.generator = new ChangelogGenerator(this.service, properties);
assertChangelog("23").hasContent(from("output-with-custom-contributors-title"));
}

@Test
void generateWhenOneExternalLink() throws Exception {
List<ExternalLink> externalLinks = new ArrayList<>();
externalLinks.add(new ExternalLink("Release Notes Link 1", "url1"));
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, null, null, null,
externalLinks);
this.generator = new ChangelogGenerator(this.service, properties);
assertChangelog("23").hasContent(from("output-with-one-external-link"));
}

@Test
void generateWhenMultipleExternalLink() throws Exception {
List<ExternalLink> externalLinks = new ArrayList<>();
externalLinks.add(new ExternalLink("Release Notes Link 1", "url1"));
externalLinks.add(new ExternalLink("Release Notes Link 2", "url2"));
externalLinks.add(new ExternalLink("Release Notes Link 3", "url3"));
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, null, null, null,
externalLinks);
this.generator = new ChangelogGenerator(this.service, properties);
assertChangelog("23").hasContent(from("output-with-multiple-external-link"));
}

private void setupGenerator(MilestoneReference id) {
Set<String> labels = new HashSet<>(Arrays.asList("duplicate", "wontfix"));
PortedIssue forwardPort = new PortedIssue("status: forward-port", "Forward port of issue #(\\d+)");
PortedIssue cherryPick = new PortedIssue("status: back-port", "Back port of issue #(\\d+)");
Set<PortedIssue> portedIssues = new HashSet<>(Arrays.asList(forwardPort, cherryPick));
ApplicationProperties properties = new ApplicationProperties(REPO, id, null,
new Issues(null, new IssuesExclude(labels), portedIssues), null);
new Issues(null, new IssuesExclude(labels), portedIssues), null, null);
this.generator = new ChangelogGenerator(this.service, properties);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ void collateWhenNoCustomSectionsUsesDefaultSections() {
Issue bug = createIssue("2", "bug");
Issue documentation = createIssue("3", "documentation");
Issue dependencyUpgrade = createIssue("4", "dependency-upgrade");
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, null, null, null);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, null, null, null,
null);
ChangelogSections sections = new ChangelogSections(properties);
Map<ChangelogSection, List<Issue>> collated = sections
.collate(Arrays.asList(enhancement, bug, documentation, dependencyUpgrade));
Expand All @@ -67,7 +68,7 @@ void collateWhenHasCustomSectionsUsesDefinedSections() {
Collections.singleton("bug"));
List<ApplicationProperties.Section> customSections = Arrays.asList(breaksPassivitySection, bugsSection);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, customSections,
null, null);
null, null, null);
ChangelogSections sections = new ChangelogSections(properties);
Issue bug = createIssue("1", "bug");
Issue nonPassive = createIssue("1", "breaks-passivity");
Expand All @@ -79,7 +80,8 @@ void collateWhenHasCustomSectionsUsesDefinedSections() {
@Test
void collateWhenNoIssuesInSectionExcludesSection() {
Issue bug = createIssue("1", "bug");
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, null, null, null);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, null, null, null,
null);
ChangelogSections sections = new ChangelogSections(properties);
Map<ChangelogSection, List<Issue>> collated = sections.collate(Collections.singletonList(bug));
Map<String, List<Issue>> bySection = getBySection(collated);
Expand All @@ -90,7 +92,8 @@ void collateWhenNoIssuesInSectionExcludesSection() {
void collateWhenIssueDoesNotMatchAnySectionLabelThenExcludesIssue() {
Issue bug = createIssue("1", "bug");
Issue nonPassive = createIssue("2", "non-passive");
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, null, null, null);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, null, null, null,
null);
ChangelogSections sections = new ChangelogSections(properties);
Map<ChangelogSection, List<Issue>> collated = sections.collate(Arrays.asList(bug, nonPassive));
Map<String, List<Issue>> bySection = getBySection(collated);
Expand All @@ -109,7 +112,7 @@ void collateWithDefaultsDoesNotAddIssueToMultipleSections() {
Collections.singleton("highlight"));
List<ApplicationProperties.Section> customSections = Arrays.asList(bugs, highlights);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, customSections,
null, null);
null, null, null);
ChangelogSections sections = new ChangelogSections(properties);
Map<ChangelogSection, List<Issue>> collated = sections.collate(Arrays.asList(bug, highlight, bugAndHighlight));
Map<String, List<Issue>> bySection = getBySection(collated);
Expand All @@ -129,7 +132,7 @@ void collateWithGroupsAddsIssuePerGroup() {
Collections.singleton("highlight"));
List<ApplicationProperties.Section> customSections = Arrays.asList(bugs, highlights);
ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, customSections,
null, null);
null, null, null);
ChangelogSections sections = new ChangelogSections(properties);
Map<ChangelogSection, List<Issue>> collated = sections.collate(Arrays.asList(bug, highlight, bugAndHighlight));
Map<String, List<Issue>> bySection = getBySection(collated);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## External Links

- [Release Notes Link 1](url1)
- [Release Notes Link 2](url2)
- [Release Notes Link 3](url3)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## External Links

- [Release Notes Link 1](url1)
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@ changelog:
title: "Nice one!"
exclude:
names: ["philwebb"]
external_links:
- name: "Release Notes 1"
location: "url1"
- name: "Release Notes 2"
location: "url2"

0 comments on commit b49f1cb

Please sign in to comment.