diff --git a/src/main/java/io/spring/githubchangeloggenerator/ApplicationProperties.java b/src/main/java/io/spring/githubchangeloggenerator/ApplicationProperties.java index 2886022..8b9df41 100644 --- a/src/main/java/io/spring/githubchangeloggenerator/ApplicationProperties.java +++ b/src/main/java/io/spring/githubchangeloggenerator/ApplicationProperties.java @@ -49,6 +49,12 @@ public class ApplicationProperties { */ private final MilestoneReference milestoneReference; + /** + * The default prefix for headings and titles - typically this contains the header + * markdown e.g., "## ". + */ + private final String defaultTitlePrefix; + /** * Section definitions in the order that they should appear. */ @@ -70,10 +76,12 @@ public class ApplicationProperties { private final List externalLinks; public ApplicationProperties(Repository repository, @DefaultValue("title") MilestoneReference milestoneReference, - List
sections, Issues issues, Contributors contributors, List externalLinks) { + @DefaultValue("## ") String defaultTitlePrefix, List
sections, Issues issues, + Contributors contributors, List externalLinks) { Assert.notNull(repository, "Repository must not be null"); this.repository = repository; this.milestoneReference = milestoneReference; + this.defaultTitlePrefix = defaultTitlePrefix; 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); @@ -88,6 +96,10 @@ public MilestoneReference getMilestoneReference() { return this.milestoneReference; } + public String getDefaultTitlePrefix() { + return this.defaultTitlePrefix; + } + public List
getSections() { return this.sections; } diff --git a/src/main/java/io/spring/githubchangeloggenerator/ChangelogGenerator.java b/src/main/java/io/spring/githubchangeloggenerator/ChangelogGenerator.java index 63d26fa..d5eca15 100644 --- a/src/main/java/io/spring/githubchangeloggenerator/ChangelogGenerator.java +++ b/src/main/java/io/spring/githubchangeloggenerator/ChangelogGenerator.java @@ -63,6 +63,8 @@ public class ChangelogGenerator { private final MilestoneReference milestoneReference; + private final String defaultTitlePrefix; + private final IssueSort sort; private final Set excludeLabels; @@ -81,6 +83,7 @@ public ChangelogGenerator(GitHubService service, ApplicationProperties propertie this.service = service; this.repository = properties.getRepository(); this.milestoneReference = properties.getMilestoneReference(); + this.defaultTitlePrefix = properties.getDefaultTitlePrefix(); this.sort = properties.getIssues().getSort(); this.excludeLabels = properties.getIssues().getExcludes().getLabels(); this.excludeContributors = properties.getContributors().getExclude().getNames(); @@ -146,7 +149,7 @@ private void addSectionContent(StringBuilder content, Map { sort(section.getSort(), issues); content.append((content.length() != 0) ? String.format("%n") : ""); - content.append("## ").append(section).append(String.format("%n%n")); + content.append(defaultTitlePrefix).append(section).append(String.format("%n%n")); issues.stream().map(this::getFormattedIssue).forEach(content::append); }); } @@ -199,7 +202,7 @@ private boolean isIncludedContributor(User user) { } private void addContributorsContent(StringBuilder content, Set contributors) { - content.append(String.format("%n## ")); + content.append(String.format("%n%s", defaultTitlePrefix)); 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")); contributors.stream().map(this::formatContributors).forEach(content::append); @@ -210,7 +213,7 @@ private String formatContributors(User c) { } private void addExternalLinksContent(StringBuilder content, List externalLinks) { - content.append(String.format("## ")); + content.append(defaultTitlePrefix); content.append(String.format("External Links%n%n")); externalLinks.stream().map(this::formatExternalLinks).forEach(content::append); } diff --git a/src/test/java/io/spring/githubchangeloggenerator/ChangelogGeneratorTests.java b/src/test/java/io/spring/githubchangeloggenerator/ChangelogGeneratorTests.java index c097499..35e725d 100644 --- a/src/test/java/io/spring/githubchangeloggenerator/ChangelogGeneratorTests.java +++ b/src/test/java/io/spring/githubchangeloggenerator/ChangelogGeneratorTests.java @@ -140,7 +140,7 @@ void generateWhenHasExcludedContributors() throws Exception { issues.add(newPullRequest("Enhancement 1", "1", Type.ENHANCEMENT, "enhancement-1-url", contributor1)); 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, + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, "## ", null, null, new Contributors(null, new ContributorsExclude(Collections.singleton("contributor1"))), null); this.generator = new ChangelogGenerator(this.service, properties); assertChangelog("23").hasContent(from("output-with-excluded-contributors")); @@ -154,7 +154,7 @@ void generateWhenHasAllContributorsExcluded() throws Exception { issues.add(newPullRequest("Enhancement 1", "1", Type.ENHANCEMENT, "enhancement-1-url", contributor1)); 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, + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, "## ", null, null, new Contributors(null, new ContributorsExclude(Collections.singleton("*"))), null); this.generator = new ChangelogGenerator(this.service, properties); assertChangelog("23").hasContent(from("output-with-all-contributors-excluded")); @@ -224,7 +224,7 @@ void generateWhenSectionSortedByTitle() throws Exception { List
sections = new ArrayList<>(); Set labels = Collections.singleton("type: enhancement"); sections.add(new Section("Enhancements", null, IssueSort.TITLE, labels)); - ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, sections, + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, "## ", sections, new Issues(null, null, null), null, null); this.generator = new ChangelogGenerator(this.service, properties); List issues = new ArrayList<>(); @@ -240,7 +240,7 @@ void generateWhenAllIssuesSortedByTitle() throws Exception { List
sections = new ArrayList<>(); Set labels = Collections.singleton("type: enhancement"); sections.add(new Section("Enhancements", null, null, labels)); - ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, sections, + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, "## ", sections, new Issues(IssueSort.TITLE, null, null), null, null); this.generator = new ChangelogGenerator(this.service, properties); List issues = new ArrayList<>(); @@ -257,7 +257,7 @@ void generateWhenHasCustomContributorsTitle() throws Exception { List issues = new ArrayList<>(); 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, + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, "## ", null, null, new Contributors(":heart: Teamwork", null), null); this.generator = new ChangelogGenerator(this.service, properties); assertChangelog("23").hasContent(from("output-with-custom-contributors-title")); @@ -267,8 +267,8 @@ void generateWhenHasCustomContributorsTitle() throws Exception { void generateWhenOneExternalLink() throws Exception { List externalLinks = new ArrayList<>(); externalLinks.add(new ExternalLink("Release Notes Link 1", "url1")); - ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.ID, null, null, null, - externalLinks); + 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")); } @@ -279,18 +279,47 @@ void generateWhenMultipleExternalLink() throws Exception { 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); + 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")); } + @Test + void generateWithCustomDefaultTitlePrefix() throws Exception { + User contributor1 = createUser("contributor1", "contributor1-github-url"); + User contributor2 = createUser("contributor2", "contributor2-github-url"); + + List issues = new ArrayList<>(); + issues.add(newPullRequest("Enhancement 1", "1", Type.ENHANCEMENT, "enhancement-1-url", contributor1)); + issues.add(newPullRequest("Enhancement 2", "2", Type.ENHANCEMENT, "enhancement-2-url", contributor2)); + issues.add(newIssue("Enhancement c", "1", "enhancement-1-url", Type.ENHANCEMENT)); + issues.add(newIssue("Enhancement z", "2", "enhancement-2-url", Type.ENHANCEMENT)); + issues.add(newIssue("enHAncEMent a", "3", "enhancement-3-url", Type.ENHANCEMENT)); + given(this.service.getIssuesForMilestone(23, REPO)).willReturn(issues); + + List
sections = new ArrayList<>(); + Set labels = Collections.singleton("type: enhancement"); + sections.add(new Section("Enhancements", null, IssueSort.TITLE, labels)); + + List 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, "== ", sections, + new Issues(IssueSort.TITLE, null, null), new Contributors(null, null), externalLinks); + this.generator = new ChangelogGenerator(this.service, properties); + + assertChangelog("23").hasContent(from("output-with-custom-title-prefix")); + } + private void setupGenerator(MilestoneReference id) { Set 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 portedIssues = new HashSet<>(Arrays.asList(forwardPort, cherryPick)); - ApplicationProperties properties = new ApplicationProperties(REPO, id, null, + ApplicationProperties properties = new ApplicationProperties(REPO, id, "## ", null, new Issues(null, new IssuesExclude(labels), portedIssues), null, null); this.generator = new ChangelogGenerator(this.service, properties); } diff --git a/src/test/java/io/spring/githubchangeloggenerator/ChangelogSectionsTests.java b/src/test/java/io/spring/githubchangeloggenerator/ChangelogSectionsTests.java index 8465042..4e2fd7b 100644 --- a/src/test/java/io/spring/githubchangeloggenerator/ChangelogSectionsTests.java +++ b/src/test/java/io/spring/githubchangeloggenerator/ChangelogSectionsTests.java @@ -46,8 +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, - null); + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, "## ", null, null, + null, null); ChangelogSections sections = new ChangelogSections(properties); Map> collated = sections .collate(Arrays.asList(enhancement, bug, documentation, dependencyUpgrade)); @@ -67,8 +67,8 @@ void collateWhenHasCustomSectionsUsesDefinedSections() { ApplicationProperties.Section bugsSection = new ApplicationProperties.Section(":beetle: Bug Fixes", null, null, Collections.singleton("bug")); List customSections = Arrays.asList(breaksPassivitySection, bugsSection); - ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, customSections, - null, null, null); + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, "## ", + customSections, null, null, null); ChangelogSections sections = new ChangelogSections(properties); Issue bug = createIssue("1", "bug"); Issue nonPassive = createIssue("1", "breaks-passivity"); @@ -80,8 +80,8 @@ void collateWhenHasCustomSectionsUsesDefinedSections() { @Test void collateWhenNoIssuesInSectionExcludesSection() { Issue bug = createIssue("1", "bug"); - ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, null, null, null, - null); + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, "## ", null, null, + null, null); ChangelogSections sections = new ChangelogSections(properties); Map> collated = sections.collate(Collections.singletonList(bug)); Map> bySection = getBySection(collated); @@ -92,8 +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, - null); + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, "## ", null, null, + null, null); ChangelogSections sections = new ChangelogSections(properties); Map> collated = sections.collate(Arrays.asList(bug, nonPassive)); Map> bySection = getBySection(collated); @@ -111,8 +111,8 @@ void collateWithDefaultsDoesNotAddIssueToMultipleSections() { ApplicationProperties.Section highlights = new ApplicationProperties.Section("Highlights", null, null, Collections.singleton("highlight")); List customSections = Arrays.asList(bugs, highlights); - ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, customSections, - null, null, null); + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, "## ", + customSections, null, null, null); ChangelogSections sections = new ChangelogSections(properties); Map> collated = sections.collate(Arrays.asList(bug, highlight, bugAndHighlight)); Map> bySection = getBySection(collated); @@ -131,8 +131,8 @@ void collateWithGroupsAddsIssuePerGroup() { ApplicationProperties.Section highlights = new ApplicationProperties.Section("Highlights", "highlights", null, Collections.singleton("highlight")); List customSections = Arrays.asList(bugs, highlights); - ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, customSections, - null, null, null); + ApplicationProperties properties = new ApplicationProperties(REPO, MilestoneReference.TITLE, "## ", + customSections, null, null, null); ChangelogSections sections = new ChangelogSections(properties); Map> collated = sections.collate(Arrays.asList(bug, highlight, bugAndHighlight)); Map> bySection = getBySection(collated); diff --git a/src/test/resources/io/spring/githubchangeloggenerator/output-with-custom-title-prefix b/src/test/resources/io/spring/githubchangeloggenerator/output-with-custom-title-prefix new file mode 100644 index 0000000..5b38fe2 --- /dev/null +++ b/src/test/resources/io/spring/githubchangeloggenerator/output-with-custom-title-prefix @@ -0,0 +1,19 @@ +== Enhancements + +- Enhancement 1 [#1](enhancement-1-url) +- Enhancement 2 [#2](enhancement-2-url) +- enHAncEMent a [#3](enhancement-3-url) +- Enhancement c [#1](enhancement-1-url) +- Enhancement z [#2](enhancement-2-url) + +== :heart: Contributors + +We'd like to thank all the contributors who worked on this release! + +- [@contributor1](contributor1-github-url) +- [@contributor2](contributor2-github-url) +== External Links + +- [Release Notes Link 1](url1) +- [Release Notes Link 2](url2) +- [Release Notes Link 3](url3)