1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-02-13 13:48:40 +02:00

feat: added sorting support to the changelog pipe

We can now add:

```yaml
changelog:
	sort: asc
```

to group together our commits by prefix or just to sort them...

Closes #284
This commit is contained in:
Carlos Alexandro Becker 2017-10-19 20:44:12 -02:00 committed by Carlos Alexandro Becker
parent 7506f0ff37
commit 6277ab9ae3
4 changed files with 144 additions and 13 deletions

View File

@ -201,6 +201,7 @@ type Filters struct {
// Changelog Config
type Changelog struct {
Filters Filters `yaml:",omitempty"`
Sort string `yaml:",omitempty"`
}
// Project includes all project configuration

View File

@ -45,10 +45,14 @@ changelog:
filters:
# commit messages matching the regexp listed here will be removed from
# the changelog
# Default is emtpy
exclude:
- '^docs:'
- typo
- (?i)foo
# could either be asc, desc or empty
# Default is empty
sort: asc
```
## Custom release notes

View File

@ -2,8 +2,10 @@
package changelog
import (
"errors"
"fmt"
"regexp"
"sort"
"strings"
"github.com/goreleaser/goreleaser/context"
@ -11,6 +13,9 @@ import (
"github.com/goreleaser/goreleaser/pipeline"
)
// ErrInvalidSortDirection happens when the sort order is invalid
var ErrInvalidSortDirection = errors.New("invalid sort direction")
// Pipe for checksums
type Pipe struct{}
@ -27,34 +32,85 @@ func (Pipe) Run(ctx *context.Context) error {
if ctx.Snapshot {
return pipeline.Skip("not available for snapshots")
}
log, err := getChangelog(ctx.Git.CurrentTag)
if err != nil {
if err := checkSortDirection(ctx.Config.Changelog.Sort); err != nil {
return err
}
var entries = strings.Split(log, "\n")
for _, filter := range ctx.Config.Changelog.Filters.Exclude {
r, err := regexp.Compile(filter)
if err != nil {
return err
}
entries = remove(r, entries)
entries, err := buildChangelog(ctx)
if err != nil {
return err
}
ctx.ReleaseNotes = fmt.Sprintf("## Changelog\n\n%v", strings.Join(entries, "\n"))
return nil
}
func checkSortDirection(mode string) error {
switch mode {
case "":
fallthrough
case "asc":
fallthrough
case "desc":
return nil
}
return ErrInvalidSortDirection
}
func buildChangelog(ctx *context.Context) ([]string, error) {
log, err := getChangelog(ctx.Git.CurrentTag)
if err != nil {
return nil, err
}
var entries = strings.Split(log, "\n")
entries = entries[0 : len(entries)-1]
entries, err = filterEntries(ctx, entries)
if err != nil {
return entries, err
}
return sortEntries(ctx, entries), nil
}
func filterEntries(ctx *context.Context, entries []string) ([]string, error) {
for _, filter := range ctx.Config.Changelog.Filters.Exclude {
r, err := regexp.Compile(filter)
if err != nil {
return entries, err
}
entries = remove(r, entries)
}
return entries, nil
}
func sortEntries(ctx *context.Context, entries []string) []string {
var direction = ctx.Config.Changelog.Sort
if direction == "" {
return entries
}
var result = make([]string, len(entries))
copy(result, entries)
sort.Slice(result, func(i, j int) bool {
_, imsg := extractCommitInfo(result[i])
_, jmsg := extractCommitInfo(result[j])
if direction == "asc" {
return strings.Compare(imsg, jmsg) < 0
}
return strings.Compare(imsg, jmsg) > 0
})
return result
}
func remove(filter *regexp.Regexp, entries []string) (result []string) {
for _, entry := range entries {
if !match(filter, entry) {
_, msg := extractCommitInfo(entry)
if !filter.MatchString(msg) {
result = append(result, entry)
}
}
return result
}
func match(filter *regexp.Regexp, line string) bool {
s := strings.Join(strings.SplitAfter(line, " ")[1:], "")
return filter.MatchString(s)
func extractCommitInfo(line string) (hash, msg string) {
ss := strings.Split(line, " ")
return ss[0], strings.Join(ss[1:], " ")
}
func getChangelog(tag string) (string, error) {

View File

@ -3,6 +3,7 @@ package changelog
import (
"testing"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/testlib"
@ -65,6 +66,75 @@ func TestChangelog(t *testing.T) {
assert.NotContains(t, ctx.ReleaseNotes, "from goreleaser/some-branch")
}
func TestChangelogSort(t *testing.T) {
f, back := testlib.Mktmp(t)
log.Info(f)
defer back()
testlib.GitInit(t)
testlib.GitCommit(t, "whatever")
testlib.GitTag(t, "v0.9.9")
testlib.GitCommit(t, "c: commit")
testlib.GitCommit(t, "a: commit")
testlib.GitCommit(t, "b: commit")
testlib.GitTag(t, "v1.0.0")
var ctx = context.New(config.Project{
Changelog: config.Changelog{},
})
ctx.Git.CurrentTag = "v1.0.0"
for _, cfg := range []struct {
Sort string
Entries []string
}{
{
Sort: "",
Entries: []string{
"b: commit",
"a: commit",
"c: commit",
},
},
{
Sort: "asc",
Entries: []string{
"a: commit",
"b: commit",
"c: commit",
},
},
{
Sort: "desc",
Entries: []string{
"c: commit",
"b: commit",
"a: commit",
},
},
} {
t.Run("changelog sort='"+cfg.Sort+"'", func(t *testing.T) {
ctx.Config.Changelog.Sort = cfg.Sort
entries, err := buildChangelog(ctx)
assert.NoError(t, err)
assert.Len(t, entries, len(cfg.Entries))
var changes []string
for _, line := range entries {
_, msg := extractCommitInfo(line)
changes = append(changes, msg)
}
assert.EqualValues(t, cfg.Entries, changes)
})
}
}
func TestChangelogInvalidSort(t *testing.T) {
var ctx = context.New(config.Project{
Changelog: config.Changelog{
Sort: "dope",
},
})
assert.EqualError(t, Pipe{}.Run(ctx), ErrInvalidSortDirection.Error())
}
func TestChangelogOfFirstRelease(t *testing.T) {
_, back := testlib.Mktmp(t)
defer back()