1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-11 14:39:28 +02:00

feat: build single target and/or build id (#2179)

* feat: build single target

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>

* feat: build single id

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
This commit is contained in:
Carlos Alexandro Becker 2021-04-21 16:36:53 -03:00 committed by GitHub
parent e7f1ec0ea6
commit 0c2e80ae93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 162 additions and 12 deletions

View File

@ -1,6 +1,8 @@
package cmd
import (
"fmt"
"os"
"runtime"
"time"
@ -9,6 +11,7 @@ import (
"github.com/fatih/color"
"github.com/goreleaser/goreleaser/internal/middleware"
"github.com/goreleaser/goreleaser/internal/pipeline"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/spf13/cobra"
)
@ -20,6 +23,7 @@ type buildCmd struct {
type buildOpts struct {
config string
id string
snapshot bool
skipValidate bool
skipPostHooks bool
@ -27,12 +31,13 @@ type buildOpts struct {
deprecated bool
parallelism int
timeout time.Duration
singleTarget bool
}
func newBuildCmd() *buildCmd {
var root = &buildCmd{}
root := &buildCmd{}
// nolint: dupl
var cmd = &cobra.Command{
cmd := &cobra.Command{
Use: "build",
Aliases: []string{"b"},
Short: "Builds the current project",
@ -65,6 +70,8 @@ func newBuildCmd() *buildCmd {
cmd.Flags().BoolVar(&root.opts.rmDist, "rm-dist", false, "Remove the dist folder before building")
cmd.Flags().IntVarP(&root.opts.parallelism, "parallelism", "p", runtime.NumCPU(), "Amount tasks to run concurrently")
cmd.Flags().DurationVar(&root.opts.timeout, "timeout", 30*time.Minute, "Timeout to the entire build process")
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().MarkHidden("deprecated")
@ -79,7 +86,9 @@ func buildProject(options buildOpts) (*context.Context, error) {
}
ctx, cancel := context.NewWithTimeout(cfg, options.timeout)
defer cancel()
setupBuildContext(ctx, options)
if err := setupBuildContext(ctx, options); err != nil {
return nil, err
}
return ctx, ctrlc.Default.Run(ctx, func() error {
for _, pipe := range pipeline.BuildPipeline {
if err := middleware.Logging(
@ -94,7 +103,7 @@ func buildProject(options buildOpts) (*context.Context, error) {
})
}
func setupBuildContext(ctx *context.Context, options buildOpts) *context.Context {
func setupBuildContext(ctx *context.Context, options buildOpts) error {
ctx.Parallelism = options.parallelism
log.Debugf("parallelism: %v", ctx.Parallelism)
ctx.Snapshot = options.snapshot
@ -103,7 +112,59 @@ func setupBuildContext(ctx *context.Context, options buildOpts) *context.Context
ctx.RmDist = options.rmDist
ctx.SkipTokenCheck = true
if options.singleTarget {
setupBuildSingleTarget(ctx)
}
if options.id != "" {
if err := setupBuildID(ctx, options.id); err != nil {
return err
}
}
// test only
ctx.Deprecated = options.deprecated
return ctx
return nil
}
func setupBuildSingleTarget(ctx *context.Context) {
goos := os.Getenv("GOOS")
if goos == "" {
goos = runtime.GOOS
}
goarch := os.Getenv("GOARCH")
if goarch == "" {
goarch = runtime.GOARCH
}
log.Infof("building only for %s/%s", goos, goarch)
if len(ctx.Config.Builds) == 0 {
ctx.Config.Builds = append(ctx.Config.Builds, config.Build{})
}
for i := range ctx.Config.Builds {
build := &ctx.Config.Builds[i]
build.Goos = []string{goos}
build.Goarch = []string{goarch}
}
}
func setupBuildID(ctx *context.Context, id string) error {
if len(ctx.Config.Builds) < 2 {
log.Warn("single build in config, '--id' ignored")
return nil
}
var keep []config.Build
for _, build := range ctx.Config.Builds {
if build.ID == id {
keep = append(keep, build)
break
}
}
if len(keep) == 0 {
return fmt.Errorf("no builds with id '%s'", id)
}
ctx.Config.Builds = keep
return nil
}

View File

@ -1,6 +1,8 @@
package cmd
import (
"os"
"runtime"
"testing"
"github.com/goreleaser/goreleaser/pkg/config"
@ -10,15 +12,22 @@ import (
func TestBuild(t *testing.T) {
setup(t)
var cmd = newBuildCmd()
cmd := newBuildCmd()
cmd.cmd.SetArgs([]string{"--snapshot", "--timeout=1m", "--parallelism=2", "--deprecated"})
require.NoError(t, cmd.cmd.Execute())
}
func TestBuildSingleTarget(t *testing.T) {
setup(t)
cmd := newBuildCmd()
cmd.cmd.SetArgs([]string{"--snapshot", "--timeout=1m", "--parallelism=2", "--deprecated", "--single-target"})
require.NoError(t, cmd.cmd.Execute())
}
func TestBuildInvalidConfig(t *testing.T) {
setup(t)
createFile(t, "goreleaser.yml", "foo: bar")
var cmd = newBuildCmd()
cmd := newBuildCmd()
cmd.cmd.SetArgs([]string{"--snapshot", "--timeout=1m", "--parallelism=2", "--deprecated"})
require.EqualError(t, cmd.cmd.Execute(), "yaml: unmarshal errors:\n line 1: field foo not found in type config.Project")
}
@ -26,18 +35,20 @@ func TestBuildInvalidConfig(t *testing.T) {
func TestBuildBrokenProject(t *testing.T) {
setup(t)
createFile(t, "main.go", "not a valid go file")
var cmd = newBuildCmd()
cmd := newBuildCmd()
cmd.cmd.SetArgs([]string{"--snapshot", "--timeout=1m", "--parallelism=2"})
require.EqualError(t, cmd.cmd.Execute(), "failed to parse dir: .: main.go:1:1: expected 'package', found not")
}
func TestBuildFlags(t *testing.T) {
var setup = func(opts buildOpts) *context.Context {
return setupBuildContext(context.New(config.Project{}), opts)
setup := func(opts buildOpts) *context.Context {
ctx := context.New(config.Project{})
require.NoError(t, setupBuildContext(ctx, opts))
return ctx
}
t.Run("snapshot", func(t *testing.T) {
var ctx = setup(buildOpts{
ctx := setup(buildOpts{
snapshot: true,
})
require.True(t, ctx.Snapshot)
@ -46,7 +57,7 @@ func TestBuildFlags(t *testing.T) {
})
t.Run("skips", func(t *testing.T) {
var ctx = setup(buildOpts{
ctx := setup(buildOpts{
skipValidate: true,
skipPostHooks: true,
})
@ -66,4 +77,82 @@ func TestBuildFlags(t *testing.T) {
rmDist: true,
}).RmDist)
})
t.Run("single-target", func(t *testing.T) {
opts := buildOpts{
singleTarget: true,
}
t.Run("runtime", func(t *testing.T) {
result := setup(opts)
require.Equal(t, []string{runtime.GOOS}, result.Config.Builds[0].Goos)
require.Equal(t, []string{runtime.GOARCH}, result.Config.Builds[0].Goarch)
})
t.Run("from env", func(t *testing.T) {
os.Setenv("GOOS", "linux")
os.Setenv("GOARCH", "arm64")
t.Cleanup(func() {
os.Unsetenv("GOOS")
os.Unsetenv("GOARCH")
})
result := setup(opts)
require.Equal(t, []string{"linux"}, result.Config.Builds[0].Goos)
require.Equal(t, []string{"arm64"}, result.Config.Builds[0].Goarch)
})
})
t.Run("id", func(t *testing.T) {
t.Run("match", func(t *testing.T) {
ctx := context.New(config.Project{
Builds: []config.Build{
{
ID: "default",
},
{
ID: "foo",
},
},
})
require.NoError(t, setupBuildContext(ctx, buildOpts{
id: "foo",
}))
})
t.Run("dont match", func(t *testing.T) {
ctx := context.New(config.Project{
Builds: []config.Build{
{
ID: "foo",
},
{
ID: "bazz",
},
},
})
require.EqualError(t, setupBuildContext(ctx, buildOpts{
id: "bar",
}), "no builds with id 'bar'")
})
t.Run("default config", func(t *testing.T) {
ctx := context.New(config.Project{})
require.NoError(t, setupBuildContext(ctx, buildOpts{
id: "aaa",
}))
})
t.Run("single build config", func(t *testing.T) {
ctx := context.New(config.Project{
Builds: []config.Build{
{
ID: "foo",
},
},
})
require.NoError(t, setupBuildContext(ctx, buildOpts{
id: "not foo but doesnt matter",
}))
})
})
}