From b5dda8253e83a5149ddee503913ff0fcbe86967a Mon Sep 17 00:00:00 2001 From: Simon Prochazka Date: Tue, 22 Oct 2019 23:44:50 +0200 Subject: [PATCH] feat: build full commit - updates expected output files to provide an example of simple and full outputs - adds logic for handling new lines (Markdown requires two empty spaces followed by a newline to correctly create a new line in text) - adds logic for open by default in the feature section - adds collapsible sections --- expected-output-simple.md | 19 +++++++++ expected-output.md | 27 +++++++++---- internal/text/build_commit_log.go | 10 +++-- internal/text/build_section.go | 2 +- internal/text/build_single_commit.go | 47 ++++++++++++++++++++--- internal/text/build_single_commit_test.go | 20 ++++++++++ internal/text/release_notes_test.go | 32 ++++++++++++++- internal/text/sections.go | 5 ++- 8 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 expected-output-simple.md create mode 100644 internal/text/build_single_commit_test.go diff --git a/expected-output-simple.md b/expected-output-simple.md new file mode 100644 index 0000000..2ef5f17 --- /dev/null +++ b/expected-output-simple.md @@ -0,0 +1,19 @@ +test heading + +## Features :rocket: + +0000000 ci test + +## Bug fixes :bug: + +0000000 huge bug + +## Chores and Improvements :wrench: + +0000000 testing +0000000 this should end up in chores + +## Other :package: + +0000000 merge master in something +0000000 random diff --git a/expected-output.md b/expected-output.md index 0aa3492..572cbf8 100644 --- a/expected-output.md +++ b/expected-output.md @@ -1,20 +1,31 @@ - +test heading ## Features :rocket: -- 0000000 ci test +
0000000 ci test + +- Body + +
## Bug fixes :bug: -- 0000000 huge bug +
0000000 huge bug + +Body + +
## Chores and Improvements :wrench: -- 0000000 testing -- 0000000 this should end up in chores +
0000000 testing -## Other :package: +- Body -- 0000000 merge master in something -- 0000000 random +
+0000000 this should end up in chores + +## Other :package: +0000000 merge master in something +0000000 random diff --git a/internal/text/build_commit_log.go b/internal/text/build_commit_log.go index de564a4..281a76a 100644 --- a/internal/text/build_commit_log.go +++ b/internal/text/build_commit_log.go @@ -2,11 +2,15 @@ package text import "strings" -func (r *ReleaseNotes) buildCommitLog(commits []Commit) string { +func (r *ReleaseNotes) buildCommitLog(commits []Commit, open bool) string { builder := strings.Builder{} - for _, commit := range commits { - builder.WriteString(r.buildSingleCommit(commit)) + for index, commit := range commits { + last := false + if index+1 == len(commits) { + last = true + } + builder.WriteString(r.buildSingleCommit(commit, last, open)) } builder.WriteString("\n") diff --git a/internal/text/build_section.go b/internal/text/build_section.go index 7eb74e2..4d4ee01 100644 --- a/internal/text/build_section.go +++ b/internal/text/build_section.go @@ -6,7 +6,7 @@ func (r *ReleaseNotes) buildSection(category string, commits []Commit) string { builder := strings.Builder{} builder.WriteString(r.buildHeading(category)) - builder.WriteString(r.buildCommitLog(commits)) + builder.WriteString(r.buildCommitLog(commits, sectionHeadings[category].openByDefault)) return builder.String() } diff --git a/internal/text/build_single_commit.go b/internal/text/build_single_commit.go index e618fbe..f581739 100644 --- a/internal/text/build_single_commit.go +++ b/internal/text/build_single_commit.go @@ -1,12 +1,26 @@ package text -import "strings" +import ( + "fmt" + "strings" +) -func (r *ReleaseNotes) buildSingleCommit(commit Commit) string { +func (r *ReleaseNotes) buildSingleCommit(commit Commit, isLast, open bool) string { builder := strings.Builder{} - commitMessage := buildSimpleCommit(commit) - builder.WriteString(commitMessage) + if r.Simple || commit.Body == "" { + simpleCommitMessage := buildSimpleCommit(commit) + builder.WriteString(simpleCommitMessage) + } else { + commitMessage := buildFullCommit(commit, open) + builder.WriteString(commitMessage) + } + + // Double space + \n creates a new line in markdown + if !isLast { + builder.WriteString(" ") + } + builder.WriteString("\n") return builder.String() } @@ -14,12 +28,33 @@ func (r *ReleaseNotes) buildSingleCommit(commit Commit) string { func buildSimpleCommit(commit Commit) string { builder := strings.Builder{} - builder.WriteString("- ") // Short version of hash usable on Github builder.WriteString(commit.Hash.String()[:7]) builder.WriteString(" ") builder.WriteString(commit.Heading) - builder.WriteString("\n") + + return builder.String() +} + +func buildFullCommit(commit Commit, open bool) string { + builder := strings.Builder{} + + // closed receives empty string + openString := "" + if open { + openString = " open" + } + detailsWrapperStart := fmt.Sprintf("", openString) + builder.WriteString(detailsWrapperStart) + builder.WriteString("") + builder.WriteString(commit.Hash.String()[:7]) + builder.WriteString(" ") + builder.WriteString(commit.Heading) + builder.WriteString("") + builder.WriteString("\n\n") + builder.WriteString(commit.Body) + builder.WriteString("\n\n") + builder.WriteString("") return builder.String() } diff --git a/internal/text/build_single_commit_test.go b/internal/text/build_single_commit_test.go new file mode 100644 index 0000000..3ec8fad --- /dev/null +++ b/internal/text/build_single_commit_test.go @@ -0,0 +1,20 @@ +package text + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBuildFullCommit(t *testing.T) { + testCommit := Commit{Heading: "stuff", Body: "hi"} + + text := buildFullCommit(testCommit, false) + + expectedText := "
0000000 stuff\n\nhi\n\n
" + assert.Equal(t, expectedText, text) + + expectedOpenText := "
0000000 stuff\n\nhi\n\n
" + openText := buildFullCommit(testCommit, true) + assert.Equal(t, expectedOpenText, openText) +} diff --git a/internal/text/release_notes_test.go b/internal/text/release_notes_test.go index 04ce001..d2d3092 100644 --- a/internal/text/release_notes_test.go +++ b/internal/text/release_notes_test.go @@ -12,12 +12,40 @@ func TestReleaseNotes(t *testing.T) { notes := ReleaseNotes{} file, err := os.Open("../../expected-output.md") + assert.NoError(t, err) + defer file.Close() + b, err := ioutil.ReadAll(file) + assert.NoError(t, err) + expected := string(b) + + sections := map[string][]Commit{ + "features": []Commit{Commit{Category: "feat", Scope: "ci", Heading: "ci test", Body: "- Body"}}, + "chores": []Commit{Commit{Category: "chore", Scope: "", Heading: "testing", Body: "- Body"}, Commit{Category: "improvement", Scope: "", Heading: "this should end up in chores"}}, + "bugs": []Commit{Commit{Category: "bug", Scope: "", Heading: "huge bug", Body: "Body"}}, + "others": []Commit{Commit{Category: "other", Scope: "", Heading: "merge master in something"}, Commit{Category: "bs", Scope: "", Heading: "random"}}, + } + + releaseNotes := notes.Generate(sections) + + assert.Equal(t, expected+"\n", "test heading"+releaseNotes) +} + +func TestReleaseNotesSimple(t *testing.T) { + notes := ReleaseNotes{} + file, err := os.Open("../../expected-output-simple.md") + + assert.NoError(t, err) + + defer file.Close() + b, err := ioutil.ReadAll(file) + assert.NoError(t, err) + expected := string(b) sections := map[string][]Commit{ @@ -29,12 +57,12 @@ func TestReleaseNotes(t *testing.T) { releaseNotes := notes.Generate(sections) - assert.Equal(t, expected, releaseNotes) + assert.Equal(t, expected+"\n", "test heading"+releaseNotes) } func TestReleaseNotesWithMissingSections(t *testing.T) { notes := ReleaseNotes{} - expected := "\n\n## Features :rocket:\n\n- 0000000 ci test\n\n" + expected := "\n\n## Features :rocket:\n\n0000000 ci test\n\n" sections := map[string][]Commit{ "features": []Commit{Commit{Heading: "ci test"}}, diff --git a/internal/text/sections.go b/internal/text/sections.go index 7baba2d..2562d33 100644 --- a/internal/text/sections.go +++ b/internal/text/sections.go @@ -3,12 +3,13 @@ package text type sectionInfo struct { title string icon string + // whether the section should not be collapsed by default + openByDefault bool } var sectionHeadings = map[string]sectionInfo{ - "breaking": sectionInfo{title: "Breaking Changes", icon: "warning"}, - "features": sectionInfo{title: "Features", icon: "rocket"}, + "features": sectionInfo{title: "Features", icon: "rocket", openByDefault: true}, "chores": sectionInfo{title: "Chores and Improvements", icon: "wrench"}, "bugs": sectionInfo{title: "Bug fixes", icon: "bug"}, "others": sectionInfo{title: "Other", icon: "package"},