Skip to content

Commit

Permalink
feat: validate goos, goarch, goarm and gomips (#1886)
Browse files Browse the repository at this point in the history
* feat: validate goos, goarch, goarm and gomips

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

* fix: lint

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

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
caarlos0 and kodiakhq[bot] committed Nov 5, 2020
1 parent fafeb9b commit 032a105
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 65 deletions.
10 changes: 7 additions & 3 deletions internal/builders/golang/build.go
Expand Up @@ -34,7 +34,7 @@ func init() {
type Builder struct{}

// WithDefaults sets the defaults for a golang build and returns it.
func (*Builder) WithDefaults(build config.Build) config.Build {
func (*Builder) WithDefaults(build config.Build) (config.Build, error) {
if build.Dir == "" {
build.Dir = "."
}
Expand All @@ -54,12 +54,16 @@ func (*Builder) WithDefaults(build config.Build) config.Build {
if len(build.Goarm) == 0 {
build.Goarm = []string{"6"}
}
build.Targets = matrix(build)
targets, err := matrix(build)
build.Targets = targets
if err != nil {
return build, err
}
}
if build.GoBinary == "" {
build.GoBinary = "go"
}
return build
return build, nil
}

// Build builds a golang build.
Expand Down
49 changes: 48 additions & 1 deletion internal/builders/golang/build_test.go
Expand Up @@ -94,13 +94,60 @@ func TestWithDefaults(t *testing.T) {
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var build = Default.WithDefaults(ctx.Config.Builds[0])
build, err := Default.WithDefaults(ctx.Config.Builds[0])
require.NoError(t, err)
require.ElementsMatch(t, build.Targets, testcase.targets)
require.EqualValues(t, testcase.goBinary, build.GoBinary)
})
}
}

func TestInvalidTargets(t *testing.T) {
type testcase struct {
build config.Build
expectedErr string
}
for s, tc := range map[string]testcase{
"goos": {
build: config.Build{
Goos: []string{"darwin", "darwim"},
},
expectedErr: "invalid goos: darwim",
},
"goarch": {
build: config.Build{
Goarch: []string{"amd64", "i386", "386"},
},
expectedErr: "invalid goarch: i386",
},
"goarm": {
build: config.Build{
Goarch: []string{"arm"},
Goarm: []string{"6", "9", "8", "7"},
},
expectedErr: "invalid goarm: 9",
},
"gomips": {
build: config.Build{
Goarch: []string{"mips"},
Gomips: []string{"softfloat", "mehfloat", "hardfloat"},
},
expectedErr: "invalid gomips: mehfloat",
},
} {
t.Run(s, func(t *testing.T) {
var config = config.Project{
Builds: []config.Build{
tc.build,
},
}
var ctx = context.New(config)
_, err := Default.WithDefaults(ctx.Config.Builds[0])
require.EqualError(t, err, tc.expectedErr)
})
}
}

