Skip to content
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 external links to be included in the changelog #55

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:/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 @@ -63,14 +63,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 +99,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 +295,36 @@ public Set<String> getNames() {

}

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

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

/**
* URL for 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 Down Expand Up @@ -73,6 +74,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 +86,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 +135,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 +208,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 @@ -139,7 +140,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 +154,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 +224,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 +240,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 +257,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"