1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-11-06 09:09:29 +02:00

feat: allow to use .PreviousTag on templates (#2683)

* feat: expose .PreviousTag

* fix: previous tag will never be a commit

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>

* fix: tests

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>

* docs: tag

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>
This commit is contained in:
Carlos Alexandro Becker
2021-11-24 09:12:24 -03:00
committed by GitHub
parent df0c31dea1
commit cd261a527a
9 changed files with 90 additions and 42 deletions

View File

@@ -48,6 +48,7 @@ changelog:
- '^test:' - '^test:'
- '^chore' - '^chore'
- Merge pull request - Merge pull request
- Merge remote-tracking branch
- Merge branch - Merge branch
- go mod tidy - go mod tidy
groups: groups:
@@ -60,7 +61,6 @@ changelog:
- title: Other work - title: Other work
order: 999 order: 999
dockers: dockers:
- image_templates: - image_templates:
- 'goreleaser/goreleaser:{{ .Tag }}-amd64' - 'goreleaser/goreleaser:{{ .Tag }}-amd64'
@@ -226,6 +226,8 @@ release:
extra_files: extra_files:
- glob: ./cosign.pub - glob: ./cosign.pub
footer: | footer: |
**Full Changelog**: https://github.com/goreleaser/goreleaser/{{ .PreviousTag }}...{{ .Tag }}
## What to do next? ## What to do next?
- Check out the [GoReleaser Pro](https://goreleaser.com/pro) distribution; - Check out the [GoReleaser Pro](https://goreleaser.com/pro) distribution;

View File

@@ -214,9 +214,14 @@ func extractCommitInfo(line string) string {
} }
func getChangelog(ctx *context.Context, tag string) (string, error) { func getChangelog(ctx *context.Context, tag string) (string, error) {
prev, err := previous(tag) prev := ctx.Git.PreviousTag
if err != nil { if prev == "" {
return "", err // get first commit
result, err := git.Clean(git.Run("rev-list", "--max-parents=0", "HEAD"))
if err != nil {
return "", err
}
prev = result
} }
return doGetChangelog(ctx, prev, tag) return doGetChangelog(ctx, prev, tag)
} }
@@ -282,18 +287,6 @@ func newSCMChangeloger(ctx *context.Context) (changeloger, error) {
}, nil }, nil
} }
func previous(tag string) (result string, err error) {
if tag := os.Getenv("GORELEASER_PREVIOUS_TAG"); tag != "" {
return tag, nil
}
result, err = git.Clean(git.Run("describe", "--tags", "--abbrev=0", fmt.Sprintf("tags/%s^", tag)))
if err != nil {
result, err = git.Clean(git.Run("rev-list", "--max-parents=0", "HEAD"))
}
return
}
func loadContent(ctx *context.Context, fileName, tmplName string) (string, error) { func loadContent(ctx *context.Context, fileName, tmplName string) (string, error) {
if tmplName != "" { if tmplName != "" {
log.Debugf("loading template %s", tmplName) log.Debugf("loading template %s", tmplName)

View File

@@ -79,6 +79,7 @@ func TestChangelog(t *testing.T) {
}, },
}, },
}) })
ctx.Git.PreviousTag = "v0.0.1"
ctx.Git.CurrentTag = "v0.0.2" ctx.Git.CurrentTag = "v0.0.2"
require.NoError(t, Pipe{}.Run(ctx)) require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog") require.Contains(t, ctx.ReleaseNotes, "## Changelog")
@@ -102,32 +103,6 @@ func TestChangelog(t *testing.T) {
require.NotEmpty(t, string(bts)) require.NotEmpty(t, string(bts))
} }
func TestChangelogPreviousTagEnv(t *testing.T) {
folder := testlib.Mktmp(t)
testlib.GitInit(t)
testlib.GitCommit(t, "first")
testlib.GitTag(t, "v0.0.1")
testlib.GitCommit(t, "second")
testlib.GitTag(t, "v0.0.2")
testlib.GitCommit(t, "third")
testlib.GitTag(t, "v0.0.3")
ctx := context.New(config.Project{
Dist: folder,
Changelog: config.Changelog{
Use: "git",
Filters: config.Filters{},
},
})
ctx.Git.CurrentTag = "v0.0.3"
require.NoError(t, os.Setenv("GORELEASER_PREVIOUS_TAG", "v0.0.1"))
require.NoError(t, Pipe{}.Run(ctx))
require.NoError(t, os.Setenv("GORELEASER_PREVIOUS_TAG", ""))
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
require.NotContains(t, ctx.ReleaseNotes, "first")
require.Contains(t, ctx.ReleaseNotes, "second")
require.Contains(t, ctx.ReleaseNotes, "third")
}
func TestChangelogForGitlab(t *testing.T) { func TestChangelogForGitlab(t *testing.T) {
folder := testlib.Mktmp(t) folder := testlib.Mktmp(t)
testlib.GitInit(t) testlib.GitInit(t)
@@ -156,6 +131,7 @@ func TestChangelogForGitlab(t *testing.T) {
}, },
}) })
ctx.TokenType = context.TokenTypeGitLab ctx.TokenType = context.TokenTypeGitLab
ctx.Git.PreviousTag = "v0.0.1"
ctx.Git.CurrentTag = "v0.0.2" ctx.Git.CurrentTag = "v0.0.2"
require.NoError(t, Pipe{}.Run(ctx)) require.NoError(t, Pipe{}.Run(ctx))
require.Contains(t, ctx.ReleaseNotes, "## Changelog") require.Contains(t, ctx.ReleaseNotes, "## Changelog")
@@ -184,6 +160,7 @@ func TestChangelogSort(t *testing.T) {
ctx := context.New(config.Project{ ctx := context.New(config.Project{
Changelog: config.Changelog{}, Changelog: config.Changelog{},
}) })
ctx.Git.PreviousTag = "v0.9.9"
ctx.Git.CurrentTag = "v1.0.0" ctx.Git.CurrentTag = "v1.0.0"
for _, cfg := range []struct { for _, cfg := range []struct {
@@ -276,6 +253,7 @@ func TestChangelogFilterInvalidRegex(t *testing.T) {
}, },
}, },
}) })
ctx.Git.PreviousTag = "v0.0.3"
ctx.Git.CurrentTag = "v0.0.4" ctx.Git.CurrentTag = "v0.0.4"
require.EqualError(t, Pipe{}.Run(ctx), "error parsing regexp: invalid or unsupported Perl syntax: `(?ia`") require.EqualError(t, Pipe{}.Run(ctx), "error parsing regexp: invalid or unsupported Perl syntax: `(?ia`")
} }

