mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-06-02 23:27:44 +02:00
fix: do not filter and sort github-native changelog (#2803)
* fix: do not filter and sort github-native Signed-off-by: Carlos A Becker <caarlos0@gmail.com> * refactor: improve code a bit Signed-off-by: Carlos A Becker <caarlos0@gmail.com> * refactor: improve code a bit Signed-off-by: Carlos A Becker <caarlos0@gmail.com> * fix: changelog header Signed-off-by: Carlos A Becker <caarlos0@gmail.com>
This commit is contained in:
parent
72535f288c
commit
bdfb09cfb7
@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/goreleaser/goreleaser/internal/client"
|
"github.com/goreleaser/goreleaser/internal/client"
|
||||||
"github.com/goreleaser/goreleaser/internal/git"
|
"github.com/goreleaser/goreleaser/internal/git"
|
||||||
"github.com/goreleaser/goreleaser/internal/tmpl"
|
"github.com/goreleaser/goreleaser/internal/tmpl"
|
||||||
"github.com/goreleaser/goreleaser/pkg/config"
|
|
||||||
"github.com/goreleaser/goreleaser/pkg/context"
|
"github.com/goreleaser/goreleaser/pkg/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,6 +22,19 @@ var ErrInvalidSortDirection = errors.New("invalid sort direction")
|
|||||||
|
|
||||||
const li = "* "
|
const li = "* "
|
||||||
|
|
||||||
|
type useChangelog string
|
||||||
|
|
||||||
|
func (u useChangelog) formatable() bool {
|
||||||
|
return u != "github-native"
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
useGit = "git"
|
||||||
|
useGitHub = "github"
|
||||||
|
useGitLab = "gitlab"
|
||||||
|
useGitHubNative = "github-native"
|
||||||
|
)
|
||||||
|
|
||||||
// Pipe for checksums.
|
// Pipe for checksums.
|
||||||
type Pipe struct{}
|
type Pipe struct{}
|
||||||
|
|
||||||
@ -60,55 +72,11 @@ func (Pipe) Run(ctx *context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
changelogStringJoiner := "\n"
|
changes, err := formatChangelog(ctx, entries)
|
||||||
if ctx.TokenType == context.TokenTypeGitLab || ctx.TokenType == context.TokenTypeGitea {
|
if err != nil {
|
||||||
// We need two or more whitespace to let markdown interpret
|
return err
|
||||||
// it as newline. See https://docs.gitlab.com/ee/user/markdown.html#newlines for details
|
|
||||||
log.Debug("is gitlab or gitea changelog")
|
|
||||||
changelogStringJoiner = " \n"
|
|
||||||
}
|
|
||||||
|
|
||||||
changelogElements := []string{
|
|
||||||
"## Changelog",
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Config.Changelog.Use == "github-native" {
|
|
||||||
changelogElements = []string{strings.Join(entries, changelogStringJoiner)}
|
|
||||||
} else if shouldGroup(ctx.Config.Changelog) {
|
|
||||||
log.Debug("grouping entries")
|
|
||||||
groups := ctx.Config.Changelog.Groups
|
|
||||||
|
|
||||||
sort.Slice(groups, func(i, j int) bool { return groups[i].Order < groups[j].Order })
|
|
||||||
for _, group := range groups {
|
|
||||||
items := make([]string, 0)
|
|
||||||
if group.Regexp == "" {
|
|
||||||
// If no regexp is provided, we purge all strikethrough entries and add remaining entries to the list
|
|
||||||
items = getAllNonEmpty(entries)
|
|
||||||
// clear array
|
|
||||||
entries = nil
|
|
||||||
} else {
|
|
||||||
regex, err := regexp.Compile(group.Regexp)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to group into %q: %w", group.Title, err)
|
|
||||||
}
|
|
||||||
for i, entry := range entries {
|
|
||||||
match := regex.MatchString(entry)
|
|
||||||
if match {
|
|
||||||
items = append(items, li+entry)
|
|
||||||
// Striking out the matched entry
|
|
||||||
entries[i] = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(items) > 0 {
|
|
||||||
changelogElements = append(changelogElements, fmt.Sprintf("### %s", group.Title))
|
|
||||||
changelogElements = append(changelogElements, strings.Join(items, changelogStringJoiner))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Debug("not grouping entries")
|
|
||||||
changelogElements = append(changelogElements, strings.Join(getAllNonEmpty(entries), changelogStringJoiner))
|
|
||||||
}
|
}
|
||||||
|
changelogElements := []string{changes}
|
||||||
|
|
||||||
if header != "" {
|
if header != "" {
|
||||||
changelogElements = append([]string{header}, changelogElements...)
|
changelogElements = append([]string{header}, changelogElements...)
|
||||||
@ -127,11 +95,60 @@ func (Pipe) Run(ctx *context.Context) error {
|
|||||||
return os.WriteFile(path, []byte(ctx.ReleaseNotes), 0o644) //nolint: gosec
|
return os.WriteFile(path, []byte(ctx.ReleaseNotes), 0o644) //nolint: gosec
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldGroup(cfg config.Changelog) bool {
|
func formatChangelog(ctx *context.Context, entries []string) (string, error) {
|
||||||
return len(cfg.Groups) > 0 && cfg.Use != "github-native"
|
newLine := "\n"
|
||||||
|
if ctx.TokenType == context.TokenTypeGitLab || ctx.TokenType == context.TokenTypeGitea {
|
||||||
|
// We need two or more whitespace to let markdown interpret
|
||||||
|
// it as newline. See https://docs.gitlab.com/ee/user/markdown.html#newlines for details
|
||||||
|
log.Debug("is gitlab or gitea changelog")
|
||||||
|
newLine = " \n"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !useChangelog(ctx.Config.Changelog.Use).formatable() {
|
||||||
|
return strings.Join(entries, newLine), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []string{"## Changelog"}
|
||||||
|
if len(ctx.Config.Changelog.Groups) == 0 {
|
||||||
|
log.Debug("not grouping entries")
|
||||||
|
return strings.Join(append(result, filterAndPrefixItems(entries)...), newLine), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("grouping entries")
|
||||||
|
groups := ctx.Config.Changelog.Groups
|
||||||
|
|
||||||
|
sort.Slice(groups, func(i, j int) bool { return groups[i].Order < groups[j].Order })
|
||||||
|
for _, group := range groups {
|
||||||
|
items := make([]string, 0)
|
||||||
|
if group.Regexp == "" {
|
||||||
|
// If no regexp is provided, we purge all strikethrough entries and add remaining entries to the list
|
||||||
|
items = filterAndPrefixItems(entries)
|
||||||
|
// clear array
|
||||||
|
entries = nil
|
||||||
|
} else {
|
||||||
|
regex, err := regexp.Compile(group.Regexp)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to group into %q: %w", group.Title, err)
|
||||||
|
}
|
||||||
|
for i, entry := range entries {
|
||||||
|
match := regex.MatchString(entry)
|
||||||
|
if match {
|
||||||
|
items = append(items, li+entry)
|
||||||
|
// Striking out the matched entry
|
||||||
|
entries[i] = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(items) > 0 {
|
||||||
|
result = append(result, fmt.Sprintf("### %s", group.Title))
|
||||||
|
result = append(result, items...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(result, newLine), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllNonEmpty(ss []string) []string {
|
func filterAndPrefixItems(ss []string) []string {
|
||||||
var r []string
|
var r []string
|
||||||
for _, s := range ss {
|
for _, s := range ss {
|
||||||
if s != "" {
|
if s != "" {
|
||||||
@ -171,6 +188,9 @@ func buildChangelog(ctx *context.Context) ([]string, error) {
|
|||||||
if lastLine := entries[len(entries)-1]; strings.TrimSpace(lastLine) == "" {
|
if lastLine := entries[len(entries)-1]; strings.TrimSpace(lastLine) == "" {
|
||||||
entries = entries[0 : len(entries)-1]
|
entries = entries[0 : len(entries)-1]
|
||||||
}
|
}
|
||||||
|
if !useChangelog(ctx.Config.Changelog.Use).formatable() {
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
entries, err = filterEntries(ctx, entries)
|
entries, err = filterEntries(ctx, entries)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return entries, err
|
return entries, err
|
||||||
@ -243,15 +263,15 @@ func doGetChangelog(ctx *context.Context, prev, tag string) (string, error) {
|
|||||||
|
|
||||||
func getChangeloger(ctx *context.Context) (changeloger, error) {
|
func getChangeloger(ctx *context.Context) (changeloger, error) {
|
||||||
switch ctx.Config.Changelog.Use {
|
switch ctx.Config.Changelog.Use {
|
||||||
case "git":
|
case useGit:
|
||||||
fallthrough
|
fallthrough
|
||||||
case "":
|
case "":
|
||||||
return gitChangeloger{}, nil
|
return gitChangeloger{}, nil
|
||||||
case "github":
|
case useGitHub:
|
||||||
fallthrough
|
fallthrough
|
||||||
case "gitlab":
|
case useGitLab:
|
||||||
return newSCMChangeloger(ctx)
|
return newSCMChangeloger(ctx)
|
||||||
case "github-native":
|
case useGitHubNative:
|
||||||
return newGithubChangeloger(ctx)
|
return newGithubChangeloger(ctx)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid changelog.use: %q", ctx.Config.Changelog.Use)
|
return nil, fmt.Errorf("invalid changelog.use: %q", ctx.Config.Changelog.Use)
|
||||||
|
@ -69,6 +69,7 @@ func TestChangelog(t *testing.T) {
|
|||||||
ctx := context.New(config.Project{
|
ctx := context.New(config.Project{
|
||||||
Dist: folder,
|
Dist: folder,
|
||||||
Changelog: config.Changelog{
|
Changelog: config.Changelog{
|
||||||
|
Use: "git",
|
||||||
Filters: config.Filters{
|
Filters: config.Filters{
|
||||||
Exclude: []string{
|
Exclude: []string{
|
||||||
"docs:",
|
"docs:",
|
||||||
@ -419,7 +420,7 @@ func TestChangeLogWithoutReleaseFooter(t *testing.T) {
|
|||||||
func TestGetChangelogGitHub(t *testing.T) {
|
func TestGetChangelogGitHub(t *testing.T) {
|
||||||
ctx := context.New(config.Project{
|
ctx := context.New(config.Project{
|
||||||
Changelog: config.Changelog{
|
Changelog: config.Changelog{
|
||||||
Use: "github",
|
Use: useGitHub,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -441,11 +442,16 @@ func TestGetChangelogGitHub(t *testing.T) {
|
|||||||
func TestGetChangelogGitHubNative(t *testing.T) {
|
func TestGetChangelogGitHubNative(t *testing.T) {
|
||||||
ctx := context.New(config.Project{
|
ctx := context.New(config.Project{
|
||||||
Changelog: config.Changelog{
|
Changelog: config.Changelog{
|
||||||
Use: "github-native",
|
Use: useGitHubNative,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expected := "**Full Changelog**: https://github.com/gorelease/goreleaser/compare/v0.180.1...v0.180.2"
|
expected := `## What's changed
|
||||||
|
|
||||||
|
* Foo bar test
|
||||||
|
|
||||||
|
**Full Changelog**: https://github.com/gorelease/goreleaser/compare/v0.180.1...v0.180.2
|
||||||
|
`
|
||||||
mock := client.NewMock()
|
mock := client.NewMock()
|
||||||
mock.ReleaseNotes = expected
|
mock.ReleaseNotes = expected
|
||||||
l := githubNativeChangeloger{
|
l := githubNativeChangeloger{
|
||||||
@ -467,20 +473,20 @@ func TestGetChangeloger(t *testing.T) {
|
|||||||
require.IsType(t, c, gitChangeloger{})
|
require.IsType(t, c, gitChangeloger{})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("git", func(t *testing.T) {
|
t.Run(useGit, func(t *testing.T) {
|
||||||
c, err := getChangeloger(context.New(config.Project{
|
c, err := getChangeloger(context.New(config.Project{
|
||||||
Changelog: config.Changelog{
|
Changelog: config.Changelog{
|
||||||
Use: "git",
|
Use: useGit,
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.IsType(t, c, gitChangeloger{})
|
require.IsType(t, c, gitChangeloger{})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("github", func(t *testing.T) {
|
t.Run(useGitHub, func(t *testing.T) {
|
||||||
ctx := context.New(config.Project{
|
ctx := context.New(config.Project{
|
||||||
Changelog: config.Changelog{
|
Changelog: config.Changelog{
|
||||||
Use: "github",
|
Use: useGitHub,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ctx.TokenType = context.TokenTypeGitHub
|
ctx.TokenType = context.TokenTypeGitHub
|
||||||
@ -489,10 +495,10 @@ func TestGetChangeloger(t *testing.T) {
|
|||||||
require.IsType(t, c, &scmChangeloger{})
|
require.IsType(t, c, &scmChangeloger{})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("github-native", func(t *testing.T) {
|
t.Run(useGitHubNative, func(t *testing.T) {
|
||||||
ctx := context.New(config.Project{
|
ctx := context.New(config.Project{
|
||||||
Changelog: config.Changelog{
|
Changelog: config.Changelog{
|
||||||
Use: "github-native",
|
Use: useGitHubNative,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ctx.TokenType = context.TokenTypeGitHub
|
ctx.TokenType = context.TokenTypeGitHub
|
||||||
@ -501,10 +507,10 @@ func TestGetChangeloger(t *testing.T) {
|
|||||||
require.IsType(t, c, &githubNativeChangeloger{})
|
require.IsType(t, c, &githubNativeChangeloger{})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("gitlab", func(t *testing.T) {
|
t.Run(useGitLab, func(t *testing.T) {
|
||||||
ctx := context.New(config.Project{
|
ctx := context.New(config.Project{
|
||||||
Changelog: config.Changelog{
|
Changelog: config.Changelog{
|
||||||
Use: "gitlab",
|
Use: useGitLab,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ctx.TokenType = context.TokenTypeGitLab
|
ctx.TokenType = context.TokenTypeGitLab
|
||||||
@ -617,30 +623,84 @@ func TestGroupBadRegex(t *testing.T) {
|
|||||||
require.EqualError(t, Pipe{}.Run(ctx), `failed to group into "Something": error parsing regexp: missing closing ]: `+"`"+`[(\w`+"`")
|
require.EqualError(t, Pipe{}.Run(ctx), `failed to group into "Something": error parsing regexp: missing closing ]: `+"`"+`[(\w`+"`")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldGroup(t *testing.T) {
|
func TestChangelogFormat(t *testing.T) {
|
||||||
t.Run("with groups", func(t *testing.T) {
|
t.Run("without groups", func(t *testing.T) {
|
||||||
t.Run("github-native", func(t *testing.T) {
|
makeConf := func(u string) config.Project {
|
||||||
require.False(t, shouldGroup(config.Changelog{
|
return config.Project{Changelog: config.Changelog{Use: u}}
|
||||||
Use: "github-native",
|
}
|
||||||
Groups: []config.ChangeLogGroup{{}},
|
|
||||||
}))
|
for _, use := range []string{useGit, useGitHub, useGitLab} {
|
||||||
})
|
t.Run(use, func(t *testing.T) {
|
||||||
for _, u := range []string{"git", "github", "gitlab"} {
|
out, err := formatChangelog(
|
||||||
t.Run(u, func(t *testing.T) {
|
context.New(makeConf(use)),
|
||||||
require.True(t, shouldGroup(config.Changelog{
|
[]string{
|
||||||
Use: u,
|
"aea123 foo",
|
||||||
Groups: []config.ChangeLogGroup{{}},
|
"aef653 bar",
|
||||||
}))
|
},
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `## Changelog
|
||||||
|
* aea123 foo
|
||||||
|
* aef653 bar`, out)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Run(useGitHubNative, func(t *testing.T) {
|
||||||
|
out, err := formatChangelog(
|
||||||
|
context.New(makeConf(useGitHubNative)),
|
||||||
|
[]string{
|
||||||
|
"# What's changed",
|
||||||
|
"* aea123 foo",
|
||||||
|
"* aef653 bar",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `# What's changed
|
||||||
|
* aea123 foo
|
||||||
|
* aef653 bar`, out)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("without groups", func(t *testing.T) {
|
t.Run("with groups", func(t *testing.T) {
|
||||||
for _, u := range []string{"git", "github", "gitlab", "github-native"} {
|
makeConf := func(u string) config.Project {
|
||||||
t.Run(u, func(t *testing.T) {
|
return config.Project{
|
||||||
require.False(t, shouldGroup(config.Changelog{
|
Changelog: config.Changelog{
|
||||||
Use: u,
|
Use: u,
|
||||||
}))
|
Groups: []config.ChangeLogGroup{
|
||||||
|
{Title: "catch-all"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run(useGitHubNative, func(t *testing.T) {
|
||||||
|
out, err := formatChangelog(
|
||||||
|
context.New(makeConf(useGitHubNative)),
|
||||||
|
[]string{
|
||||||
|
"# What's changed",
|
||||||
|
"* aea123 foo",
|
||||||
|
"* aef653 bar",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `# What's changed
|
||||||
|
* aea123 foo
|
||||||
|
* aef653 bar`, out)
|
||||||
|
})
|
||||||
|
for _, use := range []string{useGit, useGitHub, useGitLab} {
|
||||||
|
t.Run(use, func(t *testing.T) {
|
||||||
|
out, err := formatChangelog(
|
||||||
|
context.New(makeConf(use)),
|
||||||
|
[]string{
|
||||||
|
"aea123 foo",
|
||||||
|
"aef653 bar",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, `## Changelog
|
||||||
|
### catch-all
|
||||||
|
* aea123 foo
|
||||||
|
* aef653 bar`, out)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user