Repository: goreleaser/goreleaser
Pull request #1015 (2019-05-07 10:01:41)

refactor: id validations
- small pkg to validate ids
- add id field to nfpm

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

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

```diff
@@            Coverage Diff             @@
##           master    #1015      +/-   ##
==========================================
+ Coverage   88.41%   88.44%   +0.03%     
==========================================
  Files          52       53       +1     
  Lines        2581     2588       +7     
==========================================
+ Hits         2282     2289       +7     
  Misses        236      236              
  Partials       63       63
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/1015?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/config/config.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1015/diff?src=pr&el=tree#diff-cGtnL2NvbmZpZy9jb25maWcuZ28=) | `100% <ø> (ø)` | :arrow_up: |
| [internal/pipe/build/build.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1015/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9idWlsZC9idWlsZC5nbw==) | `97.46% <100%> (-0.1%)` | :arrow_down: |
| [internal/ids/ids.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1015/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaWRzL2lkcy5nbw==) | `100% <100%> (ø)` | |
| [internal/pipe/archive/archive.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1015/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9hcmNoaXZlL2FyY2hpdmUuZ28=) | `96.2% <100%> (-0.08%)` | :arrow_down: |
| [internal/pipe/nfpm/nfpm.go](https://codecov.io/gh/goreleaser/goreleaser/pull/1015/diff?src=pr&el=tree#diff-aW50ZXJuYWwvcGlwZS9uZnBtL25mcG0uZ28=) | `92.42% <100%> (+0.23%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/1015?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/1015?src=pr&el=footer). Last update [19ed756...be83f18](https://codecov.io/gh/goreleaser/goreleaser/pull/1015?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/internal/ids/ids.go b/internal/ids/ids.go
new file mode 100644
index 00000000..b1c06e48
--- /dev/null
+++ b/internal/ids/ids.go
@@ -0,0 +1,27 @@
+// Package ids provides id validation code used my multiple pipes.
+package ids
+
+import "fmt"
+
+// IDs is the IDs type
+type IDs map[string]int
+
+// New IDs
+func New() IDs {
+	return IDs(map[string]int{})
+}
+
+// Inc increment the counter of the given id
+func (ids IDs) Inc(id string) {
+	ids[id]++
+}
+
+// Validate errors if there are any ids with counter > 1
+func (ids IDs) Validate() error {
+	for id, cont := range ids {
+		if cont > 1 {
+			return fmt.Errorf("found %d items with the ID '%s', please fix your config", cont, id)
+		}
+	}
+	return nil
+}
diff --git a/internal/pipe/archive/archive.go b/internal/pipe/archive/archive.go
index 47a74e00..b15f5cd2 100644
--- a/internal/pipe/archive/archive.go
+++ b/internal/pipe/archive/archive.go
@@ -11,11 +11,11 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/goreleaser/goreleaser/internal/deprecate"
-
 	"github.com/apex/log"
 	"github.com/campoy/unique"
 	"github.com/goreleaser/goreleaser/internal/artifact"
+	"github.com/goreleaser/goreleaser/internal/deprecate"
+	"github.com/goreleaser/goreleaser/internal/ids"
 	"github.com/goreleaser/goreleaser/internal/semerrgroup"
 	"github.com/goreleaser/goreleaser/internal/tmpl"
 	"github.com/goreleaser/goreleaser/pkg/archive"
@@ -42,7 +42,7 @@ func (Pipe) String() string {
 
 // Default sets the pipe defaults
 func (Pipe) Default(ctx *context.Context) error {
-	var ids = map[string]int{}
+	var ids = ids.New()
 	if len(ctx.Config.Archives) == 0 {
 		ctx.Config.Archives = append(ctx.Config.Archives, ctx.Config.Archive)
 		if !reflect.DeepEqual(ctx.Config.Archive, config.Archive{}) {
@@ -80,15 +80,9 @@ func (Pipe) Default(ctx *context.Context) error {
 				archive.Builds = append(archive.Builds, build.ID)
 			}
 		}
-		ids[archive.ID]++
+		ids.Inc(archive.ID)
 	}
-
-	for id, cont := range ids {
-		if cont > 1 {
-			return fmt.Errorf("found %d archives with the ID '%s', please fix your config", cont, id)
-		}
-	}
-	return nil
+	return ids.Validate()
 }
 
 // Run the pipe
diff --git a/internal/pipe/build/build.go b/internal/pipe/build/build.go
index 50177952..9e1cffb8 100644
--- a/internal/pipe/build/build.go
+++ b/internal/pipe/build/build.go
@@ -3,13 +3,13 @@
 package build
 
 import (
-	"fmt"
 	"os"
 	"os/exec"
 	"path/filepath"
 	"strings"
 
 	"github.com/apex/log"
+	"github.com/goreleaser/goreleaser/internal/ids"
 	"github.com/goreleaser/goreleaser/internal/semerrgroup"
 	"github.com/goreleaser/goreleaser/internal/tmpl"
 	builders "github.com/goreleaser/goreleaser/pkg/build"
@@ -41,22 +41,17 @@ func (Pipe) Run(ctx *context.Context) error {
 
 // Default sets the pipe defaults
 func (Pipe) Default(ctx *context.Context) error {
-	var ids = map[string]int{}
+	var ids = ids.New()
 	for i, build := range ctx.Config.Builds {
 		ctx.Config.Builds[i] = buildWithDefaults(ctx, build)
-		ids[ctx.Config.Builds[i].ID]++
+		ids.Inc(ctx.Config.Builds[i].ID)
 	}
 	if len(ctx.Config.Builds) == 0 {
 		ctx.Config.Builds = []config.Build{
 			buildWithDefaults(ctx, ctx.Config.SingleBuild),
 		}
 	}
-	for id, cont := range ids {
-		if cont > 1 {
-			return fmt.Errorf("found %d builds with the ID '%s', please fix your config", cont, id)
-		}
-	}
-	return nil
+	return ids.Validate()
 }
 
 func buildWithDefaults(ctx *context.Context, build config.Build) config.Build {
diff --git a/internal/pipe/nfpm/nfpm.go b/internal/pipe/nfpm/nfpm.go
index d2f4c0aa..09927ff9 100644
--- a/internal/pipe/nfpm/nfpm.go
+++ b/internal/pipe/nfpm/nfpm.go
@@ -10,6 +10,7 @@ import (
 	"github.com/apex/log"
 	"github.com/goreleaser/goreleaser/internal/artifact"
 	"github.com/goreleaser/goreleaser/internal/deprecate"
+	"github.com/goreleaser/goreleaser/internal/ids"
 	"github.com/goreleaser/goreleaser/internal/linux"
 	"github.com/goreleaser/goreleaser/internal/pipe"
 	"github.com/goreleaser/goreleaser/internal/semerrgroup"
@@ -40,8 +41,12 @@ func (Pipe) Default(ctx *context.Context) error {
 			deprecate.Notice("nfpm")
 		}
 	}
+	var ids = ids.New()
 	for i := range ctx.Config.NFPMs {
 		var fpm = &ctx.Config.NFPMs[i]
+		if fpm.ID == "" {
+			fpm.ID = "default"
+		}
 		if fpm.Bindir == "" {
 			fpm.Bindir = "/usr/local/bin"
 		}
@@ -56,8 +61,9 @@ func (Pipe) Default(ctx *context.Context) error {
 				fpm.Builds = append(fpm.Builds, b.ID)
 			}
 		}
+		ids.Inc(fpm.ID)
 	}
-	return nil
+	return ids.Validate()
 }
 
 // Run the pipe
diff --git a/pkg/config/config.go b/pkg/config/config.go
index a2303a0c..330fa2d9 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -172,6 +172,7 @@ type NFPM struct {
 	NFPMOverridables `yaml:",inline"`
 	Overrides        map[string]NFPMOverridables `yaml:"overrides,omitempty"`
 
+	ID          string   `yaml:",omitempty"`
 	Builds      []string `yaml:",omitempty"`
 	Formats     []string `yaml:",omitempty"`
 	Vendor      string   `yaml:",omitempty"`
@@ -298,14 +299,15 @@ type S3 struct {
 
 // Put HTTP upload configuration
 type Put struct {
-	Name           string `yaml:",omitempty"`
-	Target         string `yaml:",omitempty"`
-	Username       string `yaml:",omitempty"`
-	Mode           string `yaml:",omitempty"`
-	ChecksumHeader string `yaml:"checksum_header,omitempty"`
-	TrustedCerts   string `yaml:"trusted_certificates,omitempty"`
-	Checksum       bool   `yaml:",omitempty"`
-	Signature      bool   `yaml:",omitempty"`
+	Name           string   `yaml:",omitempty"`
+	IDs            []string `yaml:"ids,omitempty"`
+	Target         string   `yaml:",omitempty"`
+	Username       string   `yaml:",omitempty"`
+	Mode           string   `yaml:",omitempty"`
+	ChecksumHeader string   `yaml:"checksum_header,omitempty"`
+	TrustedCerts   string   `yaml:"trusted_certificates,omitempty"`
+	Checksum       bool     `yaml:",omitempty"`
+	Signature      bool     `yaml:",omitempty"`
 }
 
 // Project includes all project configuration
diff --git a/www/content/nfpm.md b/www/content/nfpm.md
index 0f72d0ca..932483c7 100644
--- a/www/content/nfpm.md
+++ b/www/content/nfpm.md
@@ -15,6 +15,9 @@ Available options:
 nfpms:
   # note that this is an array of nfpm configs
   -
+    # ID of the nfpm config, must be unique.
+    # Defaults to "default".
+    id: foo
     # You can change the name of the package.
     # Default: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
     name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"


Test patch:
diff --git a/internal/ids/ids_test.go b/internal/ids/ids_test.go
new file mode 100644
index 00000000..6c2642d2
--- /dev/null
+++ b/internal/ids/ids_test.go
@@ -0,0 +1,22 @@
+package ids
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestIDs(t *testing.T) {
+	var ids = New()
+	ids.Inc("foo")
+	ids.Inc("bar")
+	require.NoError(t, ids.Validate())
+}
+
+func TestIDsError(t *testing.T) {
+	var ids = New()
+	ids.Inc("foo")
+	ids.Inc("bar")
+	ids.Inc("foo")
+	require.EqualError(t, ids.Validate(), "found 2 items with the ID 'foo', please fix your config")
+}
diff --git a/internal/pipe/archive/archive_test.go b/internal/pipe/archive/archive_test.go
index 8639c430..68db4575 100644
--- a/internal/pipe/archive/archive_test.go
+++ b/internal/pipe/archive/archive_test.go
@@ -676,5 +676,5 @@ func TestSeveralArchivesWithTheSameID(t *testing.T) {
 			},
 		},
 	}
-	require.EqualError(t, Pipe{}.Default(ctx), "found 2 archives with the ID 'a', please fix your config")
+	require.EqualError(t, Pipe{}.Default(ctx), "found 2 items with the ID 'a', please fix your config")
 }
diff --git a/internal/pipe/build/build_test.go b/internal/pipe/build/build_test.go
index d187dfdc..cf713ce5 100644
--- a/internal/pipe/build/build_test.go
+++ b/internal/pipe/build/build_test.go
@@ -235,7 +235,7 @@ func TestSeveralBuildsWithTheSameID(t *testing.T) {
 			},
 		},
 	}
