diff --git a/internal/artifact/artifact.go b/internal/artifact/artifact.go index a832eb4d9..edaecb35a 100644 --- a/internal/artifact/artifact.go +++ b/internal/artifact/artifact.go @@ -7,8 +7,9 @@ import "sync" type Type int const ( - // Archive is a tar.gz or zip archive - Archive Type = iota + // Uploadable is a file that should be uploaded to a release. + // Could be a tar.gz/zip archive or a binary. + Uploadable Type = iota // Binary is a binary (output of a gobuild) Binary // DockerImage is a docker image @@ -41,6 +42,25 @@ func New() Artifacts { } } +// List return the actual list of artifacts +func (artifacts *Artifacts) List() []Artifact { + return artifacts.items +} + +// Platform returns the platform string of a given artifact +func (a Artifact) Platform() string { + return a.Goos + a.Goarch + a.Goarm +} + +// GroupByPlatform groups the artifacts by their platform +func (artifacts *Artifacts) GroupByPlatform() map[string][]Artifact { + var result = map[string][]Artifact{} + for _, a := range artifacts.items { + result[a.Platform()] = append(result[a.Platform()], a) + } + return result +} + // Add safely adds a new artifact to an artifact list func (artifacts *Artifacts) Add(a Artifact) { artifacts.lock.Lock() diff --git a/internal/artifact/artifact_test.go b/internal/artifact/artifact_test.go index bdff0ff1c..8ccc79138 100644 --- a/internal/artifact/artifact_test.go +++ b/internal/artifact/artifact_test.go @@ -35,7 +35,7 @@ func TestAdd(t *testing.T) { }) } assert.NoError(t, g.Wait()) - assert.Len(t, artifacts.items, 4) + assert.Len(t, artifacts.List(), 4) } func TestFilter(t *testing.T) { @@ -73,3 +73,36 @@ func TestFilter(t *testing.T) { assert.Len(t, artifacts.Filter(ByType(Checksum)).items, 1) assert.Len(t, artifacts.Filter(ByType(Binary)).items, 0) } + +func TestGroupByPlatform(t *testing.T) { + var data = []Artifact{ + { + Name: "foo", + Goos: "linux", + Goarch: "amd64", + }, + { + Name: "bar", + Goos: "linux", + Goarch: "amd64", + }, + { + Name: "foobar", + Goos: "linux", + Goarch: "arm", + Goarm: "6", + }, + { + Name: "check", + Type: Checksum, + }, + } + var artifacts = New() + for _, a := range data { + artifacts.Add(a) + } + + var groups = artifacts.GroupByPlatform() + assert.Len(t, groups["linuxamd64"], 2) + assert.Len(t, groups["linuxarm6"], 1) +} diff --git a/pipeline/archive/archive.go b/pipeline/archive/archive.go index 25a313683..0ef0d4788 100644 --- a/pipeline/archive/archive.go +++ b/pipeline/archive/archive.go @@ -9,11 +9,13 @@ import ( "path/filepath" "github.com/apex/log" + "github.com/mattn/go-zglob" + "golang.org/x/sync/errgroup" + "github.com/goreleaser/archive" "github.com/goreleaser/goreleaser/context" "github.com/goreleaser/goreleaser/internal/archiveformat" - "github.com/mattn/go-zglob" - "golang.org/x/sync/errgroup" + "github.com/goreleaser/goreleaser/internal/artifact" ) // Pipe for archive @@ -26,14 +28,14 @@ func (Pipe) String() string { // Run the pipe func (Pipe) Run(ctx *context.Context) error { var g errgroup.Group - for platform, binaries := range ctx.Binaries { - platform := platform - binaries := binaries + var filtered = ctx.Artifacts.Filter(artifact.ByType(artifact.Binary)) + for _, artifacts := range filtered.GroupByPlatform() { + artifacts := artifacts g.Go(func() error { if ctx.Config.Archive.Format == "binary" { - return skip(ctx, platform, binaries) + return skip(ctx, artifacts) } - return create(ctx, platform, binaries) + return create(ctx, artifacts) }) } return g.Wait() @@ -62,52 +64,60 @@ func (Pipe) Default(ctx *context.Context) error { return nil } -func create(ctx *context.Context, platform string, groups map[string][]context.Binary) error { - for folder, binaries := range groups { - var format = archiveformat.For(ctx, platform) - archivePath := filepath.Join(ctx.Config.Dist, folder+"."+format) - archiveFile, err := os.Create(archivePath) - if err != nil { - return fmt.Errorf("failed to create directory %s: %s", archivePath, err.Error()) - } - defer func() { - if e := archiveFile.Close(); e != nil { - log.WithField("archive", archivePath).Errorf("failed to close file: %v", e) - } - }() - log.WithField("archive", archivePath).Info("creating") - var a = archive.New(archiveFile) - defer func() { - if e := a.Close(); e != nil { - log.WithField("archive", archivePath).Errorf("failed to close archive: %v", e) - } - }() - - files, err := findFiles(ctx) - if err != nil { - return fmt.Errorf("failed to find files to archive: %s", err.Error()) - } - for _, f := range files { - if err = a.Add(wrap(ctx, f, folder), f); err != nil { - return fmt.Errorf("failed to add %s to the archive: %s", f, err.Error()) - } - } - for _, binary := range binaries { - if err := a.Add(wrap(ctx, binary.Name, folder), binary.Path); err != nil { - return fmt.Errorf("failed to add %s -> %s to the archive: %s", binary.Path, binary.Name, err.Error()) - } - } - ctx.AddArtifact(archivePath) +func create(ctx *context.Context, artifacts []artifact.Artifact) error { + var format = archiveformat.For(ctx, artifacts[0].Platform()) + folder, err := nameFor(ctx, artifacts[0]) + if err != nil { + return err } + archivePath := filepath.Join(ctx.Config.Dist, folder+"."+format) + archiveFile, err := os.Create(archivePath) + if err != nil { + return fmt.Errorf("failed to create directory %s: %s", archivePath, err.Error()) + } + defer func() { + if e := archiveFile.Close(); e != nil { + log.WithField("archive", archivePath).Errorf("failed to close file: %v", e) + } + }() + log.WithField("archive", archivePath).Info("creating") + var a = archive.New(archiveFile) + defer func() { + if e := a.Close(); e != nil { + log.WithField("archive", archivePath).Errorf("failed to close archive: %v", e) + } + }() + + files, err := findFiles(ctx) + if err != nil { + return fmt.Errorf("failed to find files to archive: %s", err.Error()) + } + for _, f := range files { + if err = a.Add(wrap(ctx, f, folder), f); err != nil { + return fmt.Errorf("failed to add %s to the archive: %s", f, err.Error()) + } + } + for _, binary := range artifacts { + if err := a.Add(wrap(ctx, binary.Name, folder), binary.Path); err != nil { + return fmt.Errorf("failed to add %s -> %s to the archive: %s", binary.Path, binary.Name, err.Error()) + } + } + ctx.Artifacts.Add(artifact.Artifact{ + Type: artifact.Uploadable, + Name: folder + "." + format, + Path: archivePath, + Goos: artifacts[0].Goos, + Goarch: artifacts[0].Goarch, + Goarm: artifacts[0].Goarm, + }) return nil } -func skip(ctx *context.Context, platform string, groups map[string][]context.Binary) error { - for _, binaries := range groups { - for _, binary := range binaries { - log.WithField("binary", binary.Name).Info("skip archiving") - ctx.AddArtifact(binary.Path) - } +func skip(ctx *context.Context, artifacts []artifact.Artifact) error { + for _, a := range artifacts { + log.WithField("binary", a.Name).Info("skip archiving") + a.Type = artifact.Uploadable + ctx.Artifacts.Add(a) } return nil } diff --git a/pipeline/archive/name.go b/pipeline/archive/name.go index 4748ed543..6b4804c19 100644 --- a/pipeline/archive/name.go +++ b/pipeline/archive/name.go @@ -5,12 +5,12 @@ import ( "text/template" "github.com/goreleaser/goreleaser/context" - "github.com/goreleaser/goreleaser/internal/buildtarget" + "github.com/goreleaser/goreleaser/internal/artifact" ) -func nameFor(ctx *context.Context, target buildtarget.Target, name string) (string, error) { +func nameFor(ctx *context.Context, a artifact.Artifact) (string, error) { var out bytes.Buffer - t, err := template.New(name).Parse(ctx.Config.Archive.NameTemplate) + t, err := template.New("archive_name").Parse(ctx.Config.Archive.NameTemplate) if err != nil { return "", err } @@ -18,13 +18,12 @@ func nameFor(ctx *context.Context, target buildtarget.Target, name string) (stri Os, Arch, Arm, Version, Tag, Binary, ProjectName string Env map[string]string }{ - Os: replace(ctx.Config.Archive.Replacements, target.OS), - Arch: replace(ctx.Config.Archive.Replacements, target.Arch), - Arm: replace(ctx.Config.Archive.Replacements, target.Arm), + Os: replace(ctx.Config.Archive.Replacements, a.Goos), + Arch: replace(ctx.Config.Archive.Replacements, a.Goarch), + Arm: replace(ctx.Config.Archive.Replacements, a.Goarm), Version: ctx.Version, Tag: ctx.Git.CurrentTag, - Binary: name, // TODO: deprecated: remove this sometime - ProjectName: name, + ProjectName: ctx.Config.ProjectName, Env: ctx.Env, } err = t.Execute(&out, data)