func TestBuild(t *testing.T) {
folder, back := testlib.Mktmp(t)
defer back()
Expand Down
149 changes: 101 additions & 48 deletions internal/builders/golang/targets.go
Expand Up @@ -22,10 +22,24 @@ func (t target) String() string {
return fmt.Sprintf("%s_%s", t.os, t.arch)
}

func matrix(build config.Build) (result []string) {
func matrix(build config.Build) ([]string, error) {
// nolint:prealloc
var targets []target
// nolint:prealloc
var result []string
for _, target := range allBuildTargets(build) {
if !contains(target.os, validGoos) {
return result, fmt.Errorf("invalid goos: %s", target.os)
}
if !contains(target.arch, validGoarch) {
return result, fmt.Errorf("invalid goarch: %s", target.arch)
}
if target.arm != "" && !contains(target.arm, validGoarm) {
return result, fmt.Errorf("invalid goarm: %s", target.arm)
}
if target.mips != "" && !contains(target.mips, validGomips) {
return result, fmt.Errorf("invalid gomips: %s", target.mips)
}
if !valid(target) {
log.WithField("target", target).
Debug("skipped invalid build")
Expand All @@ -41,7 +55,7 @@ func matrix(build config.Build) (result []string) {
for _, target := range targets {
result = append(result, target.String())
}
return
return result, nil
}

func allBuildTargets(build config.Build) (targets []target) {
Expand Down Expand Up @@ -98,56 +112,95 @@ func ignored(build config.Build, target target) bool {
}

func valid(target target) bool {
var s = target.os + target.arch
for _, a := range validTargets {
if a == s {
return contains(target.os+target.arch, validTargets)
}

func contains(s string, ss []string) bool {
for _, z := range ss {
if z == s {
return true
}
}
return false
}

// list from https://golang.org/doc/install/source#environment
// lists from https://golang.org/doc/install/source#environment
// nolint: gochecknoglobals
var validTargets = []string{
"aixppc64",
"android386",
"androidamd64",
"androidarm",
"androidarm64",
// "darwin386", - deprecated on latest go 1.15+
"darwinamd64",
// "darwinarm", - requires admin rights and other ios stuff
// "darwinarm64", - requires admin rights and other ios stuff
"dragonflyamd64",
"freebsd386",
"freebsdamd64",
"freebsdarm",
"freebsdarm64", // not on the official list for some reason, yet its supported on go 1.14+
"illumosamd64",
"jswasm",
"linux386",
"linuxamd64",
"linuxarm",
"linuxarm64",
"linuxppc64",
"linuxppc64le",
"linuxmips",
"linuxmipsle",
"linuxmips64",
"linuxmips64le",
"linuxs390x",
"netbsd386",
"netbsdamd64",
"netbsdarm",
"openbsd386",
"openbsdamd64",
"openbsdarm",
"openbsdarm64",
"plan9386",
"plan9amd64",
"plan9arm",
"solarisamd64",
"windows386",
"windowsamd64",
}
var (
validTargets = []string{
"aixppc64",
"android386",
"androidamd64",
"androidarm",
"androidarm64",
// "darwin386", - deprecated on latest go 1.15+
"darwinamd64",
// "darwinarm", - requires admin rights and other ios stuff
// "darwinarm64", - requires admin rights and other ios stuff
"dragonflyamd64",
"freebsd386",
"freebsdamd64",
"freebsdarm",
"freebsdarm64", // not on the official list for some reason, yet its supported on go 1.14+
"illumosamd64",
"jswasm",
"linux386",
"linuxamd64",
"linuxarm",
"linuxarm64",
"linuxppc64",
"linuxppc64le",
"linuxmips",
"linuxmipsle",
"linuxmips64",
"linuxmips64le",
"linuxs390x",
"netbsd386",
"netbsdamd64",
"netbsdarm",
"openbsd386",
"openbsdamd64",
"openbsdarm",
"openbsdarm64",
"plan9386",
"plan9amd64",
"plan9arm",
"solarisamd64",
"windows386",
"windowsamd64",
}

validGoos = []string{
"aix",
"android",
"darwin",
"dragonfly",
"freebsd",
"illumos",
"js",
"linux",
"netbsd",
"openbsd",
"plan9",
"solaris",
"windows",
}

validGoarch = []string{
"386",
"amd64",
"arm",
"arm64",
"mips",
"mips64",
"mips64le",
"mipsle",
"ppc64",
"ppc64le",
"s390x",
"wasm",
}

validGoarm = []string{"5", "6", "7"}
validGomips = []string{"hardfloat", "softfloat"}
)
4 changes: 3 additions & 1 deletion internal/builders/golang/targets_test.go
Expand Up @@ -53,6 +53,8 @@ func TestAllBuildTargets(t *testing.T) {
},
},
}
result, err := matrix(build)
require.NoError(t, err)
require.Equal(t, []string{
"linux_386",
"linux_amd64",
Expand All @@ -74,7 +76,7 @@ func TestAllBuildTargets(t *testing.T) {
"openbsd_amd64",
"openbsd_arm64",
"js_wasm",
}, matrix(build))
}, result)
}

func TestGoosGoarchCombos(t *testing.T) {
Expand Down
14 changes: 10 additions & 4 deletions internal/pipe/build/build.go
Expand Up @@ -51,18 +51,24 @@ func (Pipe) Run(ctx *context.Context) error {
func (Pipe) Default(ctx *context.Context) error {
var ids = ids.New("builds")
for i, build := range ctx.Config.Builds {
ctx.Config.Builds[i] = buildWithDefaults(ctx, build)
build, err := buildWithDefaults(ctx, build)
if err != nil {
return err
}
ctx.Config.Builds[i] = build
ids.Inc(ctx.Config.Builds[i].ID)
}
if len(ctx.Config.Builds) == 0 {
ctx.Config.Builds = []config.Build{
buildWithDefaults(ctx, ctx.Config.SingleBuild),
build, err := buildWithDefaults(ctx, ctx.Config.SingleBuild)
if err != nil {
return err
}
ctx.Config.Builds = []config.Build{build}
}
return ids.Validate()
}

func buildWithDefaults(ctx *context.Context, build config.Build) config.Build {
func buildWithDefaults(ctx *context.Context, build config.Build) (config.Build, error) {
if build.Lang == "" {
build.Lang = "go"
}
Expand Down
48 changes: 43 additions & 5 deletions internal/pipe/build/build_test.go
Expand Up @@ -17,16 +17,21 @@ import (
"github.com/stretchr/testify/require"
)

var errFailedBuild = errors.New("fake builder failed")
var errFailedDefault = errors.New("fake builder defaults failed")

type fakeBuilder struct {
fail bool
fail bool
failDefault bool
}

func (*fakeBuilder) WithDefaults(build config.Build) config.Build {
return build
func (f *fakeBuilder) WithDefaults(build config.Build) (config.Build, error) {
if f.failDefault {
return build, errFailedDefault
}
return build, nil
}

var errFailedBuild = errors.New("fake builder failed")

func (f *fakeBuilder) Build(ctx *context.Context, build config.Build, options api.Options) error {
if f.fail {
return errFailedBuild
Expand All @@ -48,6 +53,9 @@ func init() {
api.Register("fakeFail", &fakeBuilder{
fail: true,
})
api.Register("fakeFailDefault", &fakeBuilder{
failDefault: true,
})
}

func TestPipeDescription(t *testing.T) {
Expand Down Expand Up @@ -212,6 +220,22 @@ func TestDefaultNoBuilds(t *testing.T) {
require.NoError(t, Pipe{}.Default(ctx))
}

func TestDefaultFail(t *testing.T) {
folder, back := testlib.Mktmp(t)
defer back()
var config = config.Project{
Dist: folder,
Builds: []config.Build{
{
Lang: "fakeFailDefault",
},
},
}
var ctx = context.New(config)
require.EqualError(t, Pipe{}.Default(ctx), errFailedDefault.Error())
require.Empty(t, ctx.Artifacts.List())
}

func TestDefaultExpandEnv(t *testing.T) {
require.NoError(t, os.Setenv("XBAR", "FOOBAR"))
var ctx = &context.Context{
Expand Down Expand Up @@ -351,6 +375,20 @@ func TestDefaultFillSingleBuild(t *testing.T) {
require.Equal(t, ctx.Config.Builds[0].Binary, "foo")
}

func TestDefaultFailSingleBuild(t *testing.T) {
folder, back := testlib.Mktmp(t)
defer back()
var config = config.Project{
Dist: folder,
SingleBuild: config.Build{
Lang: "fakeFailDefault",
},
}
var ctx = context.New(config)
require.EqualError(t, Pipe{}.Default(ctx), errFailedDefault.Error())
require.Empty(t, ctx.Artifacts.List())
}

func TestSkipBuild(t *testing.T) {
folder, back := testlib.Mktmp(t)
defer back()
Expand Down

1 comment on commit 032a105

@vercel
Copy link

@vercel vercel bot commented on 032a105 Nov 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.