Skip to content

Commit

Permalink
fix: native changeloger without previous tag (#3668)
Browse files Browse the repository at this point in the history
closes #3662

Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
  • Loading branch information
caarlos0 committed Dec 29, 2022
1 parent e7a2361 commit da23357
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 38 deletions.
4 changes: 2 additions & 2 deletions cmd/release.go
Expand Up @@ -70,7 +70,7 @@ func newReleaseCmd() *releaseCmd {
cmd.Flags().StringVar(&root.opts.releaseNotesTmpl, "release-notes-tmpl", "", "Load custom release notes from a templated markdown file (overrides --release-notes)")
cmd.Flags().StringVar(&root.opts.releaseHeaderTmpl, "release-header-tmpl", "", "Load custom release notes header from a templated markdown file (overrides --release-header)")
cmd.Flags().StringVar(&root.opts.releaseFooterTmpl, "release-footer-tmpl", "", "Load custom release notes footer from a templated markdown file (overrides --release-footer)")
cmd.Flags().BoolVar(&root.opts.autoSnapshot, "auto-snapshot", false, "Automatically sets --snapshot if the repo is dirty")
cmd.Flags().BoolVar(&root.opts.autoSnapshot, "auto-snapshot", false, "Automatically sets --snapshot if the repository is dirty")
cmd.Flags().BoolVar(&root.opts.snapshot, "snapshot", false, "Generate an unversioned snapshot release, skipping all validations and without publishing any artifacts (implies --skip-publish, --skip-announce and --skip-validate)")
cmd.Flags().BoolVar(&root.opts.skipPublish, "skip-publish", false, "Skips publishing artifacts (implies --skip-announce)")
cmd.Flags().BoolVar(&root.opts.skipAnnounce, "skip-announce", false, "Skips announcing releases (implies --skip-validate)")
Expand Down Expand Up @@ -128,7 +128,7 @@ func setupReleaseContext(ctx *context.Context, options releaseOpts) {
ctx.ReleaseFooterTmpl = options.releaseFooterTmpl
ctx.Snapshot = options.snapshot
if options.autoSnapshot && git.CheckDirty(ctx) != nil {
log.Info("git repo is dirty and --auto-snapshot is set, implying --snapshot")
log.Info("git repository is dirty and --auto-snapshot is set, implying --snapshot")
ctx.Snapshot = true
}
ctx.SkipPublish = ctx.Snapshot || options.skipPublish
Expand Down
2 changes: 2 additions & 0 deletions internal/client/mock.go
Expand Up @@ -37,6 +37,7 @@ type Mock struct {
FailToCloseMilestone bool
Changes string
ReleaseNotes string
ReleaseNotesParams []string
}

func (c *Mock) Changelog(ctx *context.Context, repo Repo, prev, current string) (string, error) {
Expand All @@ -48,6 +49,7 @@ func (c *Mock) Changelog(ctx *context.Context, repo Repo, prev, current string)

func (c *Mock) GenerateReleaseNotes(ctx *context.Context, repo Repo, prev, current string) (string, error) {
if c.ReleaseNotes != "" {
c.ReleaseNotesParams = []string{prev, current}
return c.ReleaseNotes, nil
}
return "", ErrNotImplemented
Expand Down
50 changes: 17 additions & 33 deletions internal/pipe/changelog/changelog.go
Expand Up @@ -220,7 +220,11 @@ func checkSortDirection(mode string) error {
}

func buildChangelog(ctx *context.Context) ([]string, error) {
log, err := getChangelog(ctx, ctx.Git.CurrentTag)
l, err := getChangeloger(ctx)
if err != nil {
return nil, err
}
log, err := l.Log(ctx)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -280,27 +284,6 @@ func extractCommitInfo(line string) string {
return strings.Join(strings.Split(line, " ")[1:], " ")
}

func getChangelog(ctx *context.Context, tag string) (string, error) {
prev := ctx.Git.PreviousTag
if prev == "" {
// get first commit
result, err := git.Clean(git.Run(ctx, "rev-list", "--max-parents=0", "HEAD"))
if err != nil {
return "", err
}
prev = result
}
return doGetChangelog(ctx, prev, tag)
}

func doGetChangelog(ctx *context.Context, prev, tag string) (string, error) {
l, err := getChangeloger(ctx)
if err != nil {
return "", err
}
return l.Log(ctx, prev, tag)
}

func getChangeloger(ctx *context.Context) (changeloger, error) {
switch ctx.Config.Changelog.Use {
case useGit:
Expand Down Expand Up @@ -387,19 +370,17 @@ func loadContent(ctx *context.Context, fileName, tmplName string) (string, error
}

type changeloger interface {
Log(ctx *context.Context, prev, current string) (string, error)
Log(ctx *context.Context) (string, error)
}

type gitChangeloger struct{}

var validSHA1 = regexp.MustCompile(`^[a-fA-F0-9]{40}$`)

func (g gitChangeloger) Log(ctx *context.Context, prev, current string) (string, error) {
func (g gitChangeloger) Log(ctx *context.Context) (string, error) {
args := []string{"log", "--pretty=oneline", "--abbrev-commit", "--no-decorate", "--no-color"}
if validSHA1.MatchString(prev) {
args = append(args, prev, current)
if ctx.Git.PreviousTag == "" {
args = append(args, ctx.Git.FirstCommit, ctx.Git.CurrentTag)
} else {
args = append(args, fmt.Sprintf("tags/%s..tags/%s", prev, current))
args = append(args, fmt.Sprintf("tags/%s..tags/%s", ctx.Git.PreviousTag, ctx.Git.CurrentTag))
}
return git.Run(ctx, args...)
}
Expand All @@ -409,15 +390,18 @@ type scmChangeloger struct {
repo client.Repo
}

func (c *scmChangeloger) Log(ctx *context.Context, prev, current string) (string, error) {
return c.client.Changelog(ctx, c.repo, prev, current)
func (c *scmChangeloger) Log(ctx *context.Context) (string, error) {
if ctx.Git.PreviousTag == "" {
return c.client.Changelog(ctx, c.repo, ctx.Git.FirstCommit, ctx.Git.PreviousTag)
}
return c.client.Changelog(ctx, c.repo, ctx.Git.PreviousTag, ctx.Git.PreviousTag)
}

type githubNativeChangeloger struct {
client client.GitHubClient
repo client.Repo
}

func (c *githubNativeChangeloger) Log(ctx *context.Context, prev, current string) (string, error) {
return c.client.GenerateReleaseNotes(ctx, c.repo, prev, current)
func (c *githubNativeChangeloger) Log(ctx *context.Context) (string, error) {
return c.client.GenerateReleaseNotes(ctx, c.repo, ctx.Git.PreviousTag, ctx.Git.CurrentTag)
}
70 changes: 68 additions & 2 deletions internal/pipe/changelog/changelog_test.go
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/goreleaser/goreleaser/internal/client"
"github.com/goreleaser/goreleaser/internal/git"
"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
Expand Down Expand Up @@ -51,6 +52,7 @@ func TestTemplatedChangelogProvidedViaFlag(t *testing.T) {
ctx.ReleaseNotesFile = "testdata/changes.md"
ctx.ReleaseNotesTmpl = "testdata/changes-templated.md"
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
require.Equal(t, "c0ff33 coffeee v0.0.1\n", ctx.ReleaseNotes)
}
Expand All @@ -59,6 +61,7 @@ func TestTemplatedChangelogProvidedViaFlagResultIsEmpty(t *testing.T) {
ctx := context.New(config.Project{})
ctx.ReleaseNotesTmpl = "testdata/changes-templated-empty.md"
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
require.Equal(t, "\n\n", ctx.ReleaseNotes)
}
Expand Down Expand Up @@ -260,6 +263,7 @@ func TestChangelogOfFirstRelease(t *testing.T) {
testlib.GitTag(t, "v0.0.1")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
for _, msg := range msgs {
Expand Down Expand Up @@ -313,6 +317,7 @@ func TestChangelogOnBranchWithSameNameAsTag(t *testing.T) {
testlib.GitCheckoutBranch(t, "v0.0.1")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
for _, msg := range msgs {
Expand All @@ -339,6 +344,7 @@ func TestChangeLogWithReleaseHeader(t *testing.T) {
testlib.GitCheckoutBranch(t, "v0.0.1")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
ctx.ReleaseHeaderFile = "testdata/release-header.md"
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
Expand All @@ -364,6 +370,7 @@ func TestChangeLogWithTemplatedReleaseHeader(t *testing.T) {
testlib.GitCheckoutBranch(t, "v0.0.1")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
ctx.ReleaseHeaderTmpl = "testdata/release-header-templated.md"
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
Expand All @@ -389,6 +396,7 @@ func TestChangeLogWithReleaseFooter(t *testing.T) {
testlib.GitCheckoutBranch(t, "v0.0.1")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
ctx.ReleaseFooterFile = "testdata/release-footer.md"
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
Expand All @@ -415,6 +423,7 @@ func TestChangeLogWithTemplatedReleaseFooter(t *testing.T) {
testlib.GitCheckoutBranch(t, "v0.0.1")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
ctx.ReleaseFooterTmpl = "testdata/release-footer-templated.md"
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
Expand All @@ -441,6 +450,7 @@ func TestChangeLogWithoutReleaseFooter(t *testing.T) {
testlib.GitCheckoutBranch(t, "v0.0.1")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v0.0.1"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
require.Equal(t, rune(ctx.ReleaseNotes[len(ctx.ReleaseNotes)-1]), '\n')
Expand All @@ -463,7 +473,12 @@ func TestGetChangelogGitHub(t *testing.T) {
Name: "goreleaser",
},
}
log, err := l.Log(ctx, "v0.180.1", "v0.180.2")

ctx.Git = context.GitInfo{
CurrentTag: "v0.180.2",
PreviousTag: "v0.180.1",
}
log, err := l.Log(ctx)
require.NoError(t, err)
require.Equal(t, expected, log)
}
Expand All @@ -490,9 +505,45 @@ func TestGetChangelogGitHubNative(t *testing.T) {
Name: "goreleaser",
},
}
log, err := l.Log(ctx, "v0.180.1", "v0.180.2")
ctx.Git = context.GitInfo{
CurrentTag: "v0.180.2",
PreviousTag: "v0.180.1",
}
log, err := l.Log(ctx)
require.NoError(t, err)
require.Equal(t, expected, log)
require.Equal(t, []string{"v0.180.1", "v0.180.2"}, mock.ReleaseNotesParams)
}

func TestGetChangelogGitHubNativeFirstRelease(t *testing.T) {
ctx := context.New(config.Project{
Changelog: config.Changelog{
Use: useGitHubNative,
},
})

expected := `## What's changed
* Foo bar test
**Full Changelog**: https://github.com/gorelease/goreleaser/commits/v0.1.0
`
mock := client.NewMock()
mock.ReleaseNotes = expected
l := githubNativeChangeloger{
client: mock,
repo: client.Repo{
Owner: "goreleaser",
Name: "goreleaser",
},
}
ctx.Git = context.GitInfo{
CurrentTag: "v0.1.0",
}
log, err := l.Log(ctx)
require.NoError(t, err)
require.Equal(t, expected, log)
require.Equal(t, []string{"", "v0.1.0"}, mock.ReleaseNotesParams)
}

func TestGetChangeloger(t *testing.T) {
Expand Down Expand Up @@ -659,6 +710,7 @@ func TestGroup(t *testing.T) {
},
})
ctx.Git.CurrentTag = "v0.0.2"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
require.Contains(t, ctx.ReleaseNotes, "### Bots")
Expand Down Expand Up @@ -686,6 +738,7 @@ func TestGroupBadRegex(t *testing.T) {
},
})
ctx.Git.CurrentTag = "v0.0.2"
ctx.Git.FirstCommit = firstCommit(t)
require.EqualError(t, Pipe{}.Run(ctx), "failed to group into \"Something\": error parsing regexp: missing closing ]: `[a-z`")
}

Expand Down Expand Up @@ -796,6 +849,8 @@ func TestAbbrev(t *testing.T) {
Changelog: config.Changelog{},
})
ctx.Git.CurrentTag = "v0.0.2"
ctx.Git.FirstCommit = firstCommit(t)

require.NoError(t, Pipe{}.Run(ctx))
ensureCommitHashLen(t, ctx.ReleaseNotes, 7)
})
Expand All @@ -808,6 +863,7 @@ func TestAbbrev(t *testing.T) {
},
})
ctx.Git.CurrentTag = "v0.0.2"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
})

Expand All @@ -819,6 +875,7 @@ func TestAbbrev(t *testing.T) {
},
})
ctx.Git.CurrentTag = "v0.0.2"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
ensureCommitHashLen(t, ctx.ReleaseNotes, 3)
})
Expand All @@ -831,6 +888,7 @@ func TestAbbrev(t *testing.T) {
},
})
ctx.Git.CurrentTag = "v0.0.2"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
ensureCommitHashLen(t, ctx.ReleaseNotes, 7)
})
Expand All @@ -843,6 +901,7 @@ func TestAbbrev(t *testing.T) {
},
})
ctx.Git.CurrentTag = "v0.0.2"
ctx.Git.FirstCommit = firstCommit(t)
require.NoError(t, Pipe{}.Run(ctx))
ensureCommitHashLen(t, ctx.ReleaseNotes, 7)
})
Expand All @@ -859,3 +918,10 @@ func ensureCommitHashLen(tb testing.TB, log string, l int) {
require.Len(tb, commit, l)
}
}

