You've already forked goreleaser
mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-09-16 09:26:52 +02:00
feat: Added new flags to support release notes header and footer. (#1212)
* Added new flags to support release notes header and footer. Created two flags for release generation. --release-footer --release-header These flags can help you to add custom changelog text before/after changes that are generated by git log. * Fix changelog.go to avoid lint errors * Fix test typo * Added tests for main, fixed bug with no passing options to release ctx * Add @caarlos0 suggestions
This commit is contained in:
committed by
Carlos Alexandro Becker
parent
fdfe0487df
commit
16cb4d8277
@@ -35,6 +35,8 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.WithField("file", ctx.ReleaseNotes).Info("loaded custom release notes")
|
||||
log.WithField("file", ctx.ReleaseNotes).Debugf("custom release notes: \n%s", notes)
|
||||
ctx.ReleaseNotes = notes
|
||||
}
|
||||
if ctx.Config.Changelog.Skip {
|
||||
@@ -46,9 +48,25 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
if ctx.ReleaseNotes != "" {
|
||||
return nil
|
||||
}
|
||||
if ctx.ReleaseHeader != "" {
|
||||
header, err := loadFromFile(ctx.ReleaseHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.ReleaseHeader = header
|
||||
}
|
||||
if ctx.ReleaseFooter != "" {
|
||||
footer, err := loadFromFile(ctx.ReleaseFooter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.ReleaseFooter = footer
|
||||
}
|
||||
|
||||
if err := checkSortDirection(ctx.Config.Changelog.Sort); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entries, err := buildChangelog(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -61,7 +79,17 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
log.Debug("is gitlab or gitea changelog")
|
||||
changelogStringJoiner = " \n"
|
||||
}
|
||||
ctx.ReleaseNotes = fmt.Sprintf("## Changelog\n\n%v\n", strings.Join(entries, changelogStringJoiner))
|
||||
|
||||
ctx.ReleaseNotes = strings.Join(
|
||||
[]string{
|
||||
ctx.ReleaseHeader,
|
||||
"## Changelog",
|
||||
strings.Join(entries, changelogStringJoiner),
|
||||
ctx.ReleaseFooter,
|
||||
},
|
||||
"\n\n",
|
||||
)
|
||||
|
||||
var path = filepath.Join(ctx.Config.Dist, "CHANGELOG.md")
|
||||
log.WithField("changelog", path).Info("writing")
|
||||
return ioutil.WriteFile(path, []byte(ctx.ReleaseNotes), 0644)
|
||||
@@ -72,8 +100,6 @@ func loadFromFile(file string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.WithField("file", file).Info("loaded custom release notes")
|
||||
log.WithField("file", file).Debugf("custom release notes: \n%s", string(bts))
|
||||
return string(bts), nil
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,7 @@ package changelog
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
@@ -46,6 +47,18 @@ func TestChangelogSkip(t *testing.T) {
|
||||
testlib.AssertSkipped(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestReleaseHeaderProvidedViaFlagDoesntExist(t *testing.T) {
|
||||
var ctx = context.New(config.Project{})
|
||||
ctx.ReleaseHeader = "testdata/header.nope"
|
||||
require.EqualError(t, Pipe{}.Run(ctx), "open testdata/header.nope: no such file or directory")
|
||||
}
|
||||
|
||||
func TestReleaseFooterProvidedViaFlagDoesntExist(t *testing.T) {
|
||||
var ctx = context.New(config.Project{})
|
||||
ctx.ReleaseFooter = "testdata/footer.nope"
|
||||
require.EqualError(t, Pipe{}.Run(ctx), "open testdata/footer.nope: no such file or directory")
|
||||
}
|
||||
|
||||
func TestSnapshot(t *testing.T) {
|
||||
var ctx = context.New(config.Project{})
|
||||
ctx.Snapshot = true
|
||||
@@ -285,3 +298,55 @@ func TestChangelogOnBranchWithSameNameAsTag(t *testing.T) {
|
||||
require.Contains(t, ctx.ReleaseNotes, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangeLogWithReleaseHeader(t *testing.T) {
|
||||
current, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
tmpdir, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
require.NoError(t, os.Symlink(current+"/testdata", tmpdir+"/testdata"))
|
||||
testlib.GitInit(t)
|
||||
var msgs = []string{
|
||||
"initial commit",
|
||||
"another one",
|
||||
"one more",
|
||||
"and finally this one",
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
testlib.GitCommit(t, msg)
|
||||
}
|
||||
testlib.GitTag(t, "v0.0.1")
|
||||
testlib.GitCheckoutBranch(t, "v0.0.1")
|
||||
var ctx = context.New(config.Project{})
|
||||
ctx.Git.CurrentTag = "v0.0.1"
|
||||
ctx.ReleaseHeader = "testdata/release-header.md"
|
||||
require.NoError(t, Pipe{}.Run(ctx))
|
||||
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
|
||||
require.Contains(t, ctx.ReleaseNotes, "test header")
|
||||
}
|
||||
|
||||
func TestChangeLogWithReleaseFooter(t *testing.T) {
|
||||
current, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
tmpdir, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
require.NoError(t, os.Symlink(current+"/testdata", tmpdir+"/testdata"))
|
||||
testlib.GitInit(t)
|
||||
var msgs = []string{
|
||||
"initial commit",
|
||||
"another one",
|
||||
"one more",
|
||||
"and finally this one",
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
testlib.GitCommit(t, msg)
|
||||
}
|
||||
testlib.GitTag(t, "v0.0.1")
|
||||
testlib.GitCheckoutBranch(t, "v0.0.1")
|
||||
var ctx = context.New(config.Project{})
|
||||
ctx.Git.CurrentTag = "v0.0.1"
|
||||
ctx.ReleaseFooter = "testdata/release-footer.md"
|
||||
require.NoError(t, Pipe{}.Run(ctx))
|
||||
require.Contains(t, ctx.ReleaseNotes, "## Changelog")
|
||||
require.Contains(t, ctx.ReleaseNotes, "test footer")
|
||||
}
|
||||
|
1
internal/pipe/changelog/testdata/release-footer.md
vendored
Normal file
1
internal/pipe/changelog/testdata/release-footer.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test footer
|
1
internal/pipe/changelog/testdata/release-header.md
vendored
Normal file
1
internal/pipe/changelog/testdata/release-header.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test header
|
46
main.go
46
main.go
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
"github.com/goreleaser/goreleaser/pkg/defaults"
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
// nolint: gochecknoglobals
|
||||
@@ -28,15 +28,17 @@ var (
|
||||
)
|
||||
|
||||
type releaseOptions struct {
|
||||
Config string
|
||||
ReleaseNotes string
|
||||
Snapshot bool
|
||||
SkipPublish bool
|
||||
SkipSign bool
|
||||
SkipValidate bool
|
||||
RmDist bool
|
||||
Parallelism int
|
||||
Timeout time.Duration
|
||||
Config string
|
||||
ReleaseNotes string
|
||||
ReleaseHeader string
|
||||
ReleaseFooter string
|
||||
Snapshot bool
|
||||
SkipPublish bool
|
||||
SkipSign bool
|
||||
SkipValidate bool
|
||||
RmDist bool
|
||||
Parallelism int
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -56,6 +58,8 @@ func main() {
|
||||
var checkCmd = app.Command("check", "Checks if configuration is valid").Alias("c")
|
||||
var releaseCmd = app.Command("release", "Releases the current project").Alias("r").Default()
|
||||
var releaseNotes = releaseCmd.Flag("release-notes", "Load custom release notes from a markdown file").PlaceHolder("notes.md").String()
|
||||
var releaseHeader = releaseCmd.Flag("release-header", "Load custom release notes header from a markdown file").PlaceHolder("notes-header.md").String()
|
||||
var releaseFooter = releaseCmd.Flag("release-footer", "Load custom release notes footer from a markdown file").PlaceHolder("notes-footer.md").String()
|
||||
var snapshot = releaseCmd.Flag("snapshot", "Generate an unversioned snapshot release, skipping all validations and without publishing any artifacts").Bool()
|
||||
var skipPublish = releaseCmd.Flag("skip-publish", "Skips publishing artifacts").Bool()
|
||||
var skipSign = releaseCmd.Flag("skip-sign", "Skips signing the artifacts").Bool()
|
||||
@@ -96,15 +100,17 @@ func main() {
|
||||
start := time.Now()
|
||||
log.Infof(color.New(color.Bold).Sprintf("releasing using goreleaser %s...", version))
|
||||
var options = releaseOptions{
|
||||
Config: *config,
|
||||
ReleaseNotes: *releaseNotes,
|
||||
Snapshot: *snapshot,
|
||||
SkipPublish: *skipPublish,
|
||||
SkipValidate: *skipValidate,
|
||||
SkipSign: *skipSign,
|
||||
RmDist: *rmDist,
|
||||
Parallelism: *parallelism,
|
||||
Timeout: *timeout,
|
||||
Config: *config,
|
||||
ReleaseNotes: *releaseNotes,
|
||||
ReleaseHeader: *releaseHeader,
|
||||
ReleaseFooter: *releaseFooter,
|
||||
Snapshot: *snapshot,
|
||||
SkipPublish: *skipPublish,
|
||||
SkipValidate: *skipValidate,
|
||||
SkipSign: *skipSign,
|
||||
RmDist: *rmDist,
|
||||
Parallelism: *parallelism,
|
||||
Timeout: *timeout,
|
||||
}
|
||||
if err := releaseProject(options); err != nil {
|
||||
log.WithError(err).Errorf(color.New(color.Bold).Sprintf("release failed after %0.2fs", time.Since(start).Seconds()))
|
||||
@@ -141,6 +147,8 @@ func releaseProject(options releaseOptions) error {
|
||||
ctx.Parallelism = options.Parallelism
|
||||
log.Debugf("parallelism: %v", ctx.Parallelism)
|
||||
ctx.ReleaseNotes = options.ReleaseNotes
|
||||
ctx.ReleaseHeader = options.ReleaseHeader
|
||||
ctx.ReleaseFooter = options.ReleaseFooter
|
||||
ctx.Snapshot = options.Snapshot
|
||||
ctx.SkipPublish = ctx.Snapshot || options.SkipPublish
|
||||
ctx.SkipValidate = ctx.Snapshot || options.SkipValidate
|
||||
|
46
main_test.go
46
main_test.go
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -107,6 +107,50 @@ func TestCustomReleaseNotesFile(t *testing.T) {
|
||||
assert.NoError(t, releaseProject(params))
|
||||
}
|
||||
|
||||
func TestCustomReleaseHeaderFileDontExist(t *testing.T) {
|
||||
_, back := setup(t)
|
||||
defer back()
|
||||
params := testParams()
|
||||
params.ReleaseHeader = "/header/that/dont/exist"
|
||||
params.Snapshot = false
|
||||
assert.Error(t, releaseProject(params))
|
||||
}
|
||||
|
||||
func TestCustomReleaseHeaderFile(t *testing.T) {
|
||||
_, back := setup(t)
|
||||
defer back()
|
||||
releaseHeader, err := ioutil.TempFile("", "")
|
||||
assert.NoError(t, err)
|
||||
createFile(t, releaseHeader.Name(), "some release header")
|
||||
params := testParams()
|
||||
params.ReleaseHeader = releaseHeader.Name()
|
||||
params.Snapshot = false
|
||||
params.SkipPublish = true
|
||||
assert.NoError(t, releaseProject(params))
|
||||
}
|
||||
|
||||
func TestCustomReleaseFooterFileDontExist(t *testing.T) {
|
||||
_, back := setup(t)
|
||||
defer back()
|
||||
params := testParams()
|
||||
params.ReleaseFooter = "/footer/that/dont/exist"
|
||||
params.Snapshot = false
|
||||
assert.Error(t, releaseProject(params))
|
||||
}
|
||||
|
||||
func TestCustomReleaseFooterFile(t *testing.T) {
|
||||
_, back := setup(t)
|
||||
defer back()
|
||||
releaseFooter, err := ioutil.TempFile("", "")
|
||||
assert.NoError(t, err)
|
||||
createFile(t, releaseFooter.Name(), "some release footer")
|
||||
params := testParams()
|
||||
params.ReleaseFooter = releaseFooter.Name()
|
||||
params.Snapshot = false
|
||||
params.SkipPublish = true
|
||||
assert.NoError(t, releaseProject(params))
|
||||
}
|
||||
|
||||
func TestBrokenPipe(t *testing.T) {
|
||||
_, back := setup(t)
|
||||
defer back()
|
||||
|
@@ -53,22 +53,24 @@ const (
|
||||
// Context carries along some data through the pipes
|
||||
type Context struct {
|
||||
ctx.Context
|
||||
Config config.Project
|
||||
Env Env
|
||||
Token string
|
||||
TokenType TokenType
|
||||
Git GitInfo
|
||||
Artifacts artifact.Artifacts
|
||||
ReleaseNotes string
|
||||
Version string
|
||||
Snapshot bool
|
||||
SkipPublish bool
|
||||
SkipSign bool
|
||||
SkipValidate bool
|
||||
RmDist bool
|
||||
PreRelease bool
|
||||
Parallelism int
|
||||
Semver Semver
|
||||
Config config.Project
|
||||
Env Env
|
||||
Token string
|
||||
TokenType TokenType
|
||||
Git GitInfo
|
||||
Artifacts artifact.Artifacts
|
||||
ReleaseNotes string
|
||||
ReleaseHeader string
|
||||
ReleaseFooter string
|
||||
Version string
|
||||
Snapshot bool
|
||||
SkipPublish bool
|
||||
SkipSign bool
|
||||
SkipValidate bool
|
||||
RmDist bool
|
||||
PreRelease bool
|
||||
Parallelism int
|
||||
Semver Semver
|
||||
}
|
||||
|
||||
// Semver represents a semantic version
|
||||
|
Reference in New Issue
Block a user