From 594cee7717f8165f7393902c20e4661799d11b72 Mon Sep 17 00:00:00 2001 From: Carlos A Becker Date: Thu, 25 Nov 2021 00:13:40 -0300 Subject: [PATCH 1/2] feat: allow a --output flag on goreleaser build Signed-off-by: Carlos A Becker --- cmd/build.go | 27 +++++++++++++++++++++- cmd/build_test.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/cmd/build.go b/cmd/build.go index 653da43b5fe..0a16125f4b0 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -9,6 +9,8 @@ import ( "github.com/apex/log" "github.com/caarlos0/ctrlc" "github.com/fatih/color" + "github.com/goreleaser/goreleaser/internal/artifact" + "github.com/goreleaser/goreleaser/internal/gio" "github.com/goreleaser/goreleaser/internal/middleware/errhandler" "github.com/goreleaser/goreleaser/internal/middleware/logging" "github.com/goreleaser/goreleaser/internal/middleware/skip" @@ -34,6 +36,7 @@ type buildOpts struct { parallelism int timeout time.Duration singleTarget bool + output string } func newBuildCmd() *buildCmd { @@ -81,6 +84,7 @@ Finally, it allows you to generate a local build for your current machine only u cmd.Flags().BoolVar(&root.opts.singleTarget, "single-target", false, "Builds only for current GOOS and GOARCH") cmd.Flags().StringVar(&root.opts.id, "id", "", "Builds only the specified build id") cmd.Flags().BoolVar(&root.opts.deprecated, "deprecated", false, "Force print the deprecation message - tests only") + cmd.Flags().StringVarP(&root.opts.output, "output", "o", "", "Path to the binary, defaults to the distribution folder according to configs. Only taked into account when using --single-target and a single id (either with --id or if config only has one build)") _ = cmd.Flags().MarkHidden("deprecated") root.cmd = cmd @@ -98,7 +102,7 @@ func buildProject(options buildOpts) (*context.Context, error) { return nil, err } return ctx, ctrlc.Default.Run(ctx, func() error { - for _, pipe := range pipeline.BuildPipeline { + for _, pipe := range setupPipeline(ctx, options) { if err := skip.Maybe( pipe, logging.Log( @@ -114,6 +118,13 @@ func buildProject(options buildOpts) (*context.Context, error) { }) } +func setupPipeline(ctx *context.Context, options buildOpts) []pipeline.Piper { + if options.singleTarget && options.output != "" && (options.id != "" || len(ctx.Config.Builds) == 1) { + return append(pipeline.BuildPipeline, withOutputPipe{options.output}) + } + return pipeline.BuildPipeline +} + func setupBuildContext(ctx *context.Context, options buildOpts) error { ctx.Parallelism = runtime.NumCPU() if options.parallelism > 0 { @@ -182,3 +193,17 @@ func setupBuildID(ctx *context.Context, id string) error { ctx.Config.Builds = keep return nil } + +// withOutputPipe copies the binary from dist to the specified output path. +type withOutputPipe struct { + output string +} + +func (w withOutputPipe) String() string { + return fmt.Sprintf("copying binary to %q", w.output) +} + +func (w withOutputPipe) Run(ctx *context.Context) error { + path := ctx.Artifacts.Filter(artifact.ByType(artifact.Binary)).List()[0].Path + return gio.Copy(path, w.output) +} diff --git a/cmd/build_test.go b/cmd/build_test.go index 41414fc398a..2ed6fa47357 100644 --- a/cmd/build_test.go +++ b/cmd/build_test.go @@ -5,6 +5,7 @@ import ( "runtime" "testing" + "github.com/goreleaser/goreleaser/internal/pipeline" "github.com/goreleaser/goreleaser/pkg/config" "github.com/goreleaser/goreleaser/pkg/context" "github.com/stretchr/testify/require" @@ -40,6 +41,62 @@ func TestBuildBrokenProject(t *testing.T) { require.EqualError(t, cmd.cmd.Execute(), "failed to parse dir: .: main.go:1:1: expected 'package', found not") } +func TestSetupPipeline(t *testing.T) { + t.Run("regular", func(t *testing.T) { + require.Equal(t, pipeline.BuildPipeline, setupPipeline(context.New(config.Project{}), buildOpts{})) + }) + + t.Run("single-target", func(t *testing.T) { + require.Equal(t, pipeline.BuildPipeline, setupPipeline(context.New(config.Project{}), buildOpts{ + singleTarget: true, + })) + }) + + t.Run("single-target and id", func(t *testing.T) { + require.Equal(t, pipeline.BuildPipeline, setupPipeline(context.New(config.Project{}), buildOpts{ + singleTarget: true, + id: "foo", + })) + }) + + t.Run("single-target and single build on config", func(t *testing.T) { + require.Equal(t, pipeline.BuildPipeline, setupPipeline(context.New(config.Project{ + Builds: []config.Build{{}}, + }), buildOpts{ + singleTarget: true, + })) + }) + + t.Run("single-target, id and output", func(t *testing.T) { + require.Equal( + t, + append(pipeline.BuildPipeline, withOutputPipe{"foobar"}), + setupPipeline( + context.New(config.Project{}), buildOpts{ + singleTarget: true, + id: "foo", + output: "foobar", + }, + ), + ) + }) + + t.Run("single-target, single build on config and output", func(t *testing.T) { + require.Equal( + t, + append(pipeline.BuildPipeline, withOutputPipe{"zaz"}), + setupPipeline( + context.New(config.Project{ + Builds: []config.Build{{}}, + }), buildOpts{ + singleTarget: true, + output: "zaz", + }, + ), + ) + }) +} + func TestBuildFlags(t *testing.T) { setup := func(opts buildOpts) *context.Context { ctx := context.New(config.Project{}) From ca43ed0b5cfb62dfe904beecc32e1d33638ee08f Mon Sep 17 00:00:00 2001 From: Carlos A Becker Date: Sun, 5 Dec 2021 23:11:34 -0300 Subject: [PATCH 2/2] fix: single build always to copies to root Signed-off-by: Carlos A Becker --- cmd/build.go | 9 +++++++-- cmd/build_test.go | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/build.go b/cmd/build.go index 0a16125f4b0..ecfa0f43074 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "os" + "path/filepath" "runtime" "time" @@ -119,7 +120,7 @@ func buildProject(options buildOpts) (*context.Context, error) { } func setupPipeline(ctx *context.Context, options buildOpts) []pipeline.Piper { - if options.singleTarget && options.output != "" && (options.id != "" || len(ctx.Config.Builds) == 1) { + if options.singleTarget && (options.id != "" || len(ctx.Config.Builds) == 1) { return append(pipeline.BuildPipeline, withOutputPipe{options.output}) } return pipeline.BuildPipeline @@ -205,5 +206,9 @@ func (w withOutputPipe) String() string { func (w withOutputPipe) Run(ctx *context.Context) error { path := ctx.Artifacts.Filter(artifact.ByType(artifact.Binary)).List()[0].Path - return gio.Copy(path, w.output) + out := w.output + if out == "" { + out = filepath.Base(path) + } + return gio.Copy(path, out) } diff --git a/cmd/build_test.go b/cmd/build_test.go index 2ed6fa47357..5886a8ad8c9 100644 --- a/cmd/build_test.go +++ b/cmd/build_test.go @@ -53,14 +53,14 @@ func TestSetupPipeline(t *testing.T) { }) t.Run("single-target and id", func(t *testing.T) { - require.Equal(t, pipeline.BuildPipeline, setupPipeline(context.New(config.Project{}), buildOpts{ + require.Equal(t, append(pipeline.BuildPipeline, withOutputPipe{""}), setupPipeline(context.New(config.Project{}), buildOpts{ singleTarget: true, id: "foo", })) }) t.Run("single-target and single build on config", func(t *testing.T) { - require.Equal(t, pipeline.BuildPipeline, setupPipeline(context.New(config.Project{ + require.Equal(t, append(pipeline.BuildPipeline, withOutputPipe{""}), setupPipeline(context.New(config.Project{ Builds: []config.Build{{}}, }), buildOpts{ singleTarget: true,