From 017541574c35e59d6048c528711a5edbadf73411 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Mon, 16 Jan 2017 14:52:27 -0200 Subject: [PATCH 01/15] fail brew pipe if there is no darwin_amd64 build --- pipeline/brew/brew.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pipeline/brew/brew.go b/pipeline/brew/brew.go index ca2247d40..034e65196 100644 --- a/pipeline/brew/brew.go +++ b/pipeline/brew/brew.go @@ -2,6 +2,7 @@ package brew import ( "bytes" + "errors" "log" "path/filepath" "strings" @@ -13,6 +14,10 @@ import ( "github.com/goreleaser/goreleaser/sha256sum" ) +// ErrNoDarwin64Build when there is no build for darwin_amd64 (goos doesn't +// 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 desc "{{ .Desc }}" homepage "{{ .Homepage }}" @@ -112,6 +117,9 @@ func dataFor(ctx *context.Context, client *github.Client) (result templateData, return } file := ctx.Archives["darwinamd64"] + if file == "" { + return result, ErrNoDarwin64Build + } sum, err := sha256sum.For("dist/" + file + "." + ctx.Config.Archive.Format) if err != nil { return From 6f98934788fab4e29635dacb85dd8495efda1f1d Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Mon, 16 Jan 2017 19:09:53 -0200 Subject: [PATCH 02/15] stop building goreleaser.exe it will probably not work on windows anyway (e.g.: calling `git` instead of `git.exe`). The get/latest script also won't work on Windows. For me, we can assume that this don't work and that's it... --- goreleaser.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/goreleaser.yml b/goreleaser.yml index a9f4dadc0..bf22c7978 100644 --- a/goreleaser.yml +++ b/goreleaser.yml @@ -1,11 +1,6 @@ brew: repo: goreleaser/homebrew-tap folder: Formula -build: - goos: - - windows - - darwin - - linux archive: files: - README.md From b6d1b56a04bc21eaa246096d0d68d58994cfd801 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Tue, 17 Jan 2017 08:33:43 -0200 Subject: [PATCH 03/15] added brew dependencies support --- config/config.go | 7 ++++--- goreleaser.example.yml | 11 +++++++++++ pipeline/brew/brew.go | 39 +++++++++++++++++++++++++++----------- pipeline/brew/brew_test.go | 5 ++++- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/config/config.go b/config/config.go index 30faf8777..1ff97ee08 100644 --- a/config/config.go +++ b/config/config.go @@ -8,9 +8,10 @@ import ( // Homebrew contains the brew section type Homebrew struct { - Repo string - Folder string - Caveats string + Repo string + Folder string + Caveats string + Dependencies []string } // Build contains the build configuration section diff --git a/goreleaser.example.yml b/goreleaser.example.yml index 2a27c6f1e..781a22215 100644 --- a/goreleaser.example.yml +++ b/goreleaser.example.yml @@ -81,3 +81,14 @@ brew: # Caveats for the user of your binary. # Default is empty. caveats: "How to use this binary" + + # Dependencies of your formula. + # For more info, check https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md + dependencies: + - pkg-config + - jpeg + - boost + - readline + - gtk+ + - x11 + diff --git a/pipeline/brew/brew.go b/pipeline/brew/brew.go index 034e65196..ef3b8ea29 100644 --- a/pipeline/brew/brew.go +++ b/pipeline/brew/brew.go @@ -25,6 +25,12 @@ const formulae = `class {{ .Name }} < Formula version "{{ .Tag }}" sha256 "{{ .SHA256 }}" + {{- if .Dependencies }} + {{ range $index, $element := .Dependencies }} + depends_on: {{ . }} + {{- end }} + {{- end }} + def install bin.install "{{ .BinaryName }}" end @@ -39,7 +45,17 @@ end ` type templateData struct { - Name, Desc, Homepage, Repo, Tag, BinaryName, Caveats, File, Format, SHA256 string + Name string + Desc string + Homepage string + Repo string + Tag string + BinaryName string + Caveats string + File string + Format string + SHA256 string + Dependencies []string } // Pipe for brew deployment @@ -135,16 +151,17 @@ func dataFor(ctx *context.Context, client *github.Client) (result templateData, description = *rep.Description } return templateData{ - Name: formulaNameFor(ctx.Config.Build.BinaryName), - Desc: description, - Homepage: homepage, - Repo: ctx.Config.Release.Repo, - Tag: ctx.Git.CurrentTag, - BinaryName: ctx.Config.Build.BinaryName, - Caveats: ctx.Config.Brew.Caveats, - File: file, - Format: ctx.Config.Archive.Format, - SHA256: sum, + Name: formulaNameFor(ctx.Config.Build.BinaryName), + Desc: description, + Homepage: homepage, + Repo: ctx.Config.Release.Repo, + Tag: ctx.Git.CurrentTag, + BinaryName: ctx.Config.Build.BinaryName, + Caveats: ctx.Config.Brew.Caveats, + File: file, + Format: ctx.Config.Archive.Format, + SHA256: sum, + Dependencies: ctx.Config.Brew.Dependencies, }, err } diff --git a/pipeline/brew/brew_test.go b/pipeline/brew/brew_test.go index 16c2603a7..84806b595 100644 --- a/pipeline/brew/brew_test.go +++ b/pipeline/brew/brew_test.go @@ -38,19 +38,21 @@ func assertDefaultTemplateData(t *testing.T, formulae string) { assert.Contains(formulae, "sha256 \"1633f61598ab0791e213135923624eb342196b3494909c91899bcd0560f84c68\"") assert.Contains(formulae, "version \"v0.1.3\"") assert.Contains(formulae, "bin.install \"test\"") - } func TestFullFormulae(t *testing.T) { assert := assert.New(t) data := defaultTemplateData data.Caveats = "Here are some caveats" + data.Dependencies = []string{"gtk", "git"} out, err := doBuildFormulae(data) assert.NoError(err) formulae := out.String() assertDefaultTemplateData(t, formulae) assert.Contains(formulae, "def caveats") assert.Contains(formulae, "Here are some caveats") + assert.Contains(formulae, "depends_on: gtk") + assert.Contains(formulae, "depends_on: git") } func TestFormulaeNoCaveats(t *testing.T) { @@ -60,4 +62,5 @@ func TestFormulaeNoCaveats(t *testing.T) { formulae := out.String() assertDefaultTemplateData(t, formulae) assert.NotContains(formulae, "def caveats") + assert.NotContains(formulae, "depends_on") } From c72cd3095f81d50ae4f87e64bb826a31c9355323 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Tue, 17 Jan 2017 10:31:11 -0200 Subject: [PATCH 04/15] Update CONTRIBUTING.md a more fail-proof way of cloning the project. --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b8ea7c958..7ee656a76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,8 +16,8 @@ Prerequisites are: Clone `releaser` from source: ```sh -$ git clone https://github.com/goreleaser/goreleaser.git -$ cd releaser +$ go get github.com/goreleaser/goreleaser +$ cd $GOPATH/src/github.com/goreleaser/goreleaser ``` Install the build and lint dependencies: From fcd1d92075be0b3aced1807a7d16230f103b97fd Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Tue, 17 Jan 2017 10:47:34 -0200 Subject: [PATCH 05/15] Update CONTRIBUTING.md --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7ee656a76..0b0475772 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ conduct](/CODE_OF_CONDUCT.md). ## Setup your machine -`releaser` is written in [Go](https://golang.org/). +`goreleaser` is written in [Go](https://golang.org/). Prerequisites are: @@ -13,7 +13,7 @@ Prerequisites are: * `make` * [Go 1.7+](http://golang.org/doc/install) -Clone `releaser` from source: +Clone `goreleaser` from source into `$GOPATH`: ```sh $ go get github.com/goreleaser/goreleaser @@ -50,5 +50,5 @@ Which runs all the linters and tests. ## Submit a pull request -Push your branch to your `releaser` fork and open a pull request against the +Push your branch to your `goreleaser` fork and open a pull request against the master branch. From 656828ea415433a144da65c654d8b33049a09ff6 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Tue, 17 Jan 2017 11:29:10 -0200 Subject: [PATCH 06/15] brew depends on git It calls the `git` binary to get tags and logs. I think it's valid to add git as a dependency since now it is supported. --- goreleaser.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/goreleaser.yml b/goreleaser.yml index bf22c7978..d955edf1c 100644 --- a/goreleaser.yml +++ b/goreleaser.yml @@ -1,6 +1,8 @@ brew: repo: goreleaser/homebrew-tap folder: Formula + dependencies: + - git archive: files: - README.md From 76926a402df1e3afdbe77fd521a318f81f187677 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Tue, 17 Jan 2017 15:38:46 -0200 Subject: [PATCH 07/15] missing quotes on formulae with dependencies fixes https://github.com/goreleaser/goreleaser/issues/86#issuecomment-273221892 --- pipeline/brew/brew.go | 2 +- pipeline/brew/brew_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pipeline/brew/brew.go b/pipeline/brew/brew.go index ef3b8ea29..d2f67ee8e 100644 --- a/pipeline/brew/brew.go +++ b/pipeline/brew/brew.go @@ -27,7 +27,7 @@ const formulae = `class {{ .Name }} < Formula {{- if .Dependencies }} {{ range $index, $element := .Dependencies }} - depends_on: {{ . }} + depends_on: "{{ . }}" {{- end }} {{- end }} diff --git a/pipeline/brew/brew_test.go b/pipeline/brew/brew_test.go index 84806b595..dd1051210 100644 --- a/pipeline/brew/brew_test.go +++ b/pipeline/brew/brew_test.go @@ -51,8 +51,8 @@ func TestFullFormulae(t *testing.T) { assertDefaultTemplateData(t, formulae) assert.Contains(formulae, "def caveats") assert.Contains(formulae, "Here are some caveats") - assert.Contains(formulae, "depends_on: gtk") - assert.Contains(formulae, "depends_on: git") + assert.Contains(formulae, "depends_on: \"gtk\"") + assert.Contains(formulae, "depends_on: \"git\"") } func TestFormulaeNoCaveats(t *testing.T) { From aa1699747e10d5ffbc8491afe10c36e301e2a7f1 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Tue, 17 Jan 2017 15:44:32 -0200 Subject: [PATCH 08/15] remove : from depends_on refs https://github.com/goreleaser/goreleaser/issues/86#issuecomment-273221892 --- pipeline/brew/brew.go | 2 +- pipeline/brew/brew_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pipeline/brew/brew.go b/pipeline/brew/brew.go index d2f67ee8e..9af6010d7 100644 --- a/pipeline/brew/brew.go +++ b/pipeline/brew/brew.go @@ -27,7 +27,7 @@ const formulae = `class {{ .Name }} < Formula {{- if .Dependencies }} {{ range $index, $element := .Dependencies }} - depends_on: "{{ . }}" + depends_on "{{ . }}" {{- end }} {{- end }} diff --git a/pipeline/brew/brew_test.go b/pipeline/brew/brew_test.go index dd1051210..d8f34d865 100644 --- a/pipeline/brew/brew_test.go +++ b/pipeline/brew/brew_test.go @@ -51,8 +51,8 @@ func TestFullFormulae(t *testing.T) { assertDefaultTemplateData(t, formulae) assert.Contains(formulae, "def caveats") assert.Contains(formulae, "Here are some caveats") - assert.Contains(formulae, "depends_on: \"gtk\"") - assert.Contains(formulae, "depends_on: \"git\"") + assert.Contains(formulae, "depends_on \"gtk\"") + assert.Contains(formulae, "depends_on \"git\"") } func TestFormulaeNoCaveats(t *testing.T) { From e8ab2b2fe29ebc017eece8cc6ec2f3feac38dfbf Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Wed, 18 Jan 2017 15:08:48 -0200 Subject: [PATCH 09/15] removed unneeded pointers from context --- context/context.go | 12 ++++----- pipeline/brew/brew.go | 2 +- pipeline/build/name_test.go | 4 +-- pipeline/defaults/defaults_test.go | 42 ++++++++++++++---------------- pipeline/env/env.go | 5 ++-- pipeline/git/git.go | 2 +- pipeline/release/release.go | 2 +- pipeline/repos/repos.go | 4 +-- 8 files changed, 35 insertions(+), 38 deletions(-) diff --git a/context/context.go b/context/context.go index 844fcb13e..a474287f1 100644 --- a/context/context.go +++ b/context/context.go @@ -16,18 +16,18 @@ type Repo struct { // Context carries along some data through the pipes type Context struct { - Config *config.Project - Token *string - Git *GitInfo - ReleaseRepo *Repo - BrewRepo *Repo + Config config.Project + Token string + Git GitInfo + ReleaseRepo Repo + BrewRepo Repo Archives map[string]string } // New context func New(config config.Project) *Context { return &Context{ - Config: &config, + Config: config, Archives: map[string]string{}, } } diff --git a/pipeline/brew/brew.go b/pipeline/brew/brew.go index 9af6010d7..a9a063792 100644 --- a/pipeline/brew/brew.go +++ b/pipeline/brew/brew.go @@ -71,7 +71,7 @@ func (Pipe) Run(ctx *context.Context) error { if ctx.Config.Brew.Repo == "" { return nil } - client := clients.GitHub(*ctx.Token) + client := clients.GitHub(ctx.Token) path := filepath.Join( ctx.Config.Brew.Folder, ctx.Config.Build.BinaryName+".rb", ) diff --git a/pipeline/build/name_test.go b/pipeline/build/name_test.go index a56c065d1..b6f5c1c81 100644 --- a/pipeline/build/name_test.go +++ b/pipeline/build/name_test.go @@ -19,7 +19,7 @@ func TestExtOthers(t *testing.T) { func TestNameFor(t *testing.T) { assert := assert.New(t) - var config = &config.Project{ + var config = config.Project{ Archive: config.Archive{ NameTemplate: "{{.BinaryName}}_{{.Os}}_{{.Arch}}_{{.Version}}", Replacements: map[string]string{ @@ -33,7 +33,7 @@ func TestNameFor(t *testing.T) { } var ctx = &context.Context{ Config: config, - Git: &context.GitInfo{ + Git: context.GitInfo{ CurrentTag: "v1.2.3", }, } diff --git a/pipeline/defaults/defaults_test.go b/pipeline/defaults/defaults_test.go index 9b4cc528f..b3cc43936 100644 --- a/pipeline/defaults/defaults_test.go +++ b/pipeline/defaults/defaults_test.go @@ -11,45 +11,43 @@ import ( func TestFillBasicData(t *testing.T) { assert := assert.New(t) - var config = &config.Project{} var ctx = &context.Context{ - Config: config, + Config: config.Project{}, } assert.NoError(Pipe{}.Run(ctx)) - assert.Equal("goreleaser/goreleaser", config.Release.Repo) - assert.Equal("goreleaser", config.Build.BinaryName) - assert.Equal("main.go", config.Build.Main) - assert.Equal("tar.gz", config.Archive.Format) - assert.Contains(config.Build.Goos, "darwin") - assert.Contains(config.Build.Goos, "linux") - assert.Contains(config.Build.Goarch, "386") - assert.Contains(config.Build.Goarch, "amd64") + assert.Equal("goreleaser/goreleaser", ctx.Config.Release.Repo) + assert.Equal("goreleaser", ctx.Config.Build.BinaryName) + assert.Equal("main.go", ctx.Config.Build.Main) + assert.Equal("tar.gz", ctx.Config.Archive.Format) + assert.Contains(ctx.Config.Build.Goos, "darwin") + assert.Contains(ctx.Config.Build.Goos, "linux") + assert.Contains(ctx.Config.Build.Goarch, "386") + assert.Contains(ctx.Config.Build.Goarch, "amd64") assert.NotEmpty( - config.Archive.Replacements, - config.Archive.NameTemplate, - config.Build.Ldflags, - config.Archive.Files, + ctx.Config.Archive.Replacements, + ctx.Config.Archive.NameTemplate, + ctx.Config.Build.Ldflags, + ctx.Config.Archive.Files, ) } func TestFilesFilled(t *testing.T) { assert := assert.New(t) - var config = &config.Project{ - Archive: config.Archive{ - Files: []string{ - "README.md", + var ctx = &context.Context{ + Config: config.Project{ + Archive: config.Archive{ + Files: []string{ + "README.md", + }, }, }, } - var ctx = &context.Context{ - Config: config, - } assert.NoError(Pipe{}.Run(ctx)) - assert.Len(config.Archive.Files, 1) + assert.Len(ctx.Config.Archive.Files, 1) } func TestAcceptFiles(t *testing.T) { diff --git a/pipeline/env/env.go b/pipeline/env/env.go index bd5a011a1..98dcdea96 100644 --- a/pipeline/env/env.go +++ b/pipeline/env/env.go @@ -20,10 +20,9 @@ func (Pipe) Description() string { // Run the pipe func (Pipe) Run(ctx *context.Context) (err error) { - token := os.Getenv("GITHUB_TOKEN") - if token == "" { + ctx.Token = os.Getenv("GITHUB_TOKEN") + if ctx.Token == "" { return ErrMissingToken } - ctx.Token = &token return } diff --git a/pipeline/git/git.go b/pipeline/git/git.go index d935d2151..9ebdd9562 100644 --- a/pipeline/git/git.go +++ b/pipeline/git/git.go @@ -25,7 +25,7 @@ func (Pipe) Run(ctx *context.Context) (err error) { return } - ctx.Git = &context.GitInfo{ + ctx.Git = context.GitInfo{ CurrentTag: tag, PreviousTag: previous, Diff: log, diff --git a/pipeline/release/release.go b/pipeline/release/release.go index 583a38a93..9fe41f358 100644 --- a/pipeline/release/release.go +++ b/pipeline/release/release.go @@ -21,7 +21,7 @@ func (Pipe) Description() string { // Run the pipe func (Pipe) Run(ctx *context.Context) error { - client := clients.GitHub(*ctx.Token) + client := clients.GitHub(ctx.Token) r, err := getOrCreateRelease(client, ctx) if err != nil { diff --git a/pipeline/repos/repos.go b/pipeline/repos/repos.go index 20740a5f6..444622f94 100644 --- a/pipeline/repos/repos.go +++ b/pipeline/repos/repos.go @@ -17,12 +17,12 @@ func (Pipe) Description() string { // Run the pipe func (Pipe) Run(ctx *context.Context) (err error) { owner, name := split(ctx.Config.Release.Repo) - ctx.ReleaseRepo = &context.Repo{ + ctx.ReleaseRepo = context.Repo{ Owner: owner, Name: name, } owner, name = split(ctx.Config.Brew.Repo) - ctx.BrewRepo = &context.Repo{ + ctx.BrewRepo = context.Repo{ Owner: owner, Name: name, } From 9982ad7bafeeea99b56d503985961875266dc6e9 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Wed, 18 Jan 2017 15:45:42 -0200 Subject: [PATCH 10/15] fixed name on --help --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 5ee0697d2..64af175fb 100644 --- a/main.go +++ b/main.go @@ -36,7 +36,7 @@ var pipes = []pipeline.Pipe{ func main() { var app = cli.NewApp() - app.Name = "release" + app.Name = "goreleaser" app.Version = version app.Usage = "Deliver Go binaries as fast and easily as possible" app.Flags = []cli.Flag{ From 22dd16df81be895f9767516bfd93645e8e13cc77 Mon Sep 17 00:00:00 2001 From: Jorin Vogel Date: Thu, 19 Jan 2017 09:05:20 +0100 Subject: [PATCH 11/15] Fix parsing of repo options. Before this it break when leaving, for example, the `brew` section empty. --- pipeline/repos/repos.go | 3 +++ pipeline/repos/repos_test.go | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/pipeline/repos/repos.go b/pipeline/repos/repos.go index 20740a5f6..b709b45ea 100644 --- a/pipeline/repos/repos.go +++ b/pipeline/repos/repos.go @@ -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] } diff --git a/pipeline/repos/repos_test.go b/pipeline/repos/repos_test.go index 6c21c4706..e6e69b2ae 100644 --- a/pipeline/repos/repos_test.go +++ b/pipeline/repos/repos_test.go @@ -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) } From 655e64b4bf4c64443cba86d3a179c5bc9b6d5cfa Mon Sep 17 00:00:00 2001 From: Jorin Vogel Date: Thu, 19 Jan 2017 09:47:17 +0100 Subject: [PATCH 12/15] Always use latest tag as source. Fixes #72. Stash local changes and checkout tag before building and releasing. Added a Cleaner interface to revert repo to original state after. Clean is even called after errors. Source pipe is implemented as pointer to store local state. --- main.go | 35 ++++++++++----- pipeline/cleaner.go | 10 +++++ pipeline/source/source.go | 89 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 pipeline/cleaner.go create mode 100644 pipeline/source/source.go diff --git a/main.go b/main.go index 5ee0697d2..66043c024 100644 --- a/main.go +++ b/main.go @@ -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 +} diff --git a/pipeline/cleaner.go b/pipeline/cleaner.go new file mode 100644 index 000000000..603eb71b4 --- /dev/null +++ b/pipeline/cleaner.go @@ -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) +} diff --git a/pipeline/source/source.go b/pipeline/source/source.go new file mode 100644 index 000000000..7ffd41454 --- /dev/null +++ b/pipeline/source/source.go @@ -0,0 +1,89 @@ +// 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" + "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. +// Uncommited 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...") + cmd = exec.Command("git", "stash", "--include-untracked", "--quiet") + var stdout bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stdout + err = cmd.Run() + if err != nil { + return fmt.Errorf("failed stashing changes: %s", stdout.String()) + } + } + + 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...") + cmd = exec.Command("git", "checkout", ctx.Git.CurrentTag) + var stdout bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stdout + if err = cmd.Run(); err != nil { + return fmt.Errorf("failed changing branch: %s", stdout.String()) + } + } + + 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...") + cmd := exec.Command("git", "checkout", "-") + var stdout bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stdout + if err := cmd.Run(); err != nil { + log.Printf("failed changing branch: %s\n", stdout.String()) + } + } + + if p.dirty { + log.Println("Popping stashed changes...") + cmd := exec.Command("git", "stash", "pop") + var stdout bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stdout + if err := cmd.Run(); err != nil { + log.Printf("failed popping stashed changes: %s\n", stdout.String()) + } + } +} From 6677571e8c78c25ba8fa942b9ddb5f828cbe96ab Mon Sep 17 00:00:00 2001 From: Jorin Vogel Date: Thu, 19 Jan 2017 10:04:41 +0100 Subject: [PATCH 13/15] Clean logging output --- pipeline/archive/archive.go | 4 ++-- pipeline/brew/brew.go | 16 ++++++++-------- pipeline/brew/brew_test.go | 4 ++-- pipeline/build/build.go | 4 ++-- pipeline/defaults/defaults.go | 2 +- pipeline/env/env.go | 2 +- pipeline/git/git.go | 2 +- pipeline/release/release.go | 8 ++++---- pipeline/repos/repos.go | 2 +- pipeline/source/source.go | 10 +++++----- 10 files changed, 27 insertions(+), 27 deletions(-) diff --git a/pipeline/archive/archive.go b/pipeline/archive/archive.go index fcd9aa9dd..4cec85c2b 100644 --- a/pipeline/archive/archive.go +++ b/pipeline/archive/archive.go @@ -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 } diff --git a/pipeline/brew/brew.go b/pipeline/brew/brew.go index 9af6010d7..e0aedb19a 100644 --- a/pipeline/brew/brew.go +++ b/pipeline/brew/brew.go @@ -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 } diff --git a/pipeline/brew/brew_test.go b/pipeline/brew/brew_test.go index d8f34d865..f9dca51f8 100644 --- a/pipeline/brew/brew_test.go +++ b/pipeline/brew/brew_test.go @@ -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) diff --git a/pipeline/build/build.go b/pipeline/build/build.go index 908033821..e156e79ea 100644 --- a/pipeline/build/build.go +++ b/pipeline/build/build.go @@ -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", diff --git a/pipeline/defaults/defaults.go b/pipeline/defaults/defaults.go index cc5f022a6..d1b454c4f 100644 --- a/pipeline/defaults/defaults.go +++ b/pipeline/defaults/defaults.go @@ -15,7 +15,7 @@ type Pipe struct{} // Description of the pipe func (Pipe) Description() string { - return "Setting defaults..." + return "Setting defaults" } // Run the pipe diff --git a/pipeline/env/env.go b/pipeline/env/env.go index bd5a011a1..015a9f3fe 100644 --- a/pipeline/env/env.go +++ b/pipeline/env/env.go @@ -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 diff --git a/pipeline/git/git.go b/pipeline/git/git.go index d935d2151..e560a1df2 100644 --- a/pipeline/git/git.go +++ b/pipeline/git/git.go @@ -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 diff --git a/pipeline/release/release.go b/pipeline/release/release.go index 583a38a93..b2fa71db0 100644 --- a/pipeline/release/release.go +++ b/pipeline/release/release.go @@ -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, diff --git a/pipeline/repos/repos.go b/pipeline/repos/repos.go index b709b45ea..3ee795afb 100644 --- a/pipeline/repos/repos.go +++ b/pipeline/repos/repos.go @@ -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 diff --git a/pipeline/source/source.go b/pipeline/source/source.go index 7ffd41454..4a3ce1f3f 100644 --- a/pipeline/source/source.go +++ b/pipeline/source/source.go @@ -19,7 +19,7 @@ type Pipe struct { // Description of the pipe func (p *Pipe) Description() string { - return "Using source from latest tag..." + return "Using source from latest tag" } // Run uses the latest tag as source. @@ -30,7 +30,7 @@ func (p *Pipe) Run(ctx *context.Context) error { dirty := err != nil if dirty { - log.Println("Stashing changes...") + log.Println("Stashing changes") cmd = exec.Command("git", "stash", "--include-untracked", "--quiet") var stdout bytes.Buffer cmd.Stdout = &stdout @@ -48,7 +48,7 @@ func (p *Pipe) Run(ctx *context.Context) error { wrongBranch := err != nil if wrongBranch { - log.Println("Checking out tag...") + log.Println("Checking out tag") cmd = exec.Command("git", "checkout", ctx.Git.CurrentTag) var stdout bytes.Buffer cmd.Stdout = &stdout @@ -66,7 +66,7 @@ func (p *Pipe) Run(ctx *context.Context) error { // 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...") + log.Println("Checking out original branch") cmd := exec.Command("git", "checkout", "-") var stdout bytes.Buffer cmd.Stdout = &stdout @@ -77,7 +77,7 @@ func (p *Pipe) Clean(ctx *context.Context) { } if p.dirty { - log.Println("Popping stashed changes...") + log.Println("Popping stashed changes") cmd := exec.Command("git", "stash", "pop") var stdout bytes.Buffer cmd.Stdout = &stdout From d338caefc8edc1d45d0cc877a16fb57d9d6cb5af Mon Sep 17 00:00:00 2001 From: Jorin Vogel Date: Thu, 19 Jan 2017 10:24:04 +0100 Subject: [PATCH 14/15] Cleaning up duplicated code. --- pipeline/source/source.go | 48 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/pipeline/source/source.go b/pipeline/source/source.go index 4a3ce1f3f..3731cc58d 100644 --- a/pipeline/source/source.go +++ b/pipeline/source/source.go @@ -4,6 +4,7 @@ package source import ( "bytes" + "errors" "fmt" "log" "os/exec" @@ -23,7 +24,7 @@ func (p *Pipe) Description() string { } // Run uses the latest tag as source. -// Uncommited changes are stashed. +// Uncommitted changes are stashed. func (p *Pipe) Run(ctx *context.Context) error { cmd := exec.Command("git", "diff-index", "--quiet", "HEAD", "--") err := cmd.Run() @@ -31,13 +32,8 @@ func (p *Pipe) Run(ctx *context.Context) error { if dirty { log.Println("Stashing changes") - cmd = exec.Command("git", "stash", "--include-untracked", "--quiet") - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout - err = cmd.Run() - if err != nil { - return fmt.Errorf("failed stashing changes: %s", stdout.String()) + if err = run("git", "stash", "--include-untracked", "--quiet"); err != nil { + return fmt.Errorf("failed stashing changes: %v", err) } } @@ -49,12 +45,8 @@ func (p *Pipe) Run(ctx *context.Context) error { if wrongBranch { log.Println("Checking out tag") - cmd = exec.Command("git", "checkout", ctx.Git.CurrentTag) - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout - if err = cmd.Run(); err != nil { - return fmt.Errorf("failed changing branch: %s", stdout.String()) + if err = run("git", "checkout", ctx.Git.CurrentTag); err != nil { + return fmt.Errorf("failed changing branch: %v", err) } } @@ -67,23 +59,27 @@ func (p *Pipe) Run(ctx *context.Context) error { func (p *Pipe) Clean(ctx *context.Context) { if p.wrongBranch { log.Println("Checking out original branch") - cmd := exec.Command("git", "checkout", "-") - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout - if err := cmd.Run(); err != nil { - log.Printf("failed changing branch: %s\n", stdout.String()) + if err := run("git", "checkout", "-"); err != nil { + log.Println("failed changing branch: ", err.Error()) } } if p.dirty { log.Println("Popping stashed changes") - cmd := exec.Command("git", "stash", "pop") - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout - if err := cmd.Run(); err != nil { - log.Printf("failed popping stashed changes: %s\n", stdout.String()) + 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 +} From b8d24c79c6b2aff64715e6a5de33ed91cb82f245 Mon Sep 17 00:00:00 2001 From: Jorin Vogel Date: Thu, 19 Jan 2017 10:30:15 +0100 Subject: [PATCH 15/15] Log used tag --- pipeline/source/source.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipeline/source/source.go b/pipeline/source/source.go index 3731cc58d..2a08063ea 100644 --- a/pipeline/source/source.go +++ b/pipeline/source/source.go @@ -44,7 +44,7 @@ func (p *Pipe) Run(ctx *context.Context) error { wrongBranch := err != nil if wrongBranch { - log.Println("Checking out tag") + 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) }