func firstCommit(tb testing.TB) string {
tb.Helper()
s, err := git.Clean(git.Run(context.New(config.Project{}), "rev-list", "--max-parents=0", "HEAD"))
require.NoError(tb, err)
return s
}
12 changes: 11 additions & 1 deletion internal/pipe/git/git.go
Expand Up @@ -58,7 +58,7 @@ var fakeInfo = context.GitInfo{

func getInfo(ctx *context.Context) (context.GitInfo, error) {
if !git.IsRepo(ctx) && ctx.Snapshot {
log.Warn("accepting to run without a git repo because this is a snapshot")
log.Warn("accepting to run without a git repository because this is a snapshot")
return fakeInfo, nil
}
if !git.IsRepo(ctx) {
Expand Down Expand Up @@ -88,6 +88,10 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
if err != nil {
return context.GitInfo{}, fmt.Errorf("couldn't get current commit: %w", err)
}
first, err := getFirstCommit(ctx)
if err != nil {
return context.GitInfo{}, fmt.Errorf("couldn't get first commit: %w", err)
}
date, err := getCommitDate(ctx)
if err != nil {
return context.GitInfo{}, fmt.Errorf("couldn't get commit date: %w", err)
Expand Down Expand Up @@ -117,6 +121,7 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
Commit: full,
FullCommit: full,
ShortCommit: short,
FirstCommit: first,
CommitDate: date,
URL: gitURL,
CurrentTag: "v0.0.0",
Expand Down Expand Up @@ -152,6 +157,7 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
Commit: full,
FullCommit: full,
ShortCommit: short,
FirstCommit: first,
CommitDate: date,
URL: gitURL,
Summary: summary,
Expand Down Expand Up @@ -221,6 +227,10 @@ func getFullCommit(ctx *context.Context) (string, error) {
return git.Clean(git.Run(ctx, "show", "--format=%H", "HEAD", "--quiet"))
}

func getFirstCommit(ctx *context.Context) (string, error) {
return git.Clean(git.Run(ctx, "rev-list", "--max-parents=0", "HEAD"))
}

func getSummary(ctx *context.Context) (string, error) {
return git.Clean(git.Run(ctx, "describe", "--always", "--dirty", "--tags"))
}
Expand Down

0 comments on commit da23357

Please sign in to comment.