diff --git a/internal/pipe/changelog/changelog.go b/internal/pipe/changelog/changelog.go index e78f63943f0..ede93695782 100644 --- a/internal/pipe/changelog/changelog.go +++ b/internal/pipe/changelog/changelog.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io/ioutil" + "os" "path/filepath" "regexp" "sort" @@ -189,6 +190,10 @@ func gitLog(refs ...string) (string, error) { } 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")) diff --git a/internal/pipe/changelog/changelog_test.go b/internal/pipe/changelog/changelog_test.go index bd43133a78b..fcf7201aed7 100644 --- a/internal/pipe/changelog/changelog_test.go +++ b/internal/pipe/changelog/changelog_test.go @@ -109,6 +109,30 @@ func TestChangelog(t *testing.T) { require.NotEmpty(t, string(bts)) } +func TestChangelogPreviousTagEnv(t *testing.T) { + folder, back := testlib.Mktmp(t) + defer back() + 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") + var ctx = context.New(config.Project{ + Dist: folder, + Changelog: config.Changelog{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) { folder, back := testlib.Mktmp(t) defer back() diff --git a/internal/pipe/git/git.go b/internal/pipe/git/git.go index 9e6f176356c..c354323d240 100644 --- a/internal/pipe/git/git.go +++ b/internal/pipe/git/git.go @@ -1,14 +1,16 @@ package git import ( + "os" "os/exec" "strings" "github.com/apex/log" + "github.com/pkg/errors" + "github.com/goreleaser/goreleaser/internal/git" "github.com/goreleaser/goreleaser/internal/pipe" "github.com/goreleaser/goreleaser/pkg/context" - "github.com/pkg/errors" ) // Pipe that sets up git state @@ -122,6 +124,10 @@ func getFullCommit() (string, error) { } func getTag() (string, error) { + if tag := os.Getenv("GORELEASER_CURRENT_TAG"); tag != "" { + return tag, nil + } + return git.Clean(git.Run("describe", "--tags", "--abbrev=0")) } diff --git a/internal/pipe/git/git_test.go b/internal/pipe/git/git_test.go index dcdef6d2aeb..1d4b19211b5 100644 --- a/internal/pipe/git/git_test.go +++ b/internal/pipe/git/git_test.go @@ -6,10 +6,12 @@ import ( "path/filepath" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/goreleaser/goreleaser/internal/testlib" "github.com/goreleaser/goreleaser/pkg/config" "github.com/goreleaser/goreleaser/pkg/context" - "github.com/stretchr/testify/assert" ) func TestDescription(t *testing.T) { @@ -189,3 +191,41 @@ func TestGitNotInPath(t *testing.T) { assert.NoError(t, os.Setenv("PATH", "")) assert.EqualError(t, Pipe{}.Run(context.New(config.Project{})), ErrNoGit.Error()) } + +func TestTagFromCI(t *testing.T) { + _, back := testlib.Mktmp(t) + defer back() + testlib.GitInit(t) + testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git") + testlib.GitCommit(t, "commit1") + testlib.GitTag(t, "v0.0.1") + testlib.GitTag(t, "v0.0.2") + + for _, tc := range []struct { + envs map[string]string + expected string + }{ + // It is not possible to concisely figure out the tag if a commit has more than one tags. Git always + // returns the tags in lexicographical order (ASC), which implies that we expect v0.0.1 here. + // More details: https://github.com/goreleaser/goreleaser/issues/1163 + {expected: "v0.0.1"}, + { + envs: map[string]string{"GORELEASER_CURRENT_TAG": "v0.0.2"}, + expected: "v0.0.2", + }, + } { + for name, value := range tc.envs { + require.NoError(t, os.Setenv(name, value)) + } + + var ctx = &context.Context{ + Config: config.Project{}, + } + assert.NoError(t, Pipe{}.Run(ctx)) + assert.Equal(t, tc.expected, ctx.Git.CurrentTag) + + for name := range tc.envs { + require.NoError(t, os.Setenv(name, "")) + } + } +} diff --git a/www/content/build.md b/www/content/build.md index c0cdacf6cdc..910896eb4cf 100644 --- a/www/content/build.md +++ b/www/content/build.md @@ -149,3 +149,9 @@ GOVERSION=$(go version) goreleaser ``` [hook]: /hooks + +## Define Build Tag + +GoReleaser uses `git describe` to get the build tag. You can set +a different build tag using the environment variable `GORELEASER_CURRENT_TAG`. +This is useful in scenarios where two tags point to the same commit. diff --git a/www/content/environment.md b/www/content/environment.md index 7e5261f3806..b79003a18b8 100644 --- a/www/content/environment.md +++ b/www/content/environment.md @@ -117,3 +117,7 @@ func main() { ``` You can override this by changing the `ldflags` option in the `build` section. + +## Overriding Git Tags + +You can force the [build tag](/build#define-build-tag) and [previous changelog tag](/release#define-previous-tag) using environment variables. This is useful in cases where one git commit is referenced by multiple git tags. diff --git a/www/content/release.md b/www/content/release.md index 190649d2894..fa585bdea45 100644 --- a/www/content/release.md +++ b/www/content/release.md @@ -137,6 +137,12 @@ changelog: - (?i)foo ``` +### Define Previous Tag + +GoReleaser uses `git describe` to get the previous tag used for generating the Changelog. +You can set a different build tag using the environment variable `GORELEASER_PREVIOUS_TAG`. +This is useful in scenarios where two tags point to the same commit. + ## Custom release notes You can specify a file containing your custom release notes, and