1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-09-16 09:26:52 +02:00

feat: release header/footer (#2267)

* feat: release header/footer

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

* feat: release header/footer

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

* refactor: using the golden library all over

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

* fix: lint

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

* fix: brew arm tests

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

* fix: use footer

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>
This commit is contained in:
Carlos Alexandro Becker
2021-05-30 21:53:40 -03:00
committed by GitHub
parent 68f23cfc16
commit 4d0c0d2072
34 changed files with 238 additions and 255 deletions

View File

@@ -158,6 +158,11 @@ snapcrafts:
publish: true
release:
discussion_category_name: Announcements
footer: |
---
__Check out [GoReleaser Pro](https://goreleaser.com/pro) as well!__
announce:
twitter:
enabled: true

View File

@@ -2,20 +2,17 @@ package deprecate
import (
"bytes"
"flag"
"os"
"testing"
"github.com/apex/log"
"github.com/apex/log/handlers/cli"
"github.com/fatih/color"
"github.com/goreleaser/goreleaser/internal/golden"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/require"
)
var update = flag.Bool("update", false, "update .golden files")
func TestNotice(t *testing.T) {
var w bytes.Buffer
@@ -28,15 +25,7 @@ func TestNotice(t *testing.T) {
log.Info("last")
require.True(t, ctx.Deprecated)
const golden = "testdata/output.txt.golden"
if *update {
require.NoError(t, os.WriteFile(golden, w.Bytes(), 0o655))
}
gbts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(gbts), w.String())
golden.RequireEqualTxt(t, w.Bytes())
}
func TestNoticeCustom(t *testing.T) {
@@ -51,13 +40,5 @@ func TestNoticeCustom(t *testing.T) {
log.Info("last")
require.True(t, ctx.Deprecated)
const golden = "testdata/output_custom.txt.golden"
if *update {
require.NoError(t, os.WriteFile(golden, w.Bytes(), 0o655))
}
gbts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(gbts), w.String())
golden.RequireEqualTxt(t, w.Bytes())
}

53
internal/golden/golden.go Normal file
View File

@@ -0,0 +1,53 @@
// Package golden asserts golden files contents.
package golden
import (
"flag"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
)
var update = flag.Bool("update", false, "update .golden files")
func RequireEqual(tb testing.TB, out []byte) {
tb.Helper()
doRequireEqual(tb, out, "")
}
func RequireEqualTxt(tb testing.TB, out []byte) {
tb.Helper()
doRequireEqual(tb, out, ".txt")
}
func RequireEqualJSON(tb testing.TB, out []byte) {
tb.Helper()
doRequireEqual(tb, out, ".json")
}
func RequireEqualRb(tb testing.TB, out []byte) {
tb.Helper()
doRequireEqual(tb, out, ".rb")
}
func RequireEqualYaml(tb testing.TB, out []byte) {
tb.Helper()
doRequireEqual(tb, out, ".yml")
}
func doRequireEqual(tb testing.TB, out []byte, ext string) {
tb.Helper()
golden := "testdata/" + tb.Name() + ext + ".golden"
if *update {
require.NoError(tb, os.MkdirAll(filepath.Dir(golden), 0o755))
require.NoError(tb, os.WriteFile(golden, out, 0o655))
}
gbts, err := os.ReadFile(golden)
require.NoError(tb, err)
require.Equal(tb, string(gbts), string(out))
}

View File

@@ -1,7 +1,6 @@
package brew
import (
"flag"
"fmt"
"io/ioutil"
"os"
@@ -10,14 +9,13 @@ import (
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/client"
"github.com/goreleaser/goreleaser/internal/golden"
"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/require"
)
var update = flag.Bool("update", false, "update .golden files")
func TestDescription(t *testing.T) {
require.NotEmpty(t, Pipe{}.String())
}
@@ -95,14 +93,7 @@ func TestFullFormulae(t *testing.T) {
}), data)
require.NoError(t, err)
golden := "testdata/test.rb.golden"
if *update {
err := os.WriteFile(golden, []byte(formulae), 0o655)
require.NoError(t, err)
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), formulae)
golden.RequireEqualRb(t, []byte(formulae))
}
func TestFullFormulaeLinuxOnly(t *testing.T) {
@@ -115,14 +106,7 @@ func TestFullFormulaeLinuxOnly(t *testing.T) {
}), data)
require.NoError(t, err)
golden := "testdata/test_linux_only.rb.golden"
if *update {
err := os.WriteFile(golden, []byte(formulae), 0o655)
require.NoError(t, err)
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), formulae)
golden.RequireEqualRb(t, []byte(formulae))
}
func TestFormulaeSimple(t *testing.T) {
@@ -246,17 +230,11 @@ func TestRunPipe(t *testing.T) {
require.NoError(t, doRun(ctx, ctx.Config.Brews[0], client))
require.True(t, client.CreatedFile)
golden := fmt.Sprintf("testdata/%s.rb.golden", name)
if *update {
require.NoError(t, os.WriteFile(golden, []byte(client.Content), 0o655))
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), client.Content)
golden.RequireEqualRb(t, []byte(client.Content))
distBts, err := os.ReadFile(distFile)
require.NoError(t, err)
require.Equal(t, string(bts), string(distBts))
require.Equal(t, client.Content, string(distBts))
})
}
}
@@ -310,17 +288,10 @@ func TestRunPipeNameTemplate(t *testing.T) {
require.NoError(t, doRun(ctx, ctx.Config.Brews[0], client))
require.True(t, client.CreatedFile)
golden := "testdata/foo_is_bar.rb.golden"
if *update {
require.NoError(t, os.WriteFile(golden, []byte(client.Content), 0o655))
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), client.Content)
golden.RequireEqualRb(t, []byte(client.Content))
distBts, err := os.ReadFile(distFile)
require.NoError(t, err)
require.Equal(t, string(bts), string(distBts))
require.Equal(t, client.Content, string(distBts))
}
func TestRunPipeMultipleBrewsWithSkip(t *testing.T) {
@@ -413,118 +384,114 @@ func TestRunPipeForMultipleArmVersions(t *testing.T) {
ctx.Config.Brews[0].Goarm = "7"
},
} {
folder := t.TempDir()
ctx := &context.Context{
TokenType: context.TokenTypeGitHub,
Git: context.GitInfo{
CurrentTag: "v1.0.1",
},
Version: "1.0.1",
Artifacts: artifact.New(),
Env: map[string]string{
"FOO": "foo_is_bar",
},
Config: config.Project{
Dist: folder,
ProjectName: name,
Brews: []config.Homebrew{
{
Name: name,
Description: "A run pipe test formula and FOO={{ .Env.FOO }}",
Caveats: "don't do this {{ .ProjectName }}",
Test: "system \"true\"\nsystem \"#{bin}/foo -h\"",
Plist: `<xml>whatever</xml>`,
Dependencies: []config.HomebrewDependency{{Name: "zsh"}, {Name: "bash", Type: "recommended"}},
Conflicts: []string{"gtk+", "qt"},
Install: `bin.install "{{ .ProjectName }}"`,
Tap: config.RepoRef{
t.Run(name, func(t *testing.T) {
folder := t.TempDir()
ctx := &context.Context{
TokenType: context.TokenTypeGitHub,
Git: context.GitInfo{
CurrentTag: "v1.0.1",
},
Version: "1.0.1",
Artifacts: artifact.New(),
Env: map[string]string{
"FOO": "foo_is_bar",
},
Config: config.Project{
Dist: folder,
ProjectName: name,
Brews: []config.Homebrew{
{
Name: name,
Description: "A run pipe test formula and FOO={{ .Env.FOO }}",
Caveats: "don't do this {{ .ProjectName }}",
Test: "system \"true\"\nsystem \"#{bin}/foo -h\"",
Plist: `<xml>whatever</xml>`,
Dependencies: []config.HomebrewDependency{{Name: "zsh"}, {Name: "bash", Type: "recommended"}},
Conflicts: []string{"gtk+", "qt"},
Install: `bin.install "{{ .ProjectName }}"`,
Tap: config.RepoRef{
Owner: "test",
Name: "test",
},
Homepage: "https://github.com/goreleaser",
},
},
GitHubURLs: config.GitHubURLs{
Download: "https://github.com",
},
Release: config.Release{
GitHub: config.Repo{
Owner: "test",
Name: "test",
},
Homepage: "https://github.com/goreleaser",
},
},
GitHubURLs: config.GitHubURLs{
Download: "https://github.com",
}
fn(ctx)
for _, a := range []struct {
name string
goos string
goarch string
goarm string
}{
{
name: "bin",
goos: "darwin",
goarch: "amd64",
},
Release: config.Release{
GitHub: config.Repo{
Owner: "test",
Name: "test",
{
name: "arm64",
goos: "linux",
goarch: "arm64",
},
{
name: "armv5",
goos: "linux",
goarch: "arm",
goarm: "5",
},
{
name: "armv6",
goos: "linux",
goarch: "arm",
goarm: "6",
},
{
name: "armv7",
goos: "linux",
goarch: "arm",
goarm: "7",
},
} {
path := filepath.Join(folder, fmt.Sprintf("%s.tar.gz", a.name))
ctx.Artifacts.Add(&artifact.Artifact{
Name: fmt.Sprintf("%s.tar.gz", a.name),
Path: path,
Goos: a.goos,
Goarch: a.goarch,
Goarm: a.goarm,
Type: artifact.UploadableArchive,
Extra: map[string]interface{}{
"ID": a.name,
"Format": "tar.gz",
},
},
},
}
fn(ctx)
for _, a := range []struct {
name string
goos string
goarch string
goarm string
}{
{
name: "bin",
goos: "darwin",
goarch: "amd64",
},
{
name: "arm64",
goos: "linux",
goarch: "arm64",
},
{
name: "armv5",
goos: "linux",
goarch: "arm",
goarm: "5",
},
{
name: "armv6",
goos: "linux",
goarch: "arm",
goarm: "6",
},
{
name: "armv7",
goos: "linux",
goarch: "arm",
goarm: "7",
},
} {
path := filepath.Join(folder, fmt.Sprintf("%s.tar.gz", a.name))
ctx.Artifacts.Add(&artifact.Artifact{
Name: fmt.Sprintf("%s.tar.gz", a.name),
Path: path,
Goos: a.goos,
Goarch: a.goarch,
Goarm: a.goarm,
Type: artifact.UploadableArchive,
Extra: map[string]interface{}{
"ID": a.name,
"Format": "tar.gz",
},
})
f, err := os.Create(path)
})
f, err := os.Create(path)
require.NoError(t, err)
require.NoError(t, f.Close())
}
client := &DummyClient{}
distFile := filepath.Join(folder, name+".rb")
require.NoError(t, doRun(ctx, ctx.Config.Brews[0], client))
require.True(t, client.CreatedFile)
golden.RequireEqualRb(t, []byte(client.Content))
distBts, err := os.ReadFile(distFile)
require.NoError(t, err)
require.NoError(t, f.Close())
}
client := &DummyClient{}
distFile := filepath.Join(folder, name+".rb")
require.NoError(t, doRun(ctx, ctx.Config.Brews[0], client))
require.True(t, client.CreatedFile)
golden := fmt.Sprintf("testdata/%s.rb.golden", name)
if *update {
require.NoError(t, os.WriteFile(golden, []byte(client.Content), 0o655))
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), client.Content)
distBts, err := os.ReadFile(distFile)
require.NoError(t, err)
require.Equal(t, string(bts), string(distBts))
require.Equal(t, client.Content, string(distBts))
})
}
}

View File

@@ -1,41 +0,0 @@
# typed: false
# frozen_string_literal: true
# This file was generated by GoReleaser. DO NOT EDIT.
class BinaryOverridden < Formula
desc "A run pipe test formula"
homepage "https://github.com/goreleaser"
version "1.0.1"
if OS.mac?
url "https://github.com/test/test/releases/download/v1.0.1/bin.todo"
sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
elsif OS.linux?
end
depends_on "zsh" => :optional
depends_on "bash"
conflicts_with "gtk+"
conflicts_with "qt"
def install
bin.install "foo"
end
def caveats; <<~EOS
don't do this
EOS
end
plist_options :startup => false
def plist; <<~EOS
<xml>whatever</xml>
EOS
end
test do
system "true"
system "#{bin}/foo -h"
end
end

View File

@@ -8,7 +8,8 @@ import (
"github.com/goreleaser/goreleaser/pkg/context"
)
const bodyTemplateText = `{{ .ReleaseNotes }}
const bodyTemplateText = `{{ with .Header }}{{ . }}{{ "\n" }}{{ end }}
{{- .ReleaseNotes }}
{{- with .DockerImages }}
@@ -17,6 +18,7 @@ const bodyTemplateText = `{{ .ReleaseNotes }}
- ` + "`docker pull {{ . -}}`" + `
{{- end -}}
{{- end }}
{{- with .Footer }}{{ "\n" }}{{ . }}{{ end }}
`
func describeBody(ctx *context.Context) (bytes.Buffer, error) {
@@ -33,9 +35,13 @@ func describeBody(ctx *context.Context) (bytes.Buffer, error) {
}
bodyTemplate := template.Must(template.New("release").Parse(bodyTemplateText))
err := bodyTemplate.Execute(&out, struct {
Header string
Footer string
ReleaseNotes string
DockerImages []string
}{
Header: ctx.Config.Release.Header,
Footer: ctx.Config.Release.Footer,
ReleaseNotes: ctx.ReleaseNotes,
DockerImages: dockers,
})

View File

@@ -1,18 +1,15 @@
package release
import (
"flag"
"os"
"testing"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/golden"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/require"
)
var update = flag.Bool("update", false, "update .golden files")
func TestDescribeBody(t *testing.T) {
changelog := "feature1: description\nfeature2: other description"
ctx := context.New(config.Project{})
@@ -30,13 +27,7 @@ func TestDescribeBody(t *testing.T) {
out, err := describeBody(ctx)
require.NoError(t, err)
golden := "testdata/release1.golden"
if *update {
_ = os.WriteFile(golden, out.Bytes(), 0o755)
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), out.String())
golden.RequireEqual(t, out.Bytes())
}
func TestDescribeBodyWithDockerManifest(t *testing.T) {
@@ -69,13 +60,7 @@ func TestDescribeBodyWithDockerManifest(t *testing.T) {
out, err := describeBody(ctx)
require.NoError(t, err)
golden := "testdata/release3.golden"
if *update {
_ = os.WriteFile(golden, out.Bytes(), 0o755)
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), out.String())
golden.RequireEqual(t, out.Bytes())
}
func TestDescribeBodyNoDockerImagesNoBrews(t *testing.T) {
@@ -86,14 +71,7 @@ func TestDescribeBodyNoDockerImagesNoBrews(t *testing.T) {
out, err := describeBody(ctx)
require.NoError(t, err)
golden := "testdata/release2.golden"
if *update {
_ = os.WriteFile(golden, out.Bytes(), 0o655)
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), out.String())
golden.RequireEqual(t, out.Bytes())
}
func TestDontEscapeHTML(t *testing.T) {
@@ -105,3 +83,22 @@ func TestDontEscapeHTML(t *testing.T) {
require.NoError(t, err)
require.Contains(t, out.String(), changelog)
}
func TestDescribeBodyWithHeaderAndFooter(t *testing.T) {
changelog := "feature1: description\nfeature2: other description"
ctx := context.New(config.Project{
Release: config.Release{
Header: "## Yada yada yada\nsomething\n",
Footer: "\n---\n\nGet GoReleaser Pro at https://goreleaser.com/pro",
},
})
ctx.ReleaseNotes = changelog
ctx.Artifacts.Add(&artifact.Artifact{
Name: "goreleaser/goreleaser:latest",
Type: artifact.DockerImage,
})
out, err := describeBody(ctx)
require.NoError(t, err)
golden.RequireEqual(t, out.Bytes())
}

View File

@@ -251,7 +251,7 @@ func TestRunPipeExtraFileNotFound(t *testing.T) {
Name: "test",
},
ExtraFiles: []config.ExtraFile{
{Glob: "./testdata/release2.golden"},
{Glob: "./testdata/f1.txt"},
{Glob: "./nope"},
},
},

View File

@@ -0,0 +1,13 @@
## Yada yada yada
something
feature1: description
feature2: other description
## Docker images
- `docker pull goreleaser/goreleaser:latest`
---
Get GoReleaser Pro at https://goreleaser.com/pro

0
internal/pipe/release/testdata/f1.txt vendored Normal file
View File

View File

@@ -2,13 +2,13 @@ package scoop
import (
ctx "context"
"flag"
"os"
"path/filepath"
"testing"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/client"
"github.com/goreleaser/goreleaser/internal/golden"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/pkg/config"
@@ -16,8 +16,6 @@ import (
"github.com/stretchr/testify/require"
)
var update = flag.Bool("update", false, "update .golden files")
func TestDescription(t *testing.T) {
require.NotEmpty(t, Pipe{}.String())
}
@@ -736,11 +734,11 @@ func Test_buildManifest(t *testing.T) {
require.NoError(t, os.WriteFile(file, []byte("lorem ipsum"), 0o644))
tests := []struct {
filename string
ctx *context.Context
desc string
ctx *context.Context
}{
{
"testdata/test_buildmanifest.json.golden",
"common",
&context.Context{
Context: ctx.Background(),
TokenType: context.TokenTypeGitHub,
@@ -777,7 +775,7 @@ func Test_buildManifest(t *testing.T) {
},
},
{
"testdata/test_buildmanifest_pre_post_install.json.golden",
"pre-post-install",
&context.Context{
Context: ctx.Background(),
TokenType: context.TokenTypeGitHub,
@@ -816,7 +814,7 @@ func Test_buildManifest(t *testing.T) {
},
},
{
"testdata/test_buildmanifest_url_template.json.golden",
"url template",
&context.Context{
Context: ctx.Background(),
TokenType: context.TokenTypeGitHub,
@@ -858,7 +856,7 @@ func Test_buildManifest(t *testing.T) {
},
},
{
"testdata/test_buildmanifest_gitlab_url_template.json.golden",
"gitlab url template",
&context.Context{
Context: ctx.Background(),
TokenType: context.TokenTypeGitLab,
@@ -902,7 +900,7 @@ func Test_buildManifest(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.filename, func(t *testing.T) {
t.Run(tt.desc, func(t *testing.T) {
ctx := tt.ctx
err := Pipe{}.Default(ctx)
require.NoError(t, err)
@@ -965,12 +963,7 @@ func Test_buildManifest(t *testing.T) {
out, err := doBuildManifest(mf)
require.NoError(t, err)
if *update {
require.NoError(t, os.WriteFile(tt.filename, out.Bytes(), 0o655))
}
bts, err := os.ReadFile(tt.filename)
require.NoError(t, err)
require.Equal(t, string(bts), out.String())
golden.RequireEqualJSON(t, out.Bytes())
})
}
}
@@ -1097,14 +1090,7 @@ func TestWrapInDirectory(t *testing.T) {
out, err := doBuildManifest(mf)
require.NoError(t, err)
golden := "testdata/test_buildmanifest_wrap.json.golden"
if *update {
require.NoError(t, os.WriteFile(golden, out.Bytes(), 0o655))
}
bts, err := os.ReadFile(golden)
require.NoError(t, err)
require.Equal(t, string(bts), out.String())
golden.RequireEqualJSON(t, out.Bytes())
}
type DummyClient struct {

View File

@@ -284,6 +284,8 @@ type Release struct {
IDs []string `yaml:"ids,omitempty"`
ExtraFiles []ExtraFile `yaml:"extra_files,omitempty"`
DiscussionCategoryName string `yaml:"discussion_category_name,omitempty"`
Header string `yaml:"header,omitempty"`
Footer string `yaml:"footer,omitempty"`
}
// Milestone config used for VCS milestone.

View File

@@ -38,6 +38,20 @@ release:
# Default is false.
prerelease: auto
# Header for the release body.
# Defaults to empty.
header: |
## Some title
Welcome to this new release!
# Footer for the release body.
# Defaults to empty.
footer: |
## Thanks!
Something to add to the end.
# You can change the name of the release.
# Default is `{{.Tag}}` on OSS and `{{.PrefixedTag}}` on Pro.
name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}"