Repository: goreleaser/goreleaser
Pull request #2741 (2021-12-06 14:44:36)

Fix JSON schema for ReleaseNotesMode
In the JSON schema, the `keep-existing` value [was missing](https://github.com/goreleaser/goreleaser/blob/167d95e67fe0266fd75bc5dffc949f5db550dc73/www/docs/static/schema.json#L1716) for `ReleaseNotesMode`.
```
					"mode": {
						"enum": [
							"append",
							"prepend",
							"replace"
						],
						"type": "string",
						"default": "keep-existing"
					}
```


I fixed a typo in the struct tags and rebuilt the schema (`task schema:generate`). This adds `keep-existing` in the enum.

Note: [`schema-pro.json`](https://github.com/goreleaser/goreleaser/blob/167d95e67fe0266fd75bc5dffc949f5db550dc73/www/docs/static/schema-pro.json#L1884) is also affected, but I don't know how it is generated.


Patch:
diff --git a/internal/pipe/git/git.go b/internal/pipe/git/git.go
index a27616f9..66a1b86e 100644
--- a/internal/pipe/git/git.go
+++ b/internal/pipe/git/git.go
@@ -121,6 +121,11 @@ func getGitInfo() (context.GitInfo, error) {
 		return context.GitInfo{}, fmt.Errorf("couldn't get tag subject: %w", err)
 	}
 
+	contents, err := getTagContents(tag)
+	if err != nil {
+		return context.GitInfo{}, fmt.Errorf("couldn't get tag contents: %w", err)
+	}
+
 	previous, err := getPreviousTag(tag)
 	if err != nil {
 		// shouldn't error, will only affect templates
@@ -137,7 +142,8 @@ func getGitInfo() (context.GitInfo, error) {
 		CommitDate:  date,
 		URL:         gitURL,
 		Summary:     summary,
-		Subject:     subject,
+		TagSubject:  subject,
+		TagContents: contents,
 	}, nil
 }
 
@@ -209,6 +215,11 @@ func getTagSubject(tag string) (string, error) {
 	return git.Clean(git.Run("tag", "-l", "--format='%(contents:subject)'", tag))
 }
 
+func getTagContents(tag string) (string, error) {
+	out, err := git.Run("tag", "-l", "--format='%(contents)'", tag)
+	return strings.ReplaceAll(strings.TrimSuffix(out, "\n"), "'", ""), err
+}
+
 func getTag() (string, error) {
 	var tag string
 	var err error
diff --git a/internal/tmpl/tmpl.go b/internal/tmpl/tmpl.go
index 534c54bb..f5fb44be 100644
--- a/internal/tmpl/tmpl.go
+++ b/internal/tmpl/tmpl.go
@@ -39,7 +39,8 @@ const (
 	commitTimestamp = "CommitTimestamp"
 	gitURL          = "GitURL"
 	summary         = "Summary"
-	subject         = "Subject"
+	tagSubject      = "TagSubject"
+	tagContents     = "TagContents"
 	releaseURL      = "ReleaseURL"
 	major           = "Major"
 	minor           = "Minor"
@@ -89,7 +90,8 @@ func New(ctx *context.Context) *Template {
 			commitTimestamp: ctx.Git.CommitDate.UTC().Unix(),
 			gitURL:          ctx.Git.URL,
 			summary:         ctx.Git.Summary,
-			subject:         ctx.Git.Subject,
+			tagSubject:      ctx.Git.TagSubject,
+			tagContents:     ctx.Git.TagContents,
 			releaseURL:      ctx.ReleaseURL,
 			env:             ctx.Env,
 			date:            ctx.Date.UTC().Format(time.RFC3339),
diff --git a/pkg/config/config.go b/pkg/config/config.go
index d1daefb1..b0d4ea48 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -477,7 +477,7 @@ type Release struct {
 	Header                 string      `yaml:"header,omitempty"`
 	Footer                 string      `yaml:"footer,omitempty"`
 
-	ReleaseNotesMode ReleaseNotesMode `yaml:"mode,omitempty" jsonschema:"title=enum=keep-existing,enum=append,enum=prepend,enum=replace,default=keep-existing"`
+	ReleaseNotesMode ReleaseNotesMode `yaml:"mode,omitempty" jsonschema:"enum=keep-existing,enum=append,enum=prepend,enum=replace,default=keep-existing"`
 }
 
 // Milestone config used for VCS milestone.
diff --git a/pkg/context/context.go b/pkg/context/context.go
index ad2ab443..3b87142e 100644
--- a/pkg/context/context.go
+++ b/pkg/context/context.go
@@ -27,7 +27,8 @@ type GitInfo struct {
 	CommitDate  time.Time
 	URL         string
 	Summary     string
-	Subject     string
+	TagSubject  string
+	TagContents string
 }
 
 // Env is the environment variables.
diff --git a/www/docs/customization/templates.md b/www/docs/customization/templates.md
index 528da185..1c5eac65 100644
--- a/www/docs/customization/templates.md
+++ b/www/docs/customization/templates.md
@@ -43,13 +43,16 @@ On fields that support templating, these fields are always available:
 | `.ReleaseURL`          | the current release download url[^4]                                                                   |
 | `.Summary`             | the git summary, e.g. `v1.0.0-10-g34f56g3`[^5]                                                         |
 | `.PrefixedSummary`     | the git summary prefixed with the monorepo config tag prefix (if any)                                  |
-| `.Subject`             | the annotated tag message, or the message of the commit it points out to                               |
+| `.TagSubject`          | the annotated tag message subject, or the message subject of the commit it points out[^6]              |
+| `.TagContents`         | the annotated tag message, or the message of the commit it points out[^7]                              |
 
 [^1]: The `v` prefix is stripped and it might be changed in `snapshot` and `nightly` builds.
 [^2]: Assuming `Tag` is a valid a SemVer, otherwise empty/zeroed.
 [^3]: Will panic if not a semantic version.
 [^4]: Composed from the current SCM's download URL and current tag. For instance, on GitHub, it'll be `https://github.com/{owner}/{repo}/releases/tag/{tag}`.
 [^5]: It is generated by `git describe --dirty --always --tags`, the format will be `{Tag}-$N-{CommitSHA}`
+[^6]: As reported by `git tag -l --format='%(contents:subject)'`
+[^7]: As reported by `git tag -l --format='%(contents)'`
 
 ## Single-artifact extra fields
 
@@ -58,15 +61,15 @@ may have some extra fields:
 
 | Key             | Description                           |
 |-----------------|---------------------------------------|
-| `.Os`           | `GOOS`[^6]                            |
-| `.Arch`         | `GOARCH`[^6]                          |
-| `.Arm`          | `GOARM`[^6]                           |
-| `.Mips`         | `GOMIPS`[^6]                          |
+| `.Os`           | `GOOS`[^8]                            |
+| `.Arch`         | `GOARCH`[^8]                          |
+| `.Arm`          | `GOARM`[^8]                           |
+| `.Mips`         | `GOMIPS`[^8]                          |
 | `.Binary`       | binary name                           |
 | `.ArtifactName` | archive name                          |
 | `.ArtifactPath` | absolute path to artifact             |
 
-[^6]: Might have been replaced by `archives.replacements`.
+[^8]: Might have been replaced by `archives.replacements`.
 
 ## nFPM extra fields
 
diff --git a/www/docs/static/schema.json b/www/docs/static/schema.json
index d51e3d38..118e30b6 100644
--- a/www/docs/static/schema.json
+++ b/www/docs/static/schema.json
@@ -1715,6 +1715,7 @@
 					},
 					"mode": {
 						"enum": [
+							"keep-existing",
 							"append",
 							"prepend",
 							"replace"


Test patch:
diff --git a/internal/pipe/git/git_test.go b/internal/pipe/git/git_test.go
index ecb87c0f..5b068469 100644
--- a/internal/pipe/git/git_test.go
+++ b/internal/pipe/git/git_test.go
@@ -6,11 +6,10 @@ import (
 	"path/filepath"
 	"testing"
 
-	"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/require"
 )
 
 func TestDescription(t *testing.T) {
@@ -37,21 +36,22 @@ func TestSingleCommit(t *testing.T) {
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
 	require.Equal(t, "v0.0.1", ctx.Git.Summary)
-	require.Equal(t, "commit1", ctx.Git.Subject)
+	require.Equal(t, "commit1", ctx.Git.TagSubject)
 }
 
 func TestAnnotatedTags(t *testing.T) {
-	testlib.Mktmp(t)
+	t.Log(testlib.Mktmp(t))
 	testlib.GitInit(t)
 	testlib.GitRemoteAdd(t, "git@github.com:foo/bar.git")
 	testlib.GitCommit(t, "commit1")
-	testlib.GitAnnotatedTag(t, "v0.0.1", "first version")
+	testlib.GitAnnotatedTag(t, "v0.0.1", "first version\n\nlalalla\nlalal\nlah")
 	ctx := &context.Context{
 		Config: config.Project{},
 	}
 	require.NoError(t, Pipe{}.Run(ctx))
 	require.Equal(t, "v0.0.1", ctx.Git.CurrentTag)
-	require.Equal(t, "first version", ctx.Git.Subject)
+	require.Equal(t, "first version", ctx.Git.TagSubject)
+	require.Equal(t, "first version\n\nlalalla\nlalal\nlah\n", ctx.Git.TagContents)
 	require.Equal(t, "v0.0.1", ctx.Git.Summary)
 }
 
diff --git a/internal/testlib/git.go b/internal/testlib/git.go
index 7c1d9960..775934f8 100644
--- a/internal/testlib/git.go
+++ b/internal/testlib/git.go
@@ -51,9 +51,9 @@ func GitTag(tb testing.TB, tag string) {
 }
 
 // GitAnnotatedTag creates an annotated tag.
-func GitAnnotatedTag(tb testing.TB, tag, subject string) {
+func GitAnnotatedTag(tb testing.TB, tag, message string) {
 	tb.Helper()
-	out, err := fakeGit("tag", "-a", tag, "-m", subject)
+	out, err := fakeGit("tag", "-a", tag, "-m", message)
 	require.NoError(tb, err)
 	require.Empty(tb, out)
 }
diff --git a/internal/tmpl/tmpl_test.go b/internal/tmpl/tmpl_test.go
index 265c7566..c596d0de 100644
--- a/internal/tmpl/tmpl_test.go
+++ b/internal/tmpl/tmpl_test.go
@@ -33,7 +33,8 @@ func TestWithArtifact(t *testing.T) {
 	ctx.Git.Commit = "commit"
 	ctx.Git.FullCommit = "fullcommit"
 	ctx.Git.ShortCommit = "shortcommit"
-	ctx.Git.Subject = "awesome release"
+	ctx.Git.TagSubject = "awesome release"
+	ctx.Git.TagContents = "awesome release\n\nanother line"
 	ctx.ReleaseNotes = "test release notes"
 	for expect, tmpl := range map[string]string{
 		"bar":                              "{{.Env.FOO}}",
@@ -59,7 +60,8 @@ func TestWithArtifact(t *testing.T) {
 		"1.2.4":                            "{{.Version | incpatch }}",
 		"test release notes":               "{{ .ReleaseNotes }}",
 		"v1.2.2":                           "{{ .PreviousTag }}",
-		"awesome release":                  "{{ .Subject }}",
+		"awesome release":                  "{{ .TagSubject }}",
+		"awesome release\n\nanother line":  "{{ .TagContents }}",
 	} {
 		tmpl := tmpl
 		expect := expect