Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: binary archive when multiple builds #3385

Merged
merged 2 commits into from Sep 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/pipe/archive/archive.go
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
23 changes: 21 additions & 2 deletions internal/pipe/archive/archive_test.go
Expand Up @@ -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())
Expand All @@ -406,7 +409,7 @@ func TestRunPipeBinary(t *testing.T) {
{
Format: "binary",
NameTemplate: defaultBinaryNameTemplate,
Builds: []string{"default"},
Builds: []string{"default", "default2"},
},
},
},
Expand Down Expand Up @@ -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"),
Expand All @@ -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) {
Expand Down
51 changes: 51 additions & 0 deletions 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
```
1 change: 1 addition & 0 deletions www/mkdocs.yml
Expand Up @@ -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
Expand Down