Skip to content

Commit

Permalink
feat: meta archives (#3093)
Browse files Browse the repository at this point in the history
adds support for creating meta archives

closes #3085

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>
  • Loading branch information
caarlos0 committed May 10, 2022
1 parent f83efdb commit e38e76c
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 16 deletions.
48 changes: 32 additions & 16 deletions internal/pipe/archive/archive.go
Expand Up @@ -84,6 +84,10 @@ func (Pipe) Run(ctx *context.Context) error {
g := semerrgroup.New(ctx.Parallelism)
for i, archive := range ctx.Config.Archives {
archive := archive
if archive.Meta {
return createMeta(ctx, archive)
}

filter := []artifact.Filter{artifact.Or(
artifact.ByType(artifact.Binary),
artifact.ByType(artifact.UniversalBinary),
Expand Down Expand Up @@ -120,11 +124,18 @@ func checkArtifacts(artifacts map[string][]*artifact.Artifact) error {
return ErrArchiveDifferentBinaryCount
}

func createMeta(ctx *context.Context, arch config.Archive) error {
return doCreate(ctx, arch, nil, arch.Format, tmpl.New(ctx))
}

func create(ctx *context.Context, arch config.Archive, binaries []*artifact.Artifact) error {
template := tmpl.New(ctx).WithArtifact(binaries[0], arch.Replacements)
format := packageFormat(arch, binaries[0].Goos)
folder, err := tmpl.New(ctx).
WithArtifact(binaries[0], arch.Replacements).
Apply(arch.NameTemplate)
return doCreate(ctx, arch, binaries, format, template)
}

func doCreate(ctx *context.Context, arch config.Archive, binaries []*artifact.Artifact, format string, template *tmpl.Template) error {
folder, err := template.Apply(arch.NameTemplate)
if err != nil {
return err
}
Expand All @@ -149,8 +160,6 @@ func create(ctx *context.Context, arch config.Archive, binaries []*artifact.Arti
log := log.WithField("archive", archivePath)
log.Info("creating")

template := tmpl.New(ctx).
WithArtifact(binaries[0], arch.Replacements)
wrap, err := template.Apply(wrapFolder(arch))
if err != nil {
return err
Expand All @@ -163,6 +172,9 @@ func create(ctx *context.Context, arch config.Archive, binaries []*artifact.Arti
if err != nil {
return fmt.Errorf("failed to find files to archive: %w", err)
}
if arch.Meta && len(files) == 0 {
return fmt.Errorf("no files found")
}
for _, f := range files {
if err = a.Add(f); err != nil {
return fmt.Errorf("failed to add: '%s' -> '%s': %w", f.Source, f.Destination, err)
Expand All @@ -178,24 +190,28 @@ func create(ctx *context.Context, arch config.Archive, binaries []*artifact.Arti
}
bins = append(bins, binary.Name)
}
ctx.Artifacts.Add(&artifact.Artifact{
Type: artifact.UploadableArchive,
Name: folder + "." + format,
Path: archivePath,
Goos: binaries[0].Goos,
Goarch: binaries[0].Goarch,
Goarm: binaries[0].Goarm,
Gomips: binaries[0].Gomips,
Goamd64: binaries[0].Goamd64,
art := &artifact.Artifact{
Type: artifact.UploadableArchive,
Name: folder + "." + format,
Path: archivePath,
Extra: map[string]interface{}{
artifact.ExtraBuilds: binaries,
artifact.ExtraID: arch.ID,
artifact.ExtraFormat: arch.Format,
artifact.ExtraWrappedIn: wrap,
artifact.ExtraBinaries: bins,
artifact.ExtraReplaces: binaries[0].Extra[artifact.ExtraReplaces],
},
})
}
if len(binaries) > 0 {
art.Goos = binaries[0].Goos
art.Goarch = binaries[0].Goarch
art.Goarm = binaries[0].Goarm
art.Gomips = binaries[0].Gomips
art.Goamd64 = binaries[0].Goamd64
art.Extra[artifact.ExtraReplaces] = binaries[0].Extra[artifact.ExtraReplaces]
}

ctx.Artifacts.Add(art)
return nil
}

Expand Down
71 changes: 71 additions & 0 deletions internal/pipe/archive/archive_meta_test.go
@@ -0,0 +1,71 @@
package archive

import (
"path/filepath"
"testing"

"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/require"
)

func TestMeta(t *testing.T) {
t.Run("good", func(t *testing.T) {
dist := t.TempDir()
ctx := context.New(config.Project{
Dist: dist,
Archives: []config.Archive{
{
Meta: true,
NameTemplate: "foo",
Files: []config.File{
{Source: "testdata/**/*.txt"},
},
},
},
})

require.NoError(t, Pipe{}.Default(ctx))
require.NoError(t, Pipe{}.Run(ctx))
require.Equal(
t,
[]string{"testdata/a/a.txt", "testdata/a/b/a.txt", "testdata/a/b/c/d.txt"},
tarFiles(t, filepath.Join(dist, "foo.tar.gz")),
)
})

t.Run("bad tmpl", func(t *testing.T) {
dist := t.TempDir()
ctx := context.New(config.Project{
Dist: dist,
Archives: []config.Archive{
{
Meta: true,
NameTemplate: "foo{{.Os}}",
Files: []config.File{
{Source: "testdata/**/*.txt"},
},
},
},
})

require.NoError(t, Pipe{}.Default(ctx))
require.EqualError(t, Pipe{}.Run(ctx), `template: tmpl:1:5: executing "tmpl" at <.Os>: map has no entry for key "Os"`)
})

t.Run("no files", func(t *testing.T) {
dist := t.TempDir()
ctx := context.New(config.Project{
Dist: dist,
Archives: []config.Archive{
{
Meta: true,
NameTemplate: "foo",
},
},
})

require.NoError(t, Pipe{}.Default(ctx))
require.EqualError(t, Pipe{}.Run(ctx), `no files found`)
})
}
1 change: 1 addition & 0 deletions pkg/config/config.go
Expand Up @@ -516,6 +516,7 @@ type Archive struct {
FormatOverrides []FormatOverride `yaml:"format_overrides,omitempty"`
WrapInDirectory string `yaml:"wrap_in_directory,omitempty"`
Files []File `yaml:"files,omitempty"`
Meta bool `yaml:"meta,omitempty"`
AllowDifferentBinaryCount bool `yaml:"allow_different_binary_count,omitempty"`
}

Expand Down
6 changes: 6 additions & 0 deletions www/docs/customization/archive.md
Expand Up @@ -15,6 +15,7 @@ archives:
id: my-archive

# Builds reference which build instances should be archived in this archive.
# Default is empty, which includes all builds.
builds:
- default

Expand All @@ -24,6 +25,11 @@ archives:
# Default is `tar.gz`.
format: zip

# This will create an archive without any binaries, only the files are there.
# The name template must not contain any references to `Os`, `Arch` and etc, since the archive will be meta.
# Defaul is false.
meta: true

# Archive name template.
# Defaults:
# - if format is `tar.gz`, `tar.xz`, `gz` or `zip`:
Expand Down

0 comments on commit e38e76c

Please sign in to comment.