Repository: goreleaser/goreleaser
Pull request #1008 (2019-04-14 17:35:58)

feat: build id
this is the first step to achieve multiple archives: we need to be able to identify builds.

The binary name alone is not a good idea, as the user may have different build configs depending on GOOS for example, so an `ID` field was added.

**This is a breaking change**: if the user has multiple builds with the same binary name the release will now fail.

refs #705 

codecov-io: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1008?src=pr&el=h1) Report
> Merging [#1008](https://codecov.io/gh/goreleaser/goreleaser/pull/1008?src=pr&el=desc) into [master](https://codecov.io/gh/goreleaser/goreleaser/commit/1a971c0d9a8c49d2092d8b87d5574efb90626f30?src=pr&el=desc) will **increase** coverage by `0.02%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/goreleaser/goreleaser/pull/1008/graphs/tree.svg?width=650&token=3bJvv6b7hN&height=150&src=pr)](https://codecov.io/gh/goreleaser/goreleaser/pull/1008?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1008      +/-   ##
==========================================
+ Coverage   88.12%   88.15%   +0.02%     
==========================================
  Files          52       52              
  Lines        2518     2524       +6     
==========================================
+ Hits         2219     2225       +6     
  Misses        236      236              
  Partials       63       63
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/1008?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/config/config.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1008/diff?src=pr&el=tree#diff-cGtnL2NvbmZpZy9jb25maWcuZ28=) | `100% <ø> (ø)` | :arrow_up: |
| [internal/pipe/build/build.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1008/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9idWlsZC9idWlsZC5nbw==) | `97.43% <100%> (+0.17%)` | :arrow_up: |
| [internal/builders/golang/build.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1008/diff?src=pr&el=tree#diff-aW50ZXJuYWwvYnVpbGRlcnMvZ29sYW5nL2J1aWxkLmdv) | `98.34% <100%> (+0.01%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1008?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1008?src=pr&el=footer). Last update [1a971c0...60697b4](https://codecov.io/gh/goreleaser/goreleaser/pull/1008?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/internal/builders/golang/build.go b/internal/builders/golang/build.go
index ffcd08e0..46e23a30 100644
--- a/internal/builders/golang/build.go
+++ b/internal/builders/golang/build.go
@@ -106,6 +106,7 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
 		Extra: map[string]interface{}{
 			"Binary": build.Binary,
 			"Ext":    options.Ext,
+			"ID":     build.ID,
 		},
 	})
 	return nil
