diff --git a/internal/pipe/archive/archive.go b/internal/pipe/archive/archive.go index 648938456a7..3d00feefb37 100644 --- a/internal/pipe/archive/archive.go +++ b/internal/pipe/archive/archive.go @@ -32,7 +32,7 @@ const ( // 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") +var ErrArchiveDifferentBinaryCount = errors.New("archive has different count of binaries for each platform, which may cause your users confusion.\nLearn more at https://goreleaser.com/errors/multiple-binaries-archive\n") // nolint: gochecknoglobals var lock sync.Mutex @@ -96,7 +96,7 @@ func (Pipe) Run(ctx *context.Context) error { filter = append(filter, artifact.ByIDs(archive.Builds...)) } artifacts := ctx.Artifacts.Filter(artifact.And(filter...)).GroupByPlatform() - if err := checkArtifacts(artifacts); err != nil && !archive.AllowDifferentBinaryCount { + if err := checkArtifacts(artifacts); err != nil && archive.Format != "binary" && !archive.AllowDifferentBinaryCount { return fmt.Errorf("invalid archive: %d: %w", i, ErrArchiveDifferentBinaryCount) } for group, artifacts := range artifacts { diff --git a/internal/pipe/archive/archive_test.go b/internal/pipe/archive/archive_test.go index e863063eaa6..eaef21dcbaa 100644 --- a/internal/pipe/archive/archive_test.go +++ b/internal/pipe/archive/archive_test.go @@ -396,6 +396,9 @@ func TestRunPipeBinary(t *testing.T) { f, err = os.Create(filepath.Join(dist, "windowsamd64", "mybin.exe")) require.NoError(t, err) require.NoError(t, f.Close()) + f, err = os.Create(filepath.Join(dist, "windowsamd64", "myotherbin")) + require.NoError(t, err) + require.NoError(t, f.Close()) f, err = os.Create(filepath.Join(folder, "README.md")) require.NoError(t, err) require.NoError(t, f.Close()) @@ -406,7 +409,7 @@ func TestRunPipeBinary(t *testing.T) { { Format: "binary", NameTemplate: defaultBinaryNameTemplate, - Builds: []string{"default"}, + Builds: []string{"default", "default2"}, }, }, }, @@ -448,9 +451,22 @@ func TestRunPipeBinary(t *testing.T) { artifact.ExtraID: "default", }, }) + ctx.Artifacts.Add(&artifact.Artifact{ + Goos: "windows", + Goarch: "amd64", + Name: "myotherbin.exe", + Path: filepath.Join(dist, "windowsamd64", "myotherbin.exe"), + Type: artifact.Binary, + Extra: map[string]interface{}{ + artifact.ExtraBinary: "myotherbin", + artifact.ExtraExt: ".exe", + artifact.ExtraID: "default2", + }, + }) + require.NoError(t, Pipe{}.Run(ctx)) binaries := ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableBinary)) - require.Len(t, binaries.List(), 3) + require.Len(t, binaries.List(), 4) darwinThin := binaries.Filter(artifact.And( artifact.ByGoos("darwin"), artifact.ByGoarch("amd64"), @@ -461,12 +477,15 @@ func TestRunPipeBinary(t *testing.T) { )).List()[0] require.True(t, artifact.ExtraOr(*darwinUniversal, artifact.ExtraReplaces, false)) windows := binaries.Filter(artifact.ByGoos("windows")).List()[0] + windows2 := binaries.Filter(artifact.ByGoos("windows")).List()[1] require.Equal(t, "mybin_0.0.1_darwin_amd64", darwinThin.Name) require.Equal(t, "mybin", artifact.ExtraOr(*darwinThin, artifact.ExtraBinary, "")) require.Equal(t, "myunibin_0.0.1_darwin_all", darwinUniversal.Name) require.Equal(t, "myunibin", artifact.ExtraOr(*darwinUniversal, artifact.ExtraBinary, "")) require.Equal(t, "mybin_0.0.1_windows_amd64.exe", windows.Name) require.Equal(t, "mybin.exe", artifact.ExtraOr(*windows, artifact.ExtraBinary, "")) + require.Equal(t, "myotherbin_0.0.1_windows_amd64.exe", windows2.Name) + require.Equal(t, "myotherbin.exe", artifact.ExtraOr(*windows2, artifact.ExtraBinary, "")) } func TestRunPipeDistRemoved(t *testing.T) { diff --git a/www/docs/errors/multiple-binaries-archive.md b/www/docs/errors/multiple-binaries-archive.md new file mode 100644 index 00000000000..a04b2d7c253 --- /dev/null +++ b/www/docs/errors/multiple-binaries-archive.md @@ -0,0 +1,51 @@ +# Archive has different count of binaries for each platform + +This error looks like this: + +```sh +тип release failed after 5s error=invalid archive: 0:archive has different count of binaries for each platform, which may cause your users confusion. +Learn more at https://goreleaser.com/errors/multiple-binaries-archive + +``` + +This will happen when you have several builds, and their target platforms are +different: + +```yaml +builds: +- id: b1 + binary: b1 + goos: [linux, darwin] +- id: b2 + binary: b2 + goos: [darwin] + +archives: +- id: a1 +``` + +In this scenario, GoReleaser will complain because the archive will have a +different binary count depending on which platform its being archived, since +it'll have 2 binaries on `darwin` and only 1 on `linux`. + + +From here on, you have a couple of options: + +- add another archive, and filter the builds on each of them - e.g. archive `a1` + with binaries from build `b1`, and archive `a2` with builds from build `b2`: + ```yaml + archives: + - id: a1 + builds: b1 + name_template: something-unique-for-a1 + - id: a2 + builds: b2 + name_template: something-unique-for-a2 + ``` +- if you really want to have the mixed archive, you can add + `allow_different_binary_count` to your archive configuration: + ```yaml + archives: + - id: a1 + allow_different_binary_count: true + ``` diff --git a/www/mkdocs.yml b/www/mkdocs.yml index 45913c3854b..369aed2def6 100644 --- a/www/mkdocs.yml +++ b/www/mkdocs.yml @@ -139,6 +139,7 @@ nav: - errors/no-main.md - errors/resource-not-accessible-by-integration.md - errors/no-history.md + - errors/multiple-binaries-archive.md - deprecations.md - Cookbooks: - About: cookbooks/index.md