From dc7b9c6852d66a2ebe806f3ca6da102e9fecb230 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Fri, 21 Apr 2017 15:25:32 -0300 Subject: [PATCH 1/2] covered main cli action with tests --- .gitignore | 1 + .travis.yml | 4 +- Makefile | 3 +- cmd/goreleaser/main.go | 51 ++++++++++++++ goreleaser.go | 79 ++++++++++++++++++++++ goreleaser.yml | 2 + goreleaser_test.go | 147 +++++++++++++++++++++++++++++++++++++++++ main.go | 107 ------------------------------ 8 files changed, 284 insertions(+), 110 deletions(-) create mode 100644 cmd/goreleaser/main.go create mode 100644 goreleaser.go create mode 100644 goreleaser_test.go delete mode 100644 main.go diff --git a/.gitignore b/.gitignore index 8b37d3196..fcf20b78c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ dist/ vendor goreleaser +!cmd/goreleaser .glide/ coverage.out diff --git a/.travis.yml b/.travis.yml index c71ec817f..26da8abbe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ install: - gem install fpm script: - make test - - go run main.go --skip-validate --skip-publish + - go run ./cmd/goreleaser/main.go --skip-validate --skip-publish after_success: - go get github.com/mattn/goveralls - goveralls -coverprofile=coverage.out -service=travis-ci -repotoken="$COVERALLS_TOKEN" - - test -n "$TRAVIS_TAG" && go run main.go + - test -n "$TRAVIS_TAG" && go run ./cmd/goreleaser/main.go notifications: email: false diff --git a/Makefile b/Makefile index de939c966..8c00c3b65 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,8 @@ lint: ## Run all the linters ci: lint test ## Run all the tests and code checks build: ## Build a beta version of releaser - go build + go build -o goreleaser ./cmd/goreleaser/main.go + # Absolutely awesome: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html help: diff --git a/cmd/goreleaser/main.go b/cmd/goreleaser/main.go new file mode 100644 index 000000000..e327bcf61 --- /dev/null +++ b/cmd/goreleaser/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "log" + "os" + + "github.com/goreleaser/goreleaser" + "github.com/urfave/cli" +) + +var ( + version = "dev" + commit = "none" + date = "unknown" +) + +func main() { + var app = cli.NewApp() + app.Name = "goreleaser" + app.Version = version + ", commit " + commit + ", built at " + date + app.Usage = "Deliver Go binaries as fast and easily as possible" + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "config, file, c, f", + Usage: "Load configuration from `FILE`", + Value: "goreleaser.yml", + }, + cli.StringFlag{ + Name: "release-notes", + Usage: "Load custom release notes from a markdown `FILE`", + }, + cli.BoolFlag{ + Name: "skip-validate", + Usage: "Skip all the validations against the release", + }, + cli.BoolFlag{ + Name: "skip-publish", + Usage: "Skip all publishing pipes of the release", + }, + } + app.Action = func(c *cli.Context) error { + log.Printf("Running goreleaser %v\n", version) + if err := goreleaser.Release(c); err != nil { + return cli.NewExitError(err.Error(), 1) + } + return nil + } + if err := app.Run(os.Args); err != nil { + log.Fatalln(err) + } +} diff --git a/goreleaser.go b/goreleaser.go new file mode 100644 index 000000000..50dbf82d7 --- /dev/null +++ b/goreleaser.go @@ -0,0 +1,79 @@ +package goreleaser + +import ( + "io/ioutil" + "log" + "os" + + "github.com/goreleaser/goreleaser/config" + "github.com/goreleaser/goreleaser/context" + "github.com/goreleaser/goreleaser/pipeline" + "github.com/goreleaser/goreleaser/pipeline/archive" + "github.com/goreleaser/goreleaser/pipeline/brew" + "github.com/goreleaser/goreleaser/pipeline/build" + "github.com/goreleaser/goreleaser/pipeline/checksums" + "github.com/goreleaser/goreleaser/pipeline/defaults" + "github.com/goreleaser/goreleaser/pipeline/env" + "github.com/goreleaser/goreleaser/pipeline/fpm" + "github.com/goreleaser/goreleaser/pipeline/git" + "github.com/goreleaser/goreleaser/pipeline/release" +) + +var pipes = []pipeline.Pipe{ + defaults.Pipe{}, // load default configs + git.Pipe{}, // get and validate git repo state + env.Pipe{}, // load and validate environment variables + build.Pipe{}, // build + archive.Pipe{}, // archive (tar.gz, zip, etc) + fpm.Pipe{}, // archive via fpm (deb, rpm, etc) + checksums.Pipe{}, // checksums of the files + release.Pipe{}, // release to github + brew.Pipe{}, // push to brew tap +} + +func init() { + log.SetFlags(0) +} + +// Flags interface represents an extractor of cli flags +type Flags interface { + IsSet(s string) bool + String(s string) string + Bool(s string) bool +} + +// Release runs the release process with the given flags +func Release(flags Flags) error { + var file = flags.String("config") + var notes = flags.String("release-notes") + cfg, err := config.Load(file) + if err != nil { + // Allow file not found errors if config file was not + // explicitly specified + _, statErr := os.Stat(file) + if !os.IsNotExist(statErr) || flags.IsSet("config") { + return err + } + } + var ctx = context.New(cfg) + ctx.Validate = !flags.Bool("skip-validate") + ctx.Publish = !flags.Bool("skip-publish") + if notes != "" { + bts, err := ioutil.ReadFile(notes) + if err != nil { + return err + } + log.Println("Loaded custom release notes from", notes) + ctx.ReleaseNotes = string(bts) + } + for _, pipe := range pipes { + log.Println(pipe.Description()) + log.SetPrefix(" -> ") + if err := pipe.Run(ctx); err != nil { + return err + } + log.SetPrefix("") + } + log.Println("Done!") + return nil +} diff --git a/goreleaser.yml b/goreleaser.yml index eece48511..1e92dc837 100644 --- a/goreleaser.yml +++ b/goreleaser.yml @@ -1,3 +1,5 @@ +build: + main: ./cmd/goreleaser/main.go brew: github: owner: goreleaser diff --git a/goreleaser_test.go b/goreleaser_test.go new file mode 100644 index 000000000..601de4488 --- /dev/null +++ b/goreleaser_test.go @@ -0,0 +1,147 @@ +package goreleaser + +import ( + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func init() { + _ = os.Unsetenv("GITHUB_TOKEN") +} + +func TestRelease(t *testing.T) { + var assert = assert.New(t) + _, back := setup(t) + defer back() + var flags = fakeFlags{ + flags: map[string]string{ + "skip-publish": "true", + "skip-validate": "true", + }, + } + assert.NoError(Release(flags)) +} + +func TestConfigFileIsSetAndDontExist(t *testing.T) { + var assert = assert.New(t) + var flags = fakeFlags{ + flags: map[string]string{ + "config": "/this/wont/exist", + }, + } + assert.Error(Release(flags)) +} + +func TestReleaseNotesFileDontExist(t *testing.T) { + var assert = assert.New(t) + var flags = fakeFlags{ + flags: map[string]string{ + "release-notes": "/this/also/wont/exist", + }, + } + assert.Error(Release(flags)) +} + +func TestCustomReleaseNotesFile(t *testing.T) { + var assert = assert.New(t) + folder, back := setup(t) + defer back() + var releaseNotes = filepath.Join(folder, "notes.md") + createFile(t, releaseNotes, "nothing important at all") + var flags = fakeFlags{ + flags: map[string]string{ + "release-notes": releaseNotes, + "skip-publish": "true", + "skip-validate": "true", + }, + } + assert.NoError(Release(flags)) +} + +func TestBrokenPipe(t *testing.T) { + var assert = assert.New(t) + _, back := setup(t) + defer back() + createFile(t, "main.go", "not a valid go file") + var flags = fakeFlags{ + flags: map[string]string{ + "skip-publish": "true", + "skip-validate": "true", + }, + } + assert.Error(Release(flags)) +} + +// fakeFlags is a mock of the cli flags +type fakeFlags struct { + flags map[string]string +} + +func (f fakeFlags) IsSet(s string) bool { + return f.flags[s] != "" +} +func (f fakeFlags) String(s string) string { + return f.flags[s] +} +func (f fakeFlags) Bool(s string) bool { + return f.flags[s] == "true" +} + +func setup(t *testing.T) (current string, back func()) { + var assert = assert.New(t) + folder, err := ioutil.TempDir("", "goreleaser") + assert.NoError(err) + log.Println("Folder:", folder) + previous, err := os.Getwd() + assert.NoError(err) + assert.NoError(os.Chdir(folder)) + var gitCmds = [][]string{ + {"init"}, + {"add", "-A"}, + {"commit", "--allow-empty", "-m", "asdf"}, + {"tag", "v0.0.1"}, + {"commit", "--allow-empty", "-m", "asas89d"}, + {"commit", "--allow-empty", "-m", "assssf"}, + {"commit", "--allow-empty", "-m", "assd"}, + {"tag", "v0.0.2"}, + {"remote", "add", "origin", "git@github.com:goreleaser/fake.git"}, + } + createGoreleaserYaml(t) + createMainGo(t) + for _, cmd := range gitCmds { + assert.NoError(exec.Command("git", cmd...).Run()) + } + return folder, func() { + assert.NoError(os.Chdir(previous)) + } +} + +func createFile(t *testing.T, filename, contents string) { + var assert = assert.New(t) + assert.NoError(ioutil.WriteFile(filename, []byte(contents), 0644)) +} + +func createMainGo(t *testing.T) { + createFile(t, "main.go", "package main\nfunc main() {println(0)}") +} + +func createGoreleaserYaml(t *testing.T) { + var yaml = `build: + binary: fake + goos: + - linux + goarch: + - amd64 +release: + github: + owner: goreleaser + name: fake +` + createFile(t, "goreleaser.yml", yaml) +} diff --git a/main.go b/main.go deleted file mode 100644 index 1dd64d5b8..000000000 --- a/main.go +++ /dev/null @@ -1,107 +0,0 @@ -package main - -import ( - "io/ioutil" - "log" - "os" - - "github.com/goreleaser/goreleaser/config" - "github.com/goreleaser/goreleaser/context" - "github.com/goreleaser/goreleaser/pipeline" - "github.com/goreleaser/goreleaser/pipeline/archive" - "github.com/goreleaser/goreleaser/pipeline/brew" - "github.com/goreleaser/goreleaser/pipeline/build" - "github.com/goreleaser/goreleaser/pipeline/checksums" - "github.com/goreleaser/goreleaser/pipeline/defaults" - "github.com/goreleaser/goreleaser/pipeline/env" - "github.com/goreleaser/goreleaser/pipeline/fpm" - "github.com/goreleaser/goreleaser/pipeline/git" - "github.com/goreleaser/goreleaser/pipeline/release" - "github.com/urfave/cli" -) - -var ( - version = "dev" - commit = "none" - date = "unknown" -) - -var pipes = []pipeline.Pipe{ - defaults.Pipe{}, // load default configs - git.Pipe{}, // get and validate git repo state - env.Pipe{}, // load and validate environment variables - build.Pipe{}, // build - archive.Pipe{}, // archive (tar.gz, zip, etc) - fpm.Pipe{}, // archive via fpm (deb, rpm, etc) - checksums.Pipe{}, // checksums of the files - release.Pipe{}, // release to github - brew.Pipe{}, // push to brew tap -} - -func init() { - log.SetFlags(0) -} - -func main() { - var app = cli.NewApp() - app.Name = "goreleaser" - app.Version = version + ", commit " + commit + ", built at " + date - app.Usage = "Deliver Go binaries as fast and easily as possible" - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "config, file, c, f", - 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", - }, - cli.BoolFlag{ - Name: "skip-publish", - Usage: "Skip all publishing pipes of the release", - }, - } - 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 - // explicitly specified - _, statErr := os.Stat(file) - if !os.IsNotExist(statErr) || c.IsSet("config") { - return cli.NewExitError(err.Error(), 1) - } - } - 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(" -> ") - if err := pipe.Run(ctx); err != nil { - return cli.NewExitError(err.Error(), 1) - } - log.SetPrefix("") - } - log.Println("Done!") - return - } - if err := app.Run(os.Args); err != nil { - log.Fatalln(err) - } -} From baf6a2855973c2888905da26c1dcd8861ffb7511 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Fri, 21 Apr 2017 15:29:45 -0300 Subject: [PATCH 2/2] travis doesnt have git setup --- goreleaser_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/goreleaser_test.go b/goreleaser_test.go index 601de4488..f8063f5ce 100644 --- a/goreleaser_test.go +++ b/goreleaser_test.go @@ -115,7 +115,14 @@ func setup(t *testing.T) (current string, back func()) { createGoreleaserYaml(t) createMainGo(t) for _, cmd := range gitCmds { - assert.NoError(exec.Command("git", cmd...).Run()) + var args = []string{ + "-c", + "user.name='GoReleaser'", + "-c", + "user.email='test@goreleaser.github.com'", + } + args = append(args, cmd...) + assert.NoError(exec.Command("git", args...).Run()) } return folder, func() { assert.NoError(os.Chdir(previous))