diff --git a/internal/pipe/build/build.go b/internal/pipe/build/build.go
index a231c114..a0972b2b 100644
--- a/internal/pipe/build/build.go
+++ b/internal/pipe/build/build.go
@@ -3,19 +3,19 @@
 package build
 
 import (
+	"fmt"
 	"os"
 	"os/exec"
 	"path/filepath"
 	"strings"
 
 	"github.com/apex/log"
-	"github.com/pkg/errors"
-
 	"github.com/goreleaser/goreleaser/internal/semerrgroup"
 	"github.com/goreleaser/goreleaser/internal/tmpl"
 	builders "github.com/goreleaser/goreleaser/pkg/build"
 	"github.com/goreleaser/goreleaser/pkg/config"
 	"github.com/goreleaser/goreleaser/pkg/context"
+	"github.com/pkg/errors"
 
 	// langs to init
 	_ "github.com/goreleaser/goreleaser/internal/builders/golang"
@@ -41,16 +41,20 @@ func (Pipe) Run(ctx *context.Context) error {
 
 // Default sets the pipe defaults
 func (Pipe) Default(ctx *context.Context) error {
+	var ids = map[string]int{}
 	for i, build := range ctx.Config.Builds {
 		ctx.Config.Builds[i] = buildWithDefaults(ctx, build)
+		ids[ctx.Config.Builds[i].ID]++
 	}
 	if len(ctx.Config.Builds) == 0 {
 		ctx.Config.Builds = []config.Build{
 			buildWithDefaults(ctx, ctx.Config.SingleBuild),
 		}
 	}
-	if len(ctx.Config.Builds) > 1 {
-		log.Warn("you have more than 1 build setup: please make sure it is a not a typo on your config")
+	for id, cont := range ids {
+		if cont > 1 {
+			return fmt.Errorf("there are more than %d builds with the ID '%s', please fix your config", cont, id)
+		}
 	}
 	return nil
 }
@@ -62,6 +66,9 @@ func buildWithDefaults(ctx *context.Context, build config.Build) config.Build {
 	if build.Binary == "" {
 		build.Binary = ctx.Config.ProjectName
 	}
+	if build.ID == "" {
+		build.ID = build.Binary
+	}
 	for k, v := range build.Env {
 		build.Env[k] = os.ExpandEnv(v)
 	}
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 7596dd7c..f3510bc9 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -123,6 +123,7 @@ func (a *FlagArray) UnmarshalYAML(unmarshal func(interface{}) error) error {
 
 // Build contains the build configuration section
 type Build struct {
+	ID       string         `yaml:",omitempty"`
 	Goos     []string       `yaml:",omitempty"`
 	Goarch   []string       `yaml:",omitempty"`
 	Goarm    []string       `yaml:",omitempty"`
diff --git a/www/content/build.md b/www/content/build.md
index c8bc469a..8efde01d 100644
--- a/www/content/build.md
+++ b/www/content/build.md
@@ -17,6 +17,10 @@ Here is a commented `builds` section with all fields specified:
 builds:
   # You can have multiple builds defined as a yaml list
   -
+    # ID of the build.
+    # Defaults to the binary name.
+    id: "my-build"
+
     # Path to main.go file or main package.
     # Default is `.`.
     main: ./cmd/main.go


Test patch:
diff --git a/internal/builders/golang/build_test.go b/internal/builders/golang/build_test.go
index 4ad26710..d04b6e51 100644
--- a/internal/builders/golang/build_test.go
+++ b/internal/builders/golang/build_test.go
@@ -27,6 +27,7 @@ func TestWithDefaults(t *testing.T) {
 	}{
 		"full": {
 			build: config.Build{
+				ID:     "foo",
 				Binary: "foo",
 				Goos: []string{
 					"linux",
@@ -50,6 +51,7 @@ func TestWithDefaults(t *testing.T) {
 		},
 		"empty": {
 			build: config.Build{
+				ID:     "foo2",
 				Binary: "foo",
 			},
 			targets: []string{
@@ -81,6 +83,7 @@ func TestBuild(t *testing.T) {
 	var config = config.Project{
 		Builds: []config.Build{
 			{
+				ID:     "foo",
 				Env:    []string{"GO111MODULE=off"},
 				Binary: "foo",
 				Targets: []string{
@@ -122,6 +125,7 @@ func TestBuild(t *testing.T) {
 			Extra: map[string]interface{}{
 				"Ext":    "",
 				"Binary": "foo",
+				"ID":     "foo",
 			},
 		},
 		{
@@ -133,6 +137,7 @@ func TestBuild(t *testing.T) {
 			Extra: map[string]interface{}{
 				"Ext":    "",
 				"Binary": "foo",
+				"ID":     "foo",
 			},
 		},
 		{
@@ -145,6 +150,7 @@ func TestBuild(t *testing.T) {
 			Extra: map[string]interface{}{
 				"Ext":    "",
 				"Binary": "foo",
+				"ID":     "foo",
 			},
 		},
 		{
@@ -156,6 +162,7 @@ func TestBuild(t *testing.T) {
 			Extra: map[string]interface{}{
 				"Ext":    ".exe",
 				"Binary": "foo",
+				"ID":     "foo",
 			},
 		},
 	})
@@ -168,6 +175,7 @@ func TestBuildFailed(t *testing.T) {
 	var config = config.Project{
 		Builds: []config.Build{
 			{
+				ID:    "buildid",
 				Flags: []string{"-flag-that-dont-exists-to-force-failure"},
 				Targets: []string{
 					runtimeTarget,
@@ -192,6 +200,7 @@ func TestBuildInvalidTarget(t *testing.T) {
 	var config = config.Project{
 		Builds: []config.Build{
 			{
+				ID:      "foo",
 				Binary:  "foo",
 				Targets: []string{target},
 			},
diff --git a/internal/pipe/build/build_test.go b/internal/pipe/build/build_test.go
index d225c263..3e81eff4 100644
--- a/internal/pipe/build/build_test.go
+++ b/internal/pipe/build/build_test.go
@@ -218,16 +218,36 @@ func TestDefaultEmptyBuild(t *testing.T) {
 	assert.Equal(t, "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}", build.Ldflags[0])
 }
 
+func TestSeveralBuildsWithTheSameID(t *testing.T) {
+	var ctx = &context.Context{
+		Config: config.Project{
+			Builds: []config.Build{
+				{
+					ID:     "a",
+					Binary: "bar",
+				},
+				{
+					ID:     "a",
+					Binary: "foo",
+				},
+			},
+		},
+	}
+	assert.EqualError(t, Pipe{}.Default(ctx), "there are more than 2 builds with the ID 'a', please fix your config")
+}
+
 func TestDefaultPartialBuilds(t *testing.T) {
 	var ctx = &context.Context{
 		Config: config.Project{
 			Builds: []config.Build{
 				{
+					ID:     "build1",
 					Binary: "bar",
 					Goos:   []string{"linux"},
 					Main:   "./cmd/main.go",
 				},
 				{
+					ID:      "build2",
 					Binary:  "foo",
 					Ldflags: []string{"-s -w"},
 					Goarch:  []string{"386"},