1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-10-30 23:58:09 +02:00

feat: multiple archives (#942)

* feat: multiple archives

* fix: several things

* test: fixed

* fix: several things

* fix: archive id on the artifact

* fix: deprecated since

* docs: deprecations page improvements
This commit is contained in:
Carlos Alexandro Becker
2019-04-16 10:19:15 -03:00
committed by GitHub
parent d8818c2683
commit b8f5901265
13 changed files with 407 additions and 220 deletions

View File

@@ -61,17 +61,18 @@ dockers:
extra_files:
- scripts/entrypoint.sh
archive:
name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
format_overrides:
- goos: windows
format: zip
archives:
-
name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
format_overrides:
- goos: windows
format: zip
brew:
github:
owner: goreleaser

View File

@@ -193,6 +193,18 @@ func ByType(t Type) Filter {
}
}
// ByIDs filter artifacts by an `ID` extra field.
func ByIDs(ids ...string) Filter {
var filters = make([]Filter, 0, len(ids))
for _, id := range ids {
id := id
filters = append(filters, func(a Artifact) bool {
return a.ExtraOr("ID", "") == id
})
}
return Or(filters...)
}
// Or performs an OR between all given filters
func Or(filters ...Filter) Filter {
return func(a Artifact) bool {

View File

@@ -195,3 +195,40 @@ func TestExtraOr(t *testing.T) {
require.Equal(t, "foo", a.ExtraOr("Foo", "bar"))
require.Equal(t, "bar", a.ExtraOr("Foobar", "bar"))
}
func TestByIDs(t *testing.T) {
var data = []Artifact{
{
Name: "foo",
Extra: map[string]interface{}{
"ID": "foo",
},
},
{
Name: "bar",
Extra: map[string]interface{}{
"ID": "bar",
},
},
{
Name: "foobar",
Extra: map[string]interface{}{
"ID": "foo",
},
},
{
Name: "check",
Extra: map[string]interface{}{
"ID": "check",
},
},
}
var artifacts = New()
for _, a := range data {
artifacts.Add(a)
}
require.Len(t, artifacts.Filter(ByIDs("check")).items, 1)
require.Len(t, artifacts.Filter(ByIDs("foo")).items, 2)
require.Len(t, artifacts.Filter(ByIDs("foo", "bar")).items, 3)
}

View File

@@ -7,19 +7,22 @@ import (
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
"github.com/goreleaser/goreleaser/internal/deprecate"
"github.com/apex/log"
"github.com/campoy/unique"
zglob "github.com/mattn/go-zglob"
"golang.org/x/sync/errgroup"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/semerrgroup"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/archive"
archivelib "github.com/goreleaser/goreleaser/pkg/archive"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
zglob "github.com/mattn/go-zglob"
)
const (
@@ -39,26 +42,50 @@ func (Pipe) String() string {
// Default sets the pipe defaults
func (Pipe) Default(ctx *context.Context) error {
var archive = &ctx.Config.Archive
if archive.Format == "" {
archive.Format = "tar.gz"
}
if len(archive.Files) == 0 {
archive.Files = []string{
"licence*",
"LICENCE*",
"license*",
"LICENSE*",
"readme*",
"README*",
"changelog*",
"CHANGELOG*",
var ids = map[string]int{}
if len(ctx.Config.Archives) == 0 {
ctx.Config.Archives = append(ctx.Config.Archives, ctx.Config.Archive)
if !reflect.DeepEqual(ctx.Config.Archive, config.Archive{}) {
deprecate.Notice("archive")
}
}
if archive.NameTemplate == "" {
archive.NameTemplate = defaultNameTemplate
if archive.Format == "binary" {
archive.NameTemplate = defaultBinaryNameTemplate
for i := range ctx.Config.Archives {
var archive = &ctx.Config.Archives[i]
if archive.Format == "" {
archive.Format = "tar.gz"
}
if archive.ID == "" {
archive.ID = "default"
}
if len(archive.Files) == 0 {
archive.Files = []string{
"licence*",
"LICENCE*",
"license*",
"LICENSE*",
"readme*",
"README*",
"changelog*",
"CHANGELOG*",
}
}
if archive.NameTemplate == "" {
archive.NameTemplate = defaultNameTemplate
if archive.Format == "binary" {
archive.NameTemplate = defaultBinaryNameTemplate
}
}
if len(archive.Builds) == 0 {
for _, build := range ctx.Config.Builds {
archive.Builds = append(archive.Builds, build.ID)
}
}
ids[archive.ID]++
}
for id, cont := range ids {
if cont > 1 {
return fmt.Errorf("found %d archives with the ID '%s', please fix your config", cont, id)
}
}
return nil
@@ -66,26 +93,34 @@ func (Pipe) Default(ctx *context.Context) error {
// Run the pipe
func (Pipe) Run(ctx *context.Context) error {
var g errgroup.Group // TODO: use semerrgroup here
var filtered = ctx.Artifacts.Filter(artifact.ByType(artifact.Binary))
for group, artifacts := range filtered.GroupByPlatform() {
log.Debugf("group %s has %d binaries", group, len(artifacts))
artifacts := artifacts
g.Go(func() error {
if packageFormat(ctx, artifacts[0].Goos) == "binary" {
return skip(ctx, artifacts)
}
return create(ctx, artifacts)
})
var g = semerrgroup.New(ctx.Parallelism)
for _, archive := range ctx.Config.Archives {
archive := archive
var filtered = ctx.Artifacts.Filter(
artifact.And(
artifact.ByType(artifact.Binary),
artifact.ByIDs(archive.Builds...),
),
)
for group, artifacts := range filtered.GroupByPlatform() {
log.Debugf("group %s has %d binaries", group, len(artifacts))
artifacts := artifacts
g.Go(func() error {
if packageFormat(archive, artifacts[0].Goos) == "binary" {
return skip(ctx, archive, artifacts)
}
return create(ctx, archive, artifacts)
})
}
}
return g.Wait()
}
func create(ctx *context.Context, binaries []artifact.Artifact) error {
var format = packageFormat(ctx, binaries[0].Goos)
func create(ctx *context.Context, archive config.Archive, binaries []artifact.Artifact) error {
var format = packageFormat(archive, binaries[0].Goos)
folder, err := tmpl.New(ctx).
WithArtifact(binaries[0], ctx.Config.Archive.Replacements).
Apply(ctx.Config.Archive.NameTemplate)
WithArtifact(binaries[0], archive.Replacements).
Apply(archive.NameTemplate)
if err != nil {
return err
}
@@ -107,16 +142,16 @@ func create(ctx *context.Context, binaries []artifact.Artifact) error {
log.Info("creating")
wrap, err := tmpl.New(ctx).
WithArtifact(binaries[0], ctx.Config.Archive.Replacements).
Apply(wrapFolder(ctx.Config.Archive))
WithArtifact(binaries[0], archive.Replacements).
Apply(wrapFolder(archive))
if err != nil {
return err
}
var a = NewEnhancedArchive(archive.New(archiveFile), wrap)
var a = NewEnhancedArchive(archivelib.New(archiveFile), wrap)
defer a.Close() // nolint: errcheck
files, err := findFiles(ctx)
files, err := findFiles(archive)
if err != nil {
return fmt.Errorf("failed to find files to archive: %s", err.Error())
}
@@ -139,6 +174,7 @@ func create(ctx *context.Context, binaries []artifact.Artifact) error {
Goarm: binaries[0].Goarm,
Extra: map[string]interface{}{
"Builds": binaries,
"ID": archive.ID,
},
})
return nil
@@ -155,12 +191,12 @@ func wrapFolder(a config.Archive) string {
}
}
func skip(ctx *context.Context, binaries []artifact.Artifact) error {
func skip(ctx *context.Context, archive config.Archive, binaries []artifact.Artifact) error {
for _, binary := range binaries {
log.WithField("binary", binary.Name).Info("skip archiving")
name, err := tmpl.New(ctx).
WithArtifact(binary, ctx.Config.Archive.Replacements).
Apply(ctx.Config.Archive.NameTemplate)
WithArtifact(binary, archive.Replacements).
Apply(archive.NameTemplate)
if err != nil {
return err
}
@@ -173,14 +209,15 @@ func skip(ctx *context.Context, binaries []artifact.Artifact) error {
Goarm: binary.Goarm,
Extra: map[string]interface{}{
"Builds": []artifact.Artifact{binary},
"ID": archive.ID,
},
})
}
return nil
}
func findFiles(ctx *context.Context) (result []string, err error) {
for _, glob := range ctx.Config.Archive.Files {
func findFiles(archive config.Archive) (result []string, err error) {
for _, glob := range archive.Files {
files, err := zglob.Glob(glob)
if err != nil {
return result, fmt.Errorf("globbing failed for pattern %s: %s", glob, err.Error())
@@ -194,13 +231,13 @@ func findFiles(ctx *context.Context) (result []string, err error) {
return
}
func packageFormat(ctx *context.Context, platform string) string {
for _, override := range ctx.Config.Archive.FormatOverrides {
func packageFormat(archive config.Archive, platform string) string {
for _, override := range archive.FormatOverrides {
if strings.HasPrefix(platform, override.Goos) {
return override.Format
}
}
return ctx.Config.Archive.Format
return archive.Format
}
// NewEnhancedArchive enhances a pre-existing archive.Archive instance

View File

@@ -44,16 +44,20 @@ func TestRunPipe(t *testing.T) {
config.Project{
Dist: dist,
ProjectName: "foobar",
Archive: config.Archive{
NameTemplate: defaultNameTemplate,
Files: []string{
"README.*",
"./foo/**/*",
},
FormatOverrides: []config.FormatOverride{
{
Goos: "windows",
Format: "zip",
Archives: []config.Archive{
{
ID: "defaultarch",
Builds: []string{"default"},
NameTemplate: defaultNameTemplate,
Files: []string{
"README.*",
"./foo/**/*",
},
FormatOverrides: []config.FormatOverride{
{
Goos: "windows",
Format: "zip",
},
},
},
},
@@ -67,6 +71,7 @@ func TestRunPipe(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
}
var windowsBuild = artifact.Artifact{
@@ -78,15 +83,19 @@ func TestRunPipe(t *testing.T) {
Extra: map[string]interface{}{
"Binary": "mybin",
"Extension": ".exe",
"ID": "default",
},
}
ctx.Artifacts.Add(darwinBuild)
ctx.Artifacts.Add(windowsBuild)
ctx.Version = "0.0.1"
ctx.Git.CurrentTag = "v0.0.1"
ctx.Config.Archive.Format = format
ctx.Config.Archives[0].Format = format
require.NoError(tt, Pipe{}.Run(ctx))
var archives = ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableArchive))
for _, arch := range archives.List() {
require.Equal(t, "defaultarch", arch.Extra["ID"].(string), "all archives should have the archive ID set")
}
require.Len(tt, archives.List(), 2)
darwin := archives.Filter(artifact.ByGoos("darwin")).List()[0]
windows := archives.Filter(artifact.ByGoos("windows")).List()[0]
@@ -175,9 +184,12 @@ func TestRunPipeBinary(t *testing.T) {
var ctx = context.New(
config.Project{
Dist: dist,
Archive: config.Archive{
Format: "binary",
NameTemplate: defaultBinaryNameTemplate,
Archives: []config.Archive{
{
Format: "binary",
NameTemplate: defaultBinaryNameTemplate,
Builds: []string{"default"},
},
},
},
)
@@ -191,6 +203,7 @@ func TestRunPipeBinary(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
})
ctx.Artifacts.Add(artifact.Artifact{
@@ -202,6 +215,7 @@ func TestRunPipeBinary(t *testing.T) {
Extra: map[string]interface{}{
"Binary": "mybin",
"Ext": ".exe",
"ID": "default",
},
})
require.NoError(t, Pipe{}.Run(ctx))
@@ -217,9 +231,12 @@ func TestRunPipeDistRemoved(t *testing.T) {
var ctx = context.New(
config.Project{
Dist: "/path/nope",
Archive: config.Archive{
NameTemplate: "nope",
Format: "zip",
Archives: []config.Archive{
{
NameTemplate: "nope",
Format: "zip",
Builds: []string{"default"},
},
},
},
)
@@ -233,6 +250,7 @@ func TestRunPipeDistRemoved(t *testing.T) {
Extra: map[string]interface{}{
"Binary": "mybin",
"Extension": ".exe",
"ID": "default",
},
})
require.EqualError(t, Pipe{}.Run(ctx), `failed to create directory /path/nope/nope.zip: open /path/nope/nope.zip: no such file or directory`)
@@ -249,11 +267,14 @@ func TestRunPipeInvalidGlob(t *testing.T) {
var ctx = context.New(
config.Project{
Dist: dist,
Archive: config.Archive{
NameTemplate: "foo",
Format: "zip",
Files: []string{
"[x-]",
Archives: []config.Archive{
{
Builds: []string{"default"},
NameTemplate: "foo",
Format: "zip",
Files: []string{
"[x-]",
},
},
},
},
@@ -267,6 +288,7 @@ func TestRunPipeInvalidGlob(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
})
require.EqualError(t, Pipe{}.Run(ctx), `failed to find files to archive: globbing failed for pattern [x-]: file does not exist`)
@@ -283,9 +305,12 @@ func TestRunPipeInvalidNameTemplate(t *testing.T) {
var ctx = context.New(
config.Project{
Dist: dist,
Archive: config.Archive{
NameTemplate: "foo{{ .fff }",
Format: "zip",
Archives: []config.Archive{
{
Builds: []string{"default"},
NameTemplate: "foo{{ .fff }",
Format: "zip",
},
},
},
)
@@ -298,6 +323,7 @@ func TestRunPipeInvalidNameTemplate(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
})
require.EqualError(t, Pipe{}.Run(ctx), `template: tmpl:1: unexpected "}" in operand`)
@@ -314,10 +340,13 @@ func TestRunPipeInvalidWrapInDirectoryTemplate(t *testing.T) {
var ctx = context.New(
config.Project{
Dist: dist,
Archive: config.Archive{
NameTemplate: "foo",
WrapInDirectory: "foo{{ .fff }",
Format: "zip",
Archives: []config.Archive{
{
Builds: []string{"default"},
NameTemplate: "foo",
WrapInDirectory: "foo{{ .fff }",
Format: "zip",
},
},
},
)
@@ -330,6 +359,7 @@ func TestRunPipeInvalidWrapInDirectoryTemplate(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
})
require.EqualError(t, Pipe{}.Run(ctx), `template: tmpl:1: unexpected "}" in operand`)
@@ -348,15 +378,18 @@ func TestRunPipeWrap(t *testing.T) {
var ctx = context.New(
config.Project{
Dist: dist,
Archive: config.Archive{
NameTemplate: "foo",
WrapInDirectory: "foo_{{ .Os }}",
Format: "tar.gz",
Replacements: map[string]string{
"darwin": "macOS",
},
Files: []string{
"README.*",
Archives: []config.Archive{
{
Builds: []string{"default"},
NameTemplate: "foo",
WrapInDirectory: "foo_{{ .Os }}",
Format: "tar.gz",
Replacements: map[string]string{
"darwin": "macOS",
},
Files: []string{
"README.*",
},
},
},
},
@@ -370,6 +403,7 @@ func TestRunPipeWrap(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
})
require.NoError(t, Pipe{}.Run(ctx))
@@ -395,61 +429,69 @@ func TestRunPipeWrap(t *testing.T) {
func TestDefault(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{
Archive: config.Archive{},
Archives: []config.Archive{},
},
}
require.NoError(t, Pipe{}.Default(ctx))
require.NotEmpty(t, ctx.Config.Archive.NameTemplate)
require.Equal(t, "tar.gz", ctx.Config.Archive.Format)
require.NotEmpty(t, ctx.Config.Archive.Files)
require.NotEmpty(t, ctx.Config.Archives[0].NameTemplate)
require.Equal(t, "tar.gz", ctx.Config.Archives[0].Format)
require.NotEmpty(t, ctx.Config.Archives[0].Files)
}
func TestDefaultSet(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{
Archive: config.Archive{
NameTemplate: "foo",
Format: "zip",
Files: []string{
"foo",
},
},
},
}
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, "foo", ctx.Config.Archive.NameTemplate)
require.Equal(t, "zip", ctx.Config.Archive.Format)
require.Equal(t, "foo", ctx.Config.Archive.Files[0])
}
func TestDefaultFormatBinary(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{
Archive: config.Archive{
Format: "binary",
},
},
}
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, defaultBinaryNameTemplate, ctx.Config.Archive.NameTemplate)
}
func TestFormatFor(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{
Archive: config.Archive{
Format: "tar.gz",
FormatOverrides: []config.FormatOverride{
{
Goos: "windows",
Format: "zip",
Archives: []config.Archive{
{
Builds: []string{"default"},
NameTemplate: "foo",
Format: "zip",
Files: []string{
"foo",
},
},
},
},
}
require.Equal(t, "zip", packageFormat(ctx, "windows"))
require.Equal(t, "tar.gz", packageFormat(ctx, "linux"))
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, "foo", ctx.Config.Archives[0].NameTemplate)
require.Equal(t, "zip", ctx.Config.Archives[0].Format)
require.Equal(t, "foo", ctx.Config.Archives[0].Files[0])
}
func TestDefaultFormatBinary(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{
Archives: []config.Archive{
{
Format: "binary",
},
},
},
}
require.NoError(t, Pipe{}.Default(ctx))
require.Equal(t, defaultBinaryNameTemplate, ctx.Config.Archives[0].NameTemplate)
}
func TestFormatFor(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{
Archives: []config.Archive{
{
Builds: []string{"default"},
Format: "tar.gz",
FormatOverrides: []config.FormatOverride{
{
Goos: "windows",
Format: "zip",
},
},
},
},
},
}
require.Equal(t, "zip", packageFormat(ctx.Config.Archives[0], "windows"))
require.Equal(t, "tar.gz", packageFormat(ctx.Config.Archives[0], "linux"))
}
func TestBinaryOverride(t *testing.T) {
@@ -471,15 +513,18 @@ func TestBinaryOverride(t *testing.T) {
config.Project{
Dist: dist,
ProjectName: "foobar",
Archive: config.Archive{
NameTemplate: defaultNameTemplate,
Files: []string{
"README.*",
},
FormatOverrides: []config.FormatOverride{
{
Goos: "windows",
Format: "binary",
Archives: []config.Archive{
{
Builds: []string{"default"},
NameTemplate: defaultNameTemplate,
Files: []string{
"README.*",
},
FormatOverrides: []config.FormatOverride{
{
Goos: "windows",
Format: "binary",
},
},
},
},
@@ -494,6 +539,7 @@ func TestBinaryOverride(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
})
ctx.Artifacts.Add(artifact.Artifact{
@@ -505,10 +551,11 @@ func TestBinaryOverride(t *testing.T) {
Extra: map[string]interface{}{
"Binary": "mybin",
"Ext": ".exe",
"ID": "default",
},
})
ctx.Version = "0.0.1"
ctx.Config.Archive.Format = format
ctx.Config.Archives[0].Format = format
require.NoError(tt, Pipe{}.Run(ctx))
var archives = ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableArchive))
@@ -537,13 +584,16 @@ func TestRunPipeSameArchiveFilename(t *testing.T) {
config.Project{
Dist: dist,
ProjectName: "foobar",
Archive: config.Archive{
NameTemplate: "same-filename",
Files: []string{
"README.*",
"./foo/**/*",
Archives: []config.Archive{
{
Builds: []string{"default"},
NameTemplate: "same-filename",
Files: []string{
"README.*",
"./foo/**/*",
},
Format: "tar.gz",
},
Format: "tar.gz",
},
},
)
@@ -555,6 +605,7 @@ func TestRunPipeSameArchiveFilename(t *testing.T) {
Type: artifact.Binary,
Extra: map[string]interface{}{
"Binary": "mybin",
"ID": "default",
},
})
ctx.Artifacts.Add(artifact.Artifact{
@@ -566,6 +617,7 @@ func TestRunPipeSameArchiveFilename(t *testing.T) {
Extra: map[string]interface{}{
"Binary": "mybin",
"Extension": ".exe",
"ID": "default",
},
})
ctx.Version = "0.0.1"
@@ -610,3 +662,19 @@ func TestWrapInDirectory(t *testing.T) {
}))
})
}
func TestSeveralArchivesWithTheSameID(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{
Archives: []config.Archive{
{
ID: "a",
},
{
ID: "a",
},
},
},
}
require.EqualError(t, Pipe{}.Default(ctx), "found 2 archives with the ID 'a', please fix your config")
}

View File

@@ -53,7 +53,7 @@ func (Pipe) Default(ctx *context.Context) error {
}
for id, cont := range ids {
if cont > 1 {
return fmt.Errorf("there are more than %d builds with the ID '%s', please fix your config", cont, id)
return fmt.Errorf("found %d builds with the ID '%s', please fix your config", cont, id)
}
}
return nil

View File

@@ -235,7 +235,7 @@ func TestSeveralBuildsWithTheSameID(t *testing.T) {
},
},
}
assert.EqualError(t, Pipe{}.Default(ctx), "there are more than 2 builds with the ID 'a', please fix your config")
assert.EqualError(t, Pipe{}.Default(ctx), "found 2 builds with the ID 'a', please fix your config")
}
func TestDefaultPartialBuilds(t *testing.T) {

View File

@@ -34,13 +34,13 @@ func TestFillBasicData(t *testing.T) {
assert.Contains(t, ctx.Config.Builds[0].Goos, "linux")
assert.Contains(t, ctx.Config.Builds[0].Goarch, "386")
assert.Contains(t, ctx.Config.Builds[0].Goarch, "amd64")
assert.Equal(t, "tar.gz", ctx.Config.Archive.Format)
assert.Equal(t, "tar.gz", ctx.Config.Archives[0].Format)
assert.Contains(t, ctx.Config.Brew.Install, "bin.install \"goreleaser\"")
assert.Empty(t, ctx.Config.Dockers)
assert.Equal(t, "https://github.com", ctx.Config.GitHubURLs.Download)
assert.NotEmpty(t, ctx.Config.Archive.NameTemplate)
assert.NotEmpty(t, ctx.Config.Archives[0].NameTemplate)
assert.NotEmpty(t, ctx.Config.Builds[0].Ldflags)
assert.NotEmpty(t, ctx.Config.Archive.Files)
assert.NotEmpty(t, ctx.Config.Archives[0].Files)
assert.NotEmpty(t, ctx.Config.Dist)
}

View File

@@ -13,8 +13,8 @@ before:
builds:
- env:
- CGO_ENABLED=0
archive:
replacements:
archives:
- replacements:
darwin: Darwin
linux: Linux
windows: Windows

View File

@@ -148,13 +148,14 @@ type FormatOverride struct {
// Archive config used for the archive
type Archive struct {
NameTemplate string `yaml:"name_template,omitempty"`
Replacements map[string]string `yaml:",omitempty"`
Format string `yaml:",omitempty"`
FormatOverrides []FormatOverride `yaml:"format_overrides,omitempty"`
WrapInDirectory string `yaml:"wrap_in_directory,omitempty"`
Files []string `yaml:",omitempty"`
ID string `yaml:",omitempty"`
Builds []string `yaml:",omitempty"`
NameTemplate string `yaml:"name_template,omitempty"`
Replacements map[string]string `yaml:",omitempty"`
Format string `yaml:",omitempty"`
FormatOverrides []FormatOverride `yaml:"format_overrides,omitempty"`
WrapInDirectory string `yaml:"wrap_in_directory,omitempty"`
Files []string `yaml:",omitempty"`
}
// Release config used for the GitHub release
@@ -312,7 +313,8 @@ type Project struct {
Brew Homebrew `yaml:",omitempty"`
Scoop Scoop `yaml:",omitempty"`
Builds []Build `yaml:",omitempty"`
Archive Archive `yaml:",omitempty"`
Archive Archive `yaml:",omitempty"` // TODO: remove this
Archives []Archive `yaml:",omitempty"`
NFPM NFPM `yaml:",omitempty"`
Snapcraft Snapcraft `yaml:",omitempty"`
Snapshot Snapshot `yaml:",omitempty"`

View File

@@ -39,8 +39,8 @@ var Defaulters = []Defaulter{
snapshot.Pipe{},
release.Pipe{},
project.Pipe{},
archive.Pipe{},
build.Pipe{},
archive.Pipe{},
nfpm.Pipe{},
snapcraft.Pipe{},
checksums.Pipe{},

View File

@@ -6,63 +6,72 @@ weight: 40
---
The binaries built will be archived together with the `README` and `LICENSE` files into a
`tar.gz` file. In the `archive` section you can customize the archive name,
`tar.gz` file. In the `archives` section you can customize the archive name,
additional files, and format.
Here is a commented `archive` section with all fields specified:
Here is a commented `archives` section with all fields specified:
```yml
# .goreleaser.yml
archive:
# Archive name template.
# Defaults:
# - if format is `tar.gz`, `gz` or `zip`:
# - `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
# - if format is `binary`:
# - `{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
archives:
-
# ID of this archive.
# Defaults to `default`.
id: my-archive
# Replacements for GOOS and GOARCH in the archive name.
# Keys should be valid GOOSs or GOARCHs.
# Values are the respective replacements.
# Default is empty.
replacements:
amd64: 64-bit
386: 32-bit
darwin: macOS
linux: Tux
# Builds reference which build instances should be archived in this archive.
builds:
- default
# Set to true, if you want all files in the archive to be in a single directory.
# If set to true and you extract the archive 'goreleaser_Linux_arm64.tar.gz',
# you get a folder 'goreleaser_Linux_arm64'.
# If set to false, all files are extracted separately.
# You can also set it to a custom folder name (templating is supported).
# Default is false.
wrap_in_directory: true
# Archive name template.
# Defaults:
# - if format is `tar.gz`, `gz` or `zip`:
# - `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
# - if format is `binary`:
# - `{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
# Archive format. Valid options are `tar.gz`, `gz`, `zip` and `binary`.
# If format is `binary`, no archives are created and the binaries are instead
# uploaded directly.
# Default is `tar.gz`.
format: zip
# Replacements for GOOS and GOARCH in the archive name.
# Keys should be valid GOOSs or GOARCHs.
# Values are the respective replacements.
# Default is empty.
replacements:
amd64: 64-bit
386: 32-bit
darwin: macOS
linux: Tux
# Can be used to change the archive formats for specific GOOSs.
# Most common use case is to archive as zip on Windows.
# Default is empty.
format_overrides:
- goos: windows
format: zip
# Set to true, if you want all files in the archive to be in a single directory.
# If set to true and you extract the archive 'goreleaser_Linux_arm64.tar.gz',
# you get a folder 'goreleaser_Linux_arm64'.
# If set to false, all files are extracted separately.
# You can also set it to a custom folder name (templating is supported).
# Default is false.
wrap_in_directory: true
# Additional files/globs you want to add to the archive.
# Defaults are any files matching `LICENCE*`, `LICENSE*`,
# `README*` and `CHANGELOG*` (case-insensitive).
files:
- LICENSE.txt
- README.md
- CHANGELOG.md
- docs/*
- design/*.png
- templates/**/*
# Archive format. Valid options are `tar.gz`, `gz`, `zip` and `binary`.
# If format is `binary`, no archives are created and the binaries are instead
# uploaded directly.
# Default is `tar.gz`.
format: zip
# Can be used to change the archive formats for specific GOOSs.
# Most common use case is to archive as zip on Windows.
# Default is empty.
format_overrides:
- goos: windows
format: zip
# Additional files/globs you want to add to the archive.
# Defaults are any files matching `LICENCE*`, `LICENSE*`,
# `README*` and `CHANGELOG*` (case-insensitive).
files:
- LICENSE.txt
- README.md
- CHANGELOG.md
- docs/*
- design/*.png
- templates/**/*
```
> Learn more about the [name template engine](/templates).
@@ -80,8 +89,8 @@ A working hack is to use something like this:
```yaml
# goreleaser.yml
archive:
files:
archives:
- files:
- none*
```

View File

@@ -33,6 +33,27 @@ to this:
-->
### archive
> since 2019-04-16
We now allow multiple archives, so the `archive` statement will be removed.
Change this:
```yaml
archive:
format: zip
```
to this:
```yaml
archives:
- id: foo
format: zip
```
### docker.binary
> since 2018-10-01