1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-17 20:47:50 +02:00

Merge pull request #98 from goreleaser/tag-only

Always use latest tag as source
This commit is contained in:
Carlos Alexandro Becker 2017-01-20 19:02:50 -02:00 committed by GitHub
commit 0636aa8d8d
13 changed files with 161 additions and 32 deletions

35
main.go
View File

@ -15,6 +15,7 @@ import (
"github.com/goreleaser/goreleaser/pipeline/git"
"github.com/goreleaser/goreleaser/pipeline/release"
"github.com/goreleaser/goreleaser/pipeline/repos"
"github.com/goreleaser/goreleaser/pipeline/source"
"github.com/urfave/cli"
)
@ -27,6 +28,8 @@ var pipes = []pipeline.Pipe{
git.Pipe{},
repos.Pipe{},
&source.Pipe{},
// real work
build.Pipe{},
archive.Pipe{},
@ -46,27 +49,39 @@ func main() {
Value: "goreleaser.yml",
},
}
app.Action = func(c *cli.Context) (err error) {
app.Action = func(c *cli.Context) error {
var file = c.String("config")
cfg, err := config.Load(file)
// Allow failing to load the config file if file is not explicitly specified
if err != nil && c.IsSet("config") {
return cli.NewExitError(err.Error(), 1)
}
context := context.New(cfg)
ctx := context.New(cfg)
log.SetFlags(0)
for _, pipe := range pipes {
log.Println(pipe.Description())
log.SetPrefix(" -> ")
if err := pipe.Run(context); err != nil {
return cli.NewExitError(err.Error(), 1)
}
log.SetPrefix("")
if err := runPipeline(ctx); err != nil {
return cli.NewExitError(err.Error(), 1)
}
log.Println("Done!")
return
return nil
}
if err := app.Run(os.Args); err != nil {
log.Fatalln(err)
}
}
func runPipeline(ctx *context.Context) error {
for _, pipe := range pipes {
log.Println(pipe.Description())
log.SetPrefix(" -> ")
err := pipe.Run(ctx)
log.SetPrefix("")
cleaner, ok := pipe.(pipeline.Cleaner)
if ok {
defer cleaner.Clean(ctx)
}
if err != nil {
return err
}
}
return nil
}

View File

@ -17,7 +17,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Creating archives..."
return "Creating archives"
}
// Run the pipe
@ -41,7 +41,7 @@ type Archive interface {
func create(name string, ctx *context.Context) error {
folder := filepath.Join("dist", name)
file, err := os.Create(folder + "." + ctx.Config.Archive.Format)
log.Println("Creating", file.Name(), "...")
log.Println("Creating", file.Name())
if err != nil {
return err
}

View File

@ -18,7 +18,7 @@ import (
// contain darwin and/or goarch doesn't contain amd64)
var ErrNoDarwin64Build = errors.New("brew tap requires a darwin amd64 build")
const formulae = `class {{ .Name }} < Formula
const formula = `class {{ .Name }} < Formula
desc "{{ .Desc }}"
homepage "{{ .Homepage }}"
url "https://github.com/{{ .Repo }}/releases/download/{{ .Tag }}/{{ .File }}.{{ .Format }}"
@ -63,7 +63,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Creating homebrew formulae..."
return "Creating homebrew formula"
}
// Run the pipe
@ -76,8 +76,8 @@ func (Pipe) Run(ctx *context.Context) error {
ctx.Config.Brew.Folder, ctx.Config.Build.BinaryName+".rb",
)
log.Println("Updating", path, "on", ctx.Config.Brew.Repo, "...")
out, err := buildFormulae(ctx, client)
log.Println("Pushing", path, "to", ctx.Config.Brew.Repo)
out, err := buildFormula(ctx, client)
if err != nil {
return err
}
@ -107,17 +107,17 @@ func (Pipe) Run(ctx *context.Context) error {
return err
}
func buildFormulae(ctx *context.Context, client *github.Client) (bytes.Buffer, error) {
func buildFormula(ctx *context.Context, client *github.Client) (bytes.Buffer, error) {
data, err := dataFor(ctx, client)
if err != nil {
return bytes.Buffer{}, err
}
return doBuildFormulae(data)
return doBuildFormula(data)
}
func doBuildFormulae(data templateData) (bytes.Buffer, error) {
func doBuildFormula(data templateData) (bytes.Buffer, error) {
var out bytes.Buffer
tmpl, err := template.New(data.BinaryName).Parse(formulae)
tmpl, err := template.New(data.BinaryName).Parse(formula)
if err != nil {
return out, err
}

View File

@ -45,7 +45,7 @@ func TestFullFormulae(t *testing.T) {
data := defaultTemplateData
data.Caveats = "Here are some caveats"
data.Dependencies = []string{"gtk", "git"}
out, err := doBuildFormulae(data)
out, err := doBuildFormula(data)
assert.NoError(err)
formulae := out.String()
assertDefaultTemplateData(t, formulae)
@ -57,7 +57,7 @@ func TestFullFormulae(t *testing.T) {
func TestFormulaeNoCaveats(t *testing.T) {
assert := assert.New(t)
out, err := doBuildFormulae(defaultTemplateData)
out, err := doBuildFormula(defaultTemplateData)
assert.NoError(err)
formulae := out.String()
assertDefaultTemplateData(t, formulae)

View File

@ -16,7 +16,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Building..."
return "Building binaries"
}
// Run the pipe
@ -42,7 +42,7 @@ func (Pipe) Run(ctx *context.Context) error {
func build(name, goos, goarch string, ctx *context.Context) error {
ldflags := ctx.Config.Build.Ldflags + " -X main.version=" + ctx.Git.CurrentTag
output := "dist/" + name + "/" + ctx.Config.Build.BinaryName + extFor(goos)
log.Println("Building", output, "...")
log.Println("Building", output)
cmd := exec.Command(
"go",
"build",

10
pipeline/cleaner.go Normal file
View File

@ -0,0 +1,10 @@
package pipeline
import "github.com/goreleaser/goreleaser/context"
// Cleaner is an interface that a pipe can implement
// to cleanup after all pipes ran.
type Cleaner interface {
// Clean is called after pipeline is done - even if a pipe returned an error.
Clean(*context.Context)
}

View File

@ -15,7 +15,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Setting defaults..."
return "Setting defaults"
}
// Run the pipe

2
pipeline/env/env.go vendored
View File

@ -15,7 +15,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Loading data from environment variables..."
return "Loading environment variables"
}
// Run the pipe

View File

@ -7,7 +7,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Gathering Git data..."
return "Getting Git info"
}
// Run the pipe

View File

@ -16,7 +16,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Releasing to GitHub..."
return "Releasing to GitHub"
}
// Run the pipe
@ -48,11 +48,11 @@ func getOrCreateRelease(client *github.Client, ctx *context.Context) (*github.Re
}
r, _, err := client.Repositories.GetReleaseByTag(owner, repo, ctx.Git.CurrentTag)
if err != nil {
log.Println("Creating release", ctx.Git.CurrentTag, "on", ctx.Config.Release.Repo, "...")
log.Println("Creating release", ctx.Git.CurrentTag, "on", ctx.Config.Release.Repo)
r, _, err = client.Repositories.CreateRelease(owner, repo, data)
return r, err
}
log.Println("Updating existing release", ctx.Git.CurrentTag, "on", ctx.Config.Release.Repo, "...")
log.Println("Updating existing release", ctx.Git.CurrentTag, "on", ctx.Config.Release.Repo)
r, _, err = client.Repositories.EditRelease(owner, repo, *r.ID, data)
return r, err
}
@ -74,7 +74,7 @@ func upload(client *github.Client, releaseID int, archive string, ctx *context.C
return err
}
defer func() { _ = file.Close() }()
log.Println("Uploading", file.Name(), "...")
log.Println("Uploading", file.Name())
_, _, err = client.Repositories.UploadReleaseAsset(
ctx.ReleaseRepo.Owner,
ctx.ReleaseRepo.Name,

View File

@ -11,7 +11,7 @@ type Pipe struct{}
// Description of the pipe
func (Pipe) Description() string {
return "Filling repositories data..."
return "Setting repositories"
}
// Run the pipe
@ -31,5 +31,8 @@ func (Pipe) Run(ctx *context.Context) (err error) {
func split(pair string) (string, string) {
parts := strings.Split(pair, "/")
if len(parts) == 1 {
return parts[0], ""
}
return parts[0], parts[1]
}

View File

@ -11,4 +11,20 @@ func TestSplit(t *testing.T) {
a, b := split("a/b")
assert.Equal("a", a)
assert.Equal("b", b)
a, b = split("")
assert.Equal("", a)
assert.Equal("", b)
a, b = split("a")
assert.Equal("a", a)
assert.Equal("", b)
a, b = split("a/")
assert.Equal("a", a)
assert.Equal("", b)
a, b = split("/b")
assert.Equal("", a)
assert.Equal("b", b)
}

85
pipeline/source/source.go Normal file
View File

@ -0,0 +1,85 @@
// Package source provides pipes to take care of using the correct source files.
// For the releasing process we need the files of the tag we are releasing.
package source
import (
"bytes"
"errors"
"fmt"
"log"
"os/exec"
"github.com/goreleaser/goreleaser/context"
)
// Pipe to use the latest Git tag as source.
type Pipe struct {
dirty bool
wrongBranch bool
}
// Description of the pipe
func (p *Pipe) Description() string {
return "Using source from latest tag"
}
// Run uses the latest tag as source.
// Uncommitted changes are stashed.
func (p *Pipe) Run(ctx *context.Context) error {
cmd := exec.Command("git", "diff-index", "--quiet", "HEAD", "--")
err := cmd.Run()
dirty := err != nil
if dirty {
log.Println("Stashing changes")
if err = run("git", "stash", "--include-untracked", "--quiet"); err != nil {
return fmt.Errorf("failed stashing changes: %v", err)
}
}
p.dirty = dirty
cmd = exec.Command("git", "describe", "--exact-match", "--match", ctx.Git.CurrentTag)
err = cmd.Run()
wrongBranch := err != nil
if wrongBranch {
log.Println("Checking out tag", ctx.Git.CurrentTag)
if err = run("git", "checkout", ctx.Git.CurrentTag); err != nil {
return fmt.Errorf("failed changing branch: %v", err)
}
}
p.wrongBranch = wrongBranch
return nil
}
// Clean switches back to the original branch and restores changes.
func (p *Pipe) Clean(ctx *context.Context) {
if p.wrongBranch {
log.Println("Checking out original branch")
if err := run("git", "checkout", "-"); err != nil {
log.Println("failed changing branch: ", err.Error())
}
}
if p.dirty {
log.Println("Popping stashed changes")
if err := run("git", "stash", "pop"); err != nil {
log.Println("failed popping stashed changes:", err.Error())
}
}
}
func run(bin string, args ...string) error {
cmd := exec.Command(bin, args...)
var out bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &out
err := cmd.Run()
if err != nil {
return errors.New(out.String())
}
return nil
}