View File

@@ -109,9 +109,17 @@ func getGitInfo() (context.GitInfo, error) {
CurrentTag: "v0.0.0", CurrentTag: "v0.0.0",
}, ErrNoTag }, ErrNoTag
} }
previous, err := getPreviousTag(tag)
if err != nil {
// shouldn't error, will only affect templates
log.Warnf("couldn't find any tags before %q", tag)
}
return context.GitInfo{ return context.GitInfo{
Branch: branch, Branch: branch,
CurrentTag: tag, CurrentTag: tag,
PreviousTag: previous,
Commit: full, Commit: full,
FullCommit: full, FullCommit: full,
ShortCommit: short, ShortCommit: short,
@@ -203,6 +211,14 @@ func getTag() (string, error) {
return tag, err return tag, err
} }
func getPreviousTag(current string) (string, error) {
if tag := os.Getenv("GORELEASER_PREVIOUS_TAG"); tag != "" {
return tag, nil
}
return git.Clean(git.Run("describe", "--tags", "--abbrev=0", fmt.Sprintf("tags/%s^", current)))
}
func getURL() (string, error) { func getURL() (string, error) {
return git.Clean(git.Run("ls-remote", "--get-url")) return git.Clean(git.Run("ls-remote", "--get-url"))
} }

View File

@@ -201,6 +201,7 @@ func TestSnapshotNoTags(t *testing.T) {
ctx.Snapshot = true ctx.Snapshot = true
testlib.AssertSkipped(t, Pipe{}.Run(ctx)) testlib.AssertSkipped(t, Pipe{}.Run(ctx))
require.Equal(t, fakeInfo.CurrentTag, ctx.Git.CurrentTag) require.Equal(t, fakeInfo.CurrentTag, ctx.Git.CurrentTag)
require.Empty(t, ctx.Git.PreviousTag)
} }
func TestSnapshotNoCommits(t *testing.T) { func TestSnapshotNoCommits(t *testing.T) {
@@ -277,6 +278,57 @@ func TestTagFromCI(t *testing.T) {
} }
} }
func TestNoPreviousTag(t *testing.T) {
testlib.Mktmp(t)
testlib.GitInit(t)
testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
testlib.GitCommit(t, "commit1")
testlib.GitTag(t, "v0.0.1")
ctx := &context.Context{
Config: config.Project{},
}
require.NoError(t, Pipe{}.Run(ctx))
require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
require.Empty(t, ctx.Git.PreviousTag, "should be empty")
}
func TestPreviousTagFromCI(t *testing.T) {
testlib.Mktmp(t)
testlib.GitInit(t)
testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
testlib.GitCommit(t, "commit1")
testlib.GitTag(t, "v0.0.1")
testlib.GitCommit(t, "commit2")
testlib.GitTag(t, "v0.0.2")
for _, tc := range []struct {
envs map[string]string
expected string
}{
{expected: "v0.0.1"},
{
envs: map[string]string{"GORELEASER_PREVIOUS_TAG": "v0.0.2"},
expected: "v0.0.2",
},
} {
t.Run(tc.expected, func(t *testing.T) {
for name, value := range tc.envs {
require.NoError(t, os.Setenv(name, value))
}
ctx := &context.Context{
Config: config.Project{},
}
require.NoError(t, Pipe{}.Run(ctx))
require.Equal(t, tc.expected, ctx.Git.PreviousTag)
for name := range tc.envs {
require.NoError(t, os.Setenv(name, ""))
}
})
}
}
func TestCommitDate(t *testing.T) { func TestCommitDate(t *testing.T) {
// round to seconds since this is expressed in a Unix timestamp // round to seconds since this is expressed in a Unix timestamp
commitDate := time.Now().AddDate(-1, 0, 0).Round(1 * time.Second) commitDate := time.Now().AddDate(-1, 0, 0).Round(1 * time.Second)
@@ -291,5 +343,6 @@ func TestCommitDate(t *testing.T) {
} }
require.NoError(t, Pipe{}.Run(ctx)) require.NoError(t, Pipe{}.Run(ctx))
require.Equal(t, "v0.0.1", ctx.Git.CurrentTag) require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
require.Empty(t, ctx.Git.PreviousTag)
require.True(t, commitDate.Equal(ctx.Git.CommitDate), "commit date does not match expected") require.True(t, commitDate.Equal(ctx.Git.CommitDate), "commit date does not match expected")
} }

