github.com/elyscape/goreleaser@v0.66.1-0.20180515111211-5252f74ade63/pipeline/git/git.go (about) 1 package git 2 3 import ( 4 "bytes" 5 "fmt" 6 "regexp" 7 "strings" 8 "text/template" 9 "time" 10 11 "github.com/apex/log" 12 "github.com/goreleaser/goreleaser/context" 13 "github.com/goreleaser/goreleaser/internal/git" 14 "github.com/goreleaser/goreleaser/pipeline" 15 "github.com/pkg/errors" 16 ) 17 18 // Pipe for brew deployment 19 type Pipe struct{} 20 21 func (Pipe) String() string { 22 return "getting and validating git state" 23 } 24 25 // Run the pipe 26 func (Pipe) Run(ctx *context.Context) error { 27 info, err := getInfo(ctx) 28 if err != nil { 29 return err 30 } 31 ctx.Git = info 32 log.Infof("releasing %s, commit %s", info.CurrentTag, info.Commit) 33 if err := setVersion(ctx); err != nil { 34 return err 35 } 36 return validate(ctx) 37 } 38 39 var fakeInfo = context.GitInfo{ 40 CurrentTag: "v0.0.0", 41 Commit: "none", 42 } 43 44 func getInfo(ctx *context.Context) (context.GitInfo, error) { 45 if !git.IsRepo() && ctx.Snapshot { 46 log.Warn("accepting to run without a git repo because this is a snapshot") 47 return fakeInfo, nil 48 } 49 if !git.IsRepo() { 50 return context.GitInfo{}, ErrNotRepository 51 } 52 info, err := getGitInfo(ctx) 53 if err != nil && ctx.Snapshot { 54 log.WithError(err).Warn("ignoring errors because this is a snapshot") 55 if info.Commit == "" { 56 info = fakeInfo 57 } 58 return info, nil 59 } 60 return info, err 61 } 62 63 func getGitInfo(ctx *context.Context) (context.GitInfo, error) { 64 commit, err := getCommit(ctx) 65 if err != nil { 66 return context.GitInfo{}, errors.Wrap(err, "couldn't get current commit") 67 } 68 tag, err := getTag() 69 if err != nil { 70 return context.GitInfo{ 71 Commit: commit, 72 CurrentTag: "v0.0.0", 73 }, ErrNoTag 74 } 75 return context.GitInfo{ 76 CurrentTag: tag, 77 Commit: commit, 78 }, nil 79 } 80 81 func setVersion(ctx *context.Context) error { 82 if ctx.Snapshot { 83 snapshotName, err := getSnapshotName(ctx) 84 if err != nil { 85 return errors.Wrap(err, "failed to generate snapshot name") 86 } 87 ctx.Version = snapshotName 88 return nil 89 } 90 // removes usual `v` prefix 91 ctx.Version = strings.TrimPrefix(ctx.Git.CurrentTag, "v") 92 return nil 93 } 94 95 type snapshotNameData struct { 96 Commit string 97 Tag string 98 Timestamp int64 99 } 100 101 func getSnapshotName(ctx *context.Context) (string, error) { 102 tmpl, err := template.New("snapshot").Parse(ctx.Config.Snapshot.NameTemplate) 103 var out bytes.Buffer 104 if err != nil { 105 return "", err 106 } 107 var data = snapshotNameData{ 108 Commit: ctx.Git.Commit, 109 Tag: ctx.Git.CurrentTag, 110 Timestamp: time.Now().Unix(), 111 } 112 err = tmpl.Execute(&out, data) 113 return out.String(), err 114 } 115 116 func validate(ctx *context.Context) error { 117 if ctx.Snapshot { 118 return pipeline.ErrSnapshotEnabled 119 } 120 if ctx.SkipValidate { 121 return pipeline.ErrSkipValidateEnabled 122 } 123 out, err := git.Run("status", "--porcelain") 124 if strings.TrimSpace(out) != "" || err != nil { 125 return ErrDirty{out} 126 } 127 if !regexp.MustCompile("^[0-9.]+").MatchString(ctx.Version) { 128 return ErrInvalidVersionFormat{ctx.Version} 129 } 130 _, err = git.Clean(git.Run("describe", "--exact-match", "--tags", "--match", ctx.Git.CurrentTag)) 131 if err != nil { 132 return ErrWrongRef{ctx.Git.Commit, ctx.Git.CurrentTag} 133 } 134 return nil 135 } 136 137 func getCommit(ctx *context.Context) (string, error) { 138 format := "%H" 139 if ctx.Config.Git.ShortHash { 140 format = "%h" 141 } 142 return git.Clean(git.Run("show", fmt.Sprintf("--format='%s'", format), "HEAD")) 143 } 144 145 func getTag() (string, error) { 146 return git.Clean(git.Run("describe", "--tags", "--abbrev=0")) 147 }