-	assert.EqualError(t, Pipe{}.Default(ctx), "found 2 builds with the ID 'a', please fix your config")
+	assert.EqualError(t, Pipe{}.Default(ctx), "found 2 items with the ID 'a', please fix your config")
 }
 
 func TestDefaultPartialBuilds(t *testing.T) {
diff --git a/internal/pipe/nfpm/nfpm_test.go b/internal/pipe/nfpm/nfpm_test.go
index 09deed0d..fb94a964 100644
--- a/internal/pipe/nfpm/nfpm_test.go
+++ b/internal/pipe/nfpm/nfpm_test.go
@@ -342,3 +342,19 @@ func TestOverrides(t *testing.T) {
 	require.Equal(t, "bar", ctx.Config.NFPMs[0].Overrides["deb"].NameTemplate)
 	require.Equal(t, "bar", merged.NameTemplate)
 }
+
+func TestSeveralNFPMsWithTheSameID(t *testing.T) {
+	var ctx = &context.Context{
+		Config: config.Project{
+			NFPMs: []config.NFPM{
+				{
+					ID: "a",
+				},
+				{
+					ID: "a",
+				},
+			},
+		},
+	}
+	require.EqualError(t, Pipe{}.Default(ctx), "found 2 items with the ID 'a', please fix your config")
+}