View File

@@ -31,6 +31,7 @@ const (
version = "Version" version = "Version"
rawVersion = "RawVersion" rawVersion = "RawVersion"
tag = "Tag" tag = "Tag"
previousTag = "PreviousTag"
branch = "Branch" branch = "Branch"
commit = "Commit" commit = "Commit"
shortCommit = "ShortCommit" shortCommit = "ShortCommit"
@@ -78,6 +79,7 @@ func New(ctx *context.Context) *Template {
version: ctx.Version, version: ctx.Version,
rawVersion: rawVersionV, rawVersion: rawVersionV,
tag: ctx.Git.CurrentTag, tag: ctx.Git.CurrentTag,
previousTag: ctx.Git.PreviousTag,
branch: ctx.Git.Branch, branch: ctx.Git.Branch,
commit: ctx.Git.Commit, commit: ctx.Git.Commit,
shortCommit: ctx.Git.ShortCommit, shortCommit: ctx.Git.ShortCommit,

View File

@@ -22,6 +22,7 @@ func TestWithArtifact(t *testing.T) {
"FOO": "bar", "FOO": "bar",
} }
ctx.Version = "1.2.3" ctx.Version = "1.2.3"
ctx.Git.PreviousTag = "v1.2.2"
ctx.Git.CurrentTag = "v1.2.3" ctx.Git.CurrentTag = "v1.2.3"
ctx.Semver = context.Semver{ ctx.Semver = context.Semver{
Major: 1, Major: 1,
@@ -56,6 +57,7 @@ func TestWithArtifact(t *testing.T) {
"v1.2.4": "{{.Tag | incpatch }}", "v1.2.4": "{{.Tag | incpatch }}",
"1.2.4": "{{.Version | incpatch }}", "1.2.4": "{{.Version | incpatch }}",
"test release notes": "{{ .ReleaseNotes }}", "test release notes": "{{ .ReleaseNotes }}",
"v1.2.2": "{{ .PreviousTag }}",
} { } {
tmpl := tmpl tmpl := tmpl
expect := expect expect := expect

View File

@@ -20,6 +20,7 @@ import (
type GitInfo struct { type GitInfo struct {
Branch string Branch string
CurrentTag string CurrentTag string
PreviousTag string
Commit string Commit string
ShortCommit string ShortCommit string
FullCommit string FullCommit string

View File

@@ -17,6 +17,7 @@ On fields that support templating, these fields are always available:
| `.Branch` | the current git branch | | `.Branch` | the current git branch |
| `.PrefixedTag` | the current git tag prefixed with the monorepo config tag prefix (if any) | | `.PrefixedTag` | the current git tag prefixed with the monorepo config tag prefix (if any) |
| `.Tag` | the current git tag | | `.Tag` | the current git tag |
| `.PreviousTag` | the previous git tag, or empty if no previous tags |
| `.ShortCommit` | the git commit short hash | | `.ShortCommit` | the git commit short hash |
| `.FullCommit` | the git commit full hash | | `.FullCommit` | the git commit full hash |
| `.Commit` | the git commit hash (deprecated) | | `.Commit` | the git commit hash (deprecated) |