diff --git a/internal/pipe/archive/archive.go b/internal/pipe/archive/archive.go index 909920efb..7cac6d123 100644 --- a/internal/pipe/archive/archive.go +++ b/internal/pipe/archive/archive.go @@ -4,6 +4,7 @@ package archive import ( + "errors" "fmt" "os" "path/filepath" @@ -28,6 +29,11 @@ const ( defaultBinaryNameTemplate = "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" ) +// ErrArchiveDifferentBinaryCount happens when an archive uses several builds which have different goos/goarch/etc sets, +// causing the archives for some platforms to have more binaries than others. +// GoReleaser breaks in these cases as it will only cause confusion to other users. +var ErrArchiveDifferentBinaryCount = errors.New("archive has different count of built binaries for each platform, which may cause your users confusion. Please make sure all builds used have the same set of goos/goarch/etc or split it into multiple archives") + // nolint: gochecknoglobals var lock sync.Mutex @@ -83,15 +89,18 @@ func (Pipe) Default(ctx *context.Context) error { // Run the pipe. func (Pipe) Run(ctx *context.Context) error { var g = semerrgroup.New(ctx.Parallelism) - for _, archive := range ctx.Config.Archives { + for i, archive := range ctx.Config.Archives { archive := archive - var filtered = ctx.Artifacts.Filter( + var artifacts = ctx.Artifacts.Filter( artifact.And( artifact.ByType(artifact.Binary), artifact.ByIDs(archive.Builds...), ), - ) - for group, artifacts := range filtered.GroupByPlatform() { + ).GroupByPlatform() + if err := checkArtifacts(artifacts); err != nil { + return fmt.Errorf("invalid archive: %d: %w", i, ErrArchiveDifferentBinaryCount) + } + for group, artifacts := range artifacts { log.Debugf("group %s has %d binaries", group, len(artifacts)) artifacts := artifacts g.Go(func() error { @@ -105,6 +114,17 @@ func (Pipe) Run(ctx *context.Context) error { return g.Wait() } +func checkArtifacts(artifacts map[string][]*artifact.Artifact) error { + var lens = map[int]bool{} + for _, v := range artifacts { + lens[len(v)] = true + } + if len(lens) == 1 { + return nil + } + return ErrArchiveDifferentBinaryCount +} + func create(ctx *context.Context, arch config.Archive, binaries []*artifact.Artifact) error { var format = packageFormat(arch, binaries[0].Goos) folder, err := tmpl.New(ctx). diff --git a/internal/pipe/archive/archive_test.go b/internal/pipe/archive/archive_test.go index d150b7ab0..71eb0e8f8 100644 --- a/internal/pipe/archive/archive_test.go +++ b/internal/pipe/archive/archive_test.go @@ -181,6 +181,69 @@ func TestRunPipe(t *testing.T) { } } +func TestRunPipeDifferentBinaryCount(t *testing.T) { + folder, back := testlib.Mktmp(t) + defer back() + var dist = filepath.Join(folder, "dist") + require.NoError(t, os.Mkdir(dist, 0755)) + for _, arch := range []string{"darwinamd64", "linuxamd64"} { + createFakeBinary(t, dist, arch, "bin/mybin") + } + createFakeBinary(t, dist, "darwinamd64", "bin/foobar") + var ctx = context.New(config.Project{ + Dist: dist, + ProjectName: "foobar", + Archives: []config.Archive{ + { + ID: "myid", + Format: "tar.gz", + Builds: []string{"default", "foobar"}, + NameTemplate: defaultNameTemplate, + }, + }, + }) + var darwinBuild = &artifact.Artifact{ + Goos: "darwin", + Goarch: "amd64", + Name: "bin/mybin", + Path: filepath.Join(dist, "darwinamd64", "bin", "mybin"), + Type: artifact.Binary, + Extra: map[string]interface{}{ + "Binary": "bin/mybin", + "ID": "default", + }, + } + var darwinBuild2 = &artifact.Artifact{ + Goos: "darwin", + Goarch: "amd64", + Name: "bin/foobar", + Path: filepath.Join(dist, "darwinamd64", "bin", "foobar"), + Type: artifact.Binary, + Extra: map[string]interface{}{ + "Binary": "bin/foobar", + "ID": "foobar", + }, + } + var linuxArmBuild = &artifact.Artifact{ + Goos: "linux", + Goarch: "amd64", + Name: "bin/mybin", + Path: filepath.Join(dist, "linuxamd64", "bin", "mybin"), + Type: artifact.Binary, + Extra: map[string]interface{}{ + "Binary": "bin/mybin", + "ID": "default", + }, + } + + ctx.Artifacts.Add(darwinBuild) + ctx.Artifacts.Add(darwinBuild2) + ctx.Artifacts.Add(linuxArmBuild) + ctx.Version = "0.0.1" + ctx.Git.CurrentTag = "v0.0.1" + require.EqualError(t, Pipe{}.Run(ctx), "invalid archive: 0: "+ErrArchiveDifferentBinaryCount.Error()) +} + func zipFiles(t *testing.T, path string) []string { f, err := os.Open(path) require.NoError(t, err)