2017-04-15 21:12:32 +02:00
|
|
|
// Package git implements the Pipe interface getting and validating the
|
|
|
|
// current git repository state
|
2017-01-14 16:34:22 +02:00
|
|
|
package git
|
|
|
|
|
2017-01-30 01:55:32 +02:00
|
|
|
import (
|
2017-04-29 12:49:22 +02:00
|
|
|
"bytes"
|
2017-04-15 22:04:26 +02:00
|
|
|
"fmt"
|
2017-01-30 12:08:42 +02:00
|
|
|
"regexp"
|
2017-01-30 01:55:32 +02:00
|
|
|
"strings"
|
2017-04-29 12:49:22 +02:00
|
|
|
"text/template"
|
2017-06-22 05:09:14 +02:00
|
|
|
"time"
|
2017-01-30 01:55:32 +02:00
|
|
|
|
2017-06-22 05:09:14 +02:00
|
|
|
"github.com/apex/log"
|
2017-01-30 01:55:32 +02:00
|
|
|
"github.com/goreleaser/goreleaser/context"
|
2017-08-19 17:47:04 +02:00
|
|
|
"github.com/goreleaser/goreleaser/internal/git"
|
2017-08-20 21:35:46 +02:00
|
|
|
"github.com/goreleaser/goreleaser/pipeline"
|
2017-01-30 01:55:32 +02:00
|
|
|
)
|
2017-01-14 16:34:22 +02:00
|
|
|
|
|
|
|
// Pipe for brew deployment
|
|
|
|
type Pipe struct{}
|
|
|
|
|
2017-01-14 20:41:32 +02:00
|
|
|
// Description of the pipe
|
2017-01-14 19:14:35 +02:00
|
|
|
func (Pipe) Description() string {
|
2017-04-15 21:11:47 +02:00
|
|
|
return "Getting and validating git state"
|
2017-01-14 16:34:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Run the pipe
|
2017-04-15 19:00:49 +02:00
|
|
|
func (Pipe) Run(ctx *context.Context) (err error) {
|
2017-04-19 22:05:10 +02:00
|
|
|
tag, commit, err := getInfo()
|
2017-01-14 16:34:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2017-04-29 12:49:22 +02:00
|
|
|
if tag == "" && !ctx.Snapshot {
|
|
|
|
return ErrNoTag
|
|
|
|
}
|
2017-01-18 19:08:48 +02:00
|
|
|
ctx.Git = context.GitInfo{
|
2017-04-19 22:05:10 +02:00
|
|
|
CurrentTag: tag,
|
|
|
|
Commit: commit,
|
2017-01-14 18:06:57 +02:00
|
|
|
}
|
2017-09-03 03:51:03 +02:00
|
|
|
log.Infof("releasing %s, commit %s", tag, commit)
|
2017-05-01 15:39:57 +02:00
|
|
|
if err = setLog(ctx, tag, commit); err != nil {
|
|
|
|
return
|
2017-04-19 21:59:26 +02:00
|
|
|
}
|
2017-05-01 15:39:57 +02:00
|
|
|
if err = setVersion(ctx, tag, commit); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !ctx.Validate {
|
2017-08-20 21:35:46 +02:00
|
|
|
return pipeline.Skip("--skip-validate is set")
|
2017-05-01 15:39:57 +02:00
|
|
|
}
|
2017-05-01 15:57:37 +02:00
|
|
|
return validate(ctx, commit, tag)
|
2017-05-01 15:39:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func setVersion(ctx *context.Context, tag, commit string) (err error) {
|
|
|
|
if ctx.Snapshot {
|
2017-04-29 12:49:22 +02:00
|
|
|
snapshotName, err := getSnapshotName(ctx, tag, commit)
|
|
|
|
if err != nil {
|
2017-05-01 15:39:57 +02:00
|
|
|
return fmt.Errorf("failed to generate snapshot name: %s", err.Error())
|
2017-04-29 12:49:22 +02:00
|
|
|
}
|
|
|
|
ctx.Version = snapshotName
|
2017-05-01 15:39:57 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// removes usual `v` prefix
|
|
|
|
ctx.Version = strings.TrimPrefix(tag, "v")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func setLog(ctx *context.Context, tag, commit string) (err error) {
|
|
|
|
if ctx.ReleaseNotes != "" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var log string
|
|
|
|
if tag == "" {
|
|
|
|
log, err = getChangelog(commit)
|
2017-04-29 12:49:22 +02:00
|
|
|
} else {
|
2017-05-01 15:39:57 +02:00
|
|
|
log, err = getChangelog(tag)
|
2017-04-29 12:49:22 +02:00
|
|
|
}
|
2017-05-01 15:39:57 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2017-04-18 18:10:13 +02:00
|
|
|
}
|
2017-05-01 15:39:57 +02:00
|
|
|
ctx.ReleaseNotes = fmt.Sprintf("## Changelog\n\n%v", log)
|
|
|
|
return nil
|
2017-04-29 12:49:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type snapshotNameData struct {
|
|
|
|
Commit string
|
|
|
|
Tag string
|
|
|
|
Timestamp int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func getSnapshotName(ctx *context.Context, tag, commit string) (string, error) {
|
|
|
|
tmpl, err := template.New("snapshot").Parse(ctx.Config.Snapshot.NameTemplate)
|
|
|
|
var out bytes.Buffer
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2017-05-01 15:39:57 +02:00
|
|
|
var data = snapshotNameData{
|
|
|
|
Commit: commit,
|
|
|
|
Tag: tag,
|
|
|
|
Timestamp: time.Now().Unix(),
|
2017-04-29 12:49:22 +02:00
|
|
|
}
|
2017-05-01 15:39:57 +02:00
|
|
|
err = tmpl.Execute(&out, data)
|
|
|
|
return out.String(), err
|
2017-04-15 22:04:26 +02:00
|
|
|
}
|
|
|
|
|
2017-05-01 15:57:37 +02:00
|
|
|
func validate(ctx *context.Context, commit, tag string) error {
|
2017-08-19 17:47:04 +02:00
|
|
|
out, err := git.Run("status", "--porcelain")
|
2017-04-15 21:11:47 +02:00
|
|
|
if strings.TrimSpace(out) != "" || err != nil {
|
|
|
|
return ErrDirty{out}
|
|
|
|
}
|
2017-05-01 15:57:37 +02:00
|
|
|
if ctx.Snapshot {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if !regexp.MustCompile("^[0-9.]+").MatchString(ctx.Version) {
|
|
|
|
return ErrInvalidVersionFormat{ctx.Version}
|
|
|
|
}
|
|
|
|
_, err = cleanGit("describe", "--exact-match", "--tags", "--match", tag)
|
|
|
|
if err != nil {
|
|
|
|
return ErrWrongRef{commit, tag}
|
2017-04-15 21:11:47 +02:00
|
|
|
}
|
|
|
|
return nil
|
2017-01-14 16:34:22 +02:00
|
|
|
}
|
2017-04-15 18:05:54 +02:00
|
|
|
|
2017-04-19 22:05:10 +02:00
|
|
|
func getChangelog(tag string) (string, error) {
|
|
|
|
prev, err := previous(tag)
|
2017-04-15 18:05:54 +02:00
|
|
|
if err != nil {
|
2017-04-19 22:05:10 +02:00
|
|
|
return "", err
|
2017-04-15 22:04:26 +02:00
|
|
|
}
|
2017-04-23 21:33:44 +02:00
|
|
|
if !prev.Tag {
|
|
|
|
return gitLog(prev.SHA, tag)
|
|
|
|
}
|
|
|
|
return gitLog(fmt.Sprintf("%v..%v", prev.SHA, tag))
|
|
|
|
}
|
|
|
|
|
|
|
|
func gitLog(refs ...string) (string, error) {
|
|
|
|
var args = []string{"log", "--pretty=oneline", "--abbrev-commit"}
|
|
|
|
args = append(args, refs...)
|
2017-08-19 17:47:04 +02:00
|
|
|
return git.Run(args...)
|
2017-04-19 22:05:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func getInfo() (tag, commit string, err error) {
|
2017-04-23 21:33:44 +02:00
|
|
|
tag, err = cleanGit("describe", "--tags", "--abbrev=0")
|
2017-04-15 22:04:26 +02:00
|
|
|
if err != nil {
|
2017-06-22 15:47:34 +02:00
|
|
|
log.WithError(err).Info("failed to retrieve current tag")
|
2017-04-15 22:04:26 +02:00
|
|
|
}
|
|
|
|
commit, err = cleanGit("show", "--format='%H'", "HEAD")
|
2017-04-15 18:05:54 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-04-23 21:42:34 +02:00
|
|
|
func previous(tag string) (result ref, err error) {
|
|
|
|
result.Tag = true
|
|
|
|
result.SHA, err = cleanGit("describe", "--tags", "--abbrev=0", tag+"^")
|
2017-04-15 22:04:26 +02:00
|
|
|
if err != nil {
|
2017-04-23 21:42:34 +02:00
|
|
|
result.Tag = false
|
|
|
|
result.SHA, err = cleanGit("rev-list", "--max-parents=0", "HEAD")
|
2017-04-15 18:05:54 +02:00
|
|
|
}
|
2017-04-23 21:42:34 +02:00
|
|
|
return
|
2017-04-23 21:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type ref struct {
|
|
|
|
Tag bool
|
|
|
|
SHA string
|
2017-04-15 18:05:54 +02:00
|
|
|
}
|