mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-25 21:29:14 +02:00
Merge pull request #184 from goreleaser/custom-release-file
Custom release file
This commit is contained in:
commit
880b2c22ed
@ -4,7 +4,6 @@ package client
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
)
|
||||
@ -19,17 +18,7 @@ type Info struct {
|
||||
// Client interface
|
||||
type Client interface {
|
||||
GetInfo(ctx *context.Context) (info Info, err error)
|
||||
CreateRelease(ctx *context.Context) (releaseID int, err error)
|
||||
CreateRelease(ctx *context.Context, body string) (releaseID int, err error)
|
||||
CreateFile(ctx *context.Context, content bytes.Buffer, path string) (err error)
|
||||
Upload(ctx *context.Context, releaseID int, name string, file *os.File) (err error)
|
||||
}
|
||||
|
||||
func describeRelease(diff string) string {
|
||||
result := "## Changelog\n" + diff + "\n\n--\nAutomated with @goreleaser"
|
||||
cmd := exec.Command("go", "version")
|
||||
bts, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
return result + "\nBuilt with " + string(bts)
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDescription(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
desc := describeRelease("0abf342 some message")
|
||||
assert.Contains(desc, "0abf342 some message")
|
||||
assert.Contains(desc, "Automated with @goreleaser")
|
||||
assert.Contains(desc, "go version go1.")
|
||||
}
|
@ -88,11 +88,11 @@ func (c *githubClient) GetInfo(ctx *context.Context) (info Info, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *githubClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
|
||||
func (c *githubClient) CreateRelease(ctx *context.Context, body string) (releaseID int, err error) {
|
||||
data := &github.RepositoryRelease{
|
||||
Name: github.String(ctx.Git.CurrentTag),
|
||||
TagName: github.String(ctx.Git.CurrentTag),
|
||||
Body: github.String(describeRelease(ctx.Git.Diff)),
|
||||
Body: github.String(body),
|
||||
}
|
||||
r, _, err := c.client.Repositories.GetReleaseByTag(
|
||||
ctx,
|
||||
|
@ -17,23 +17,22 @@ import (
|
||||
|
||||
// GitInfo includes tags and diffs used in some point
|
||||
type GitInfo struct {
|
||||
CurrentTag string
|
||||
PreviousTag string
|
||||
Diff string
|
||||
Commit string
|
||||
CurrentTag string
|
||||
Commit string
|
||||
}
|
||||
|
||||
// Context carries along some data through the pipes
|
||||
type Context struct {
|
||||
ctx.Context
|
||||
Config config.Project
|
||||
Token string
|
||||
Git GitInfo
|
||||
Archives map[string]string
|
||||
Artifacts []string
|
||||
Version string
|
||||
Validate bool
|
||||
Publish bool
|
||||
Config config.Project
|
||||
Token string
|
||||
Git GitInfo
|
||||
Archives map[string]string
|
||||
Artifacts []string
|
||||
ReleaseNotes string
|
||||
Version string
|
||||
Validate bool
|
||||
Publish bool
|
||||
}
|
||||
|
||||
var lock sync.Mutex
|
||||
|
15
main.go
15
main.go
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
@ -52,6 +53,10 @@ func main() {
|
||||
Usage: "Load configuration from `FILE`",
|
||||
Value: "goreleaser.yml",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "release-notes",
|
||||
Usage: "Path to a markdown file with custom release notes",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "skip-validate",
|
||||
Usage: "Skip all the validations against the release",
|
||||
@ -62,7 +67,9 @@ func main() {
|
||||
},
|
||||
}
|
||||
app.Action = func(c *cli.Context) (err error) {
|
||||
// TODO: cover this with tests
|
||||
var file = c.String("config")
|
||||
var notes = c.String("release-notes")
|
||||
cfg, err := config.Load(file)
|
||||
if err != nil {
|
||||
// Allow file not found errors if config file was not
|
||||
@ -75,6 +82,14 @@ func main() {
|
||||
var ctx = context.New(cfg)
|
||||
ctx.Validate = !c.Bool("skip-validate")
|
||||
ctx.Publish = !c.Bool("skip-publish")
|
||||
if notes != "" {
|
||||
bts, err := ioutil.ReadFile(notes)
|
||||
if err != nil {
|
||||
return cli.NewExitError(err.Error(), 1)
|
||||
}
|
||||
log.Println("Loaded custom release notes from", notes)
|
||||
ctx.ReleaseNotes = string(bts)
|
||||
}
|
||||
for _, pipe := range pipes {
|
||||
log.Println(pipe.Description())
|
||||
log.SetPrefix(" -> ")
|
||||
|
@ -163,7 +163,7 @@ func (client *DummyClient) GetInfo(ctx *context.Context) (info client.Info, err
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
|
||||
func (client *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseID int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
if ctx.Config.Release.GitHub.Name == "" {
|
||||
repo, err := remoteRepo()
|
||||
ctx.Config.Release.GitHub = repo
|
||||
// TODO add a test to cover this
|
||||
if err != nil {
|
||||
return errors.New("failed reading repo from git: " + err.Error())
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
func remoteRepo() (result config.Repo, err error) {
|
||||
cmd := exec.Command("git", "config", "--get", "remote.origin.url")
|
||||
bts, err := cmd.CombinedOutput()
|
||||
// TODO: cover this with tests
|
||||
if err != nil {
|
||||
return result, errors.New(err.Error() + ": " + string(bts))
|
||||
}
|
||||
|
@ -47,15 +47,20 @@ func (Pipe) Description() string {
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) (err error) {
|
||||
tag, prev, commit, log, err := getInfo()
|
||||
tag, commit, err := getInfo()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctx.Git = context.GitInfo{
|
||||
CurrentTag: tag,
|
||||
PreviousTag: prev,
|
||||
Diff: log,
|
||||
Commit: commit,
|
||||
CurrentTag: tag,
|
||||
Commit: commit,
|
||||
}
|
||||
if ctx.ReleaseNotes == "" {
|
||||
log, err := getChangelog(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.ReleaseNotes = fmt.Sprintf("## Changelog\n\n%v", log)
|
||||
}
|
||||
// removes usual `v` prefix
|
||||
ctx.Version = strings.TrimPrefix(tag, "v")
|
||||
@ -81,19 +86,19 @@ func validate(commit, tag, version string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getInfo() (tag, prev, commit, log string, err error) {
|
||||
func getChangelog(tag string) (string, error) {
|
||||
prev, err := previous(tag)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return git("log", "--pretty=oneline", "--abbrev-commit", prev+".."+tag)
|
||||
}
|
||||
|
||||
func getInfo() (tag, commit string, err error) {
|
||||
tag, err = cleanGit("describe", "--tags", "--abbrev=0", "--always")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
prev, err = previous(tag)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log, err = git("log", "--pretty=oneline", "--abbrev-commit", prev+".."+tag)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
commit, err = cleanGit("show", "--format='%H'", "HEAD")
|
||||
return
|
||||
}
|
||||
|
@ -118,6 +118,42 @@ func TestNoValidate(t *testing.T) {
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestChangelog(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
_, back := createAndChdir(t)
|
||||
defer back()
|
||||
gitInit(t)
|
||||
gitCommit(t, "first")
|
||||
gitTag(t, "v0.0.1")
|
||||
gitCommit(t, "added feature 1")
|
||||
gitCommit(t, "fixed bug 2")
|
||||
gitTag(t, "v0.0.2")
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{},
|
||||
}
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
assert.Equal("v0.0.2", ctx.Git.CurrentTag)
|
||||
assert.Contains(ctx.ReleaseNotes, "## Changelog")
|
||||
assert.Contains(ctx.ReleaseNotes, "added feature 1")
|
||||
assert.Contains(ctx.ReleaseNotes, "fixed bug 2")
|
||||
}
|
||||
|
||||
func TestCustomReleaseNotes(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
_, back := createAndChdir(t)
|
||||
defer back()
|
||||
gitInit(t)
|
||||
gitCommit(t, "first")
|
||||
gitTag(t, "v0.0.1")
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{},
|
||||
ReleaseNotes: "custom",
|
||||
}
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
assert.Equal("v0.0.1", ctx.Git.CurrentTag)
|
||||
assert.Equal(ctx.ReleaseNotes, "custom")
|
||||
}
|
||||
|
||||
//
|
||||
// helper functions
|
||||
//
|
||||
|
32
pipeline/release/body.go
Normal file
32
pipeline/release/body.go
Normal file
@ -0,0 +1,32 @@
|
||||
package release
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"os/exec"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
)
|
||||
|
||||
const bodyTemplate = `{{ .ReleaseNotes }}
|
||||
|
||||
---
|
||||
Automated with @goreleaser
|
||||
Built with {{ .GoVersion }}
|
||||
`
|
||||
|
||||
func describeBody(ctx *context.Context) (bytes.Buffer, error) {
|
||||
var out bytes.Buffer
|
||||
bts, err := exec.Command("go", "version").CombinedOutput()
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
var template = template.Must(template.New("release").Parse(bodyTemplate))
|
||||
err = template.Execute(&out, struct {
|
||||
ReleaseNotes, GoVersion string
|
||||
}{
|
||||
ReleaseNotes: ctx.ReleaseNotes,
|
||||
GoVersion: string(bts),
|
||||
})
|
||||
return out, err
|
||||
}
|
36
pipeline/release/body_test.go
Normal file
36
pipeline/release/body_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package release
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDescribeBody(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var changelog = "\nfeature1: description\nfeature2: other description"
|
||||
var ctx = &context.Context{
|
||||
ReleaseNotes: changelog,
|
||||
}
|
||||
out, err := describeBody(ctx)
|
||||
assert.NoError(err)
|
||||
assert.Contains(out.String(), changelog)
|
||||
assert.Contains(out.String(), "Automated with @goreleaser")
|
||||
assert.Contains(out.String(), "Built with go version go1.8")
|
||||
}
|
||||
|
||||
func TestGoVersionFails(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var path = os.Getenv("PATH")
|
||||
defer func() {
|
||||
assert.NoError(os.Setenv("PATH", path))
|
||||
}()
|
||||
os.Setenv("PATH", "")
|
||||
var ctx = &context.Context{
|
||||
ReleaseNotes: "changelog",
|
||||
}
|
||||
_, err := describeBody(ctx)
|
||||
assert.Error(err)
|
||||
}
|
@ -30,7 +30,11 @@ func doRun(ctx *context.Context, client client.Client) error {
|
||||
return nil
|
||||
}
|
||||
log.Println("Creating or updating release", ctx.Git.CurrentTag, "on", ctx.Config.Release.GitHub.String())
|
||||
releaseID, err := client.CreateRelease(ctx)
|
||||
body, err := describeBody(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
releaseID, err := client.CreateRelease(ctx, body.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ func (client *DummyClient) GetInfo(ctx *context.Context) (info client.Info, err
|
||||
return
|
||||
}
|
||||
|
||||
func (client *DummyClient) CreateRelease(ctx *context.Context) (releaseID int, err error) {
|
||||
func (client *DummyClient) CreateRelease(ctx *context.Context, body string) (releaseID int, err error) {
|
||||
if client.FailToCreateRelease {
|
||||
return 0, errors.New("release failed")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user