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:
parent
7506f0ff37
commit
6277ab9ae3
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user