Skip to content

Commit

Permalink
feat: allow to template archives.files.info
Browse files Browse the repository at this point in the history
Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
  • Loading branch information
caarlos0 committed Dec 11, 2022
1 parent ddf7660 commit 9b82464
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 62 deletions.
20 changes: 20 additions & 0 deletions internal/archivefiles/archivefiles.go
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"path/filepath"
"sort"
"time"

"github.com/caarlos0/log"
"github.com/goreleaser/fileglob"
Expand All @@ -26,6 +27,25 @@ func Eval(template *tmpl.Template, files []config.File) ([]config.File, error) {
return result, fmt.Errorf("globbing failed for pattern %s: %w", replaced, err)
}

f.Info.Owner, err = template.Apply(f.Info.Owner)
if err != nil {
return result, fmt.Errorf("failed to apply template %s: %w", f.Info.Owner, err)
}
f.Info.Group, err = template.Apply(f.Info.Group)
if err != nil {
return result, fmt.Errorf("failed to apply template %s: %w", f.Info.Group, err)
}
f.Info.MTime, err = template.Apply(f.Info.MTime)
if err != nil {
return result, fmt.Errorf("failed to apply template %s: %w", f.Info.MTime, err)
}
if f.Info.MTime != "" {
f.Info.ParsedMTime, err = time.Parse(time.RFC3339Nano, f.Info.MTime)
if err != nil {
return result, fmt.Errorf("failed to parse %s: %w", f.Info.MTime, err)
}
}

for _, file := range files {
result = append(result, config.File{
Source: file,
Expand Down
134 changes: 105 additions & 29 deletions internal/archivefiles/archivefiles_test.go
Expand Up @@ -4,6 +4,7 @@ import (
"testing"
"time"

"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
Expand All @@ -12,7 +13,82 @@ import (

func TestEval(t *testing.T) {
now := time.Now().Truncate(time.Second)
tmpl := tmpl.New(context.New(config.Project{}))
ctx := context.New(config.Project{
Env: []string{"OWNER=carlos"},
})
ctx.Git.CommitDate = now
tmpl := tmpl.New(ctx)

t.Run("templated info", func(t *testing.T) {
result, err := Eval(tmpl, []config.File{
{
Source: "./testdata/**/d.txt",
Destination: "var/foobar/d.txt",
Info: config.FileInfo{
MTime: "{{.CommitDate}}",
Owner: "{{ .Env.OWNER }}",
Group: "{{ .Env.OWNER }}",
},
},
})

require.NoError(t, err)
require.Equal(t, []config.File{
{
Source: "testdata/a/b/c/d.txt",
Destination: "var/foobar/d.txt/testdata/a/b/c/d.txt",
Info: config.FileInfo{
MTime: now.UTC().Format(time.RFC3339),
ParsedMTime: now.UTC(),
Owner: "carlos",
Group: "carlos",
},
},
}, result)
})

t.Run("template info errors", func(t *testing.T) {
t.Run("owner", func(t *testing.T) {
_, err := Eval(tmpl, []config.File{{
Source: "./testdata/**/d.txt",
Destination: "var/foobar/d.txt",
Info: config.FileInfo{
Owner: "{{ .Env.NOPE }}",
},
}})
testlib.RequireTemplateError(t, err)
})
t.Run("group", func(t *testing.T) {
_, err := Eval(tmpl, []config.File{{
Source: "./testdata/**/d.txt",
Destination: "var/foobar/d.txt",
Info: config.FileInfo{
Group: "{{ .Env.NOPE }}",
},
}})
testlib.RequireTemplateError(t, err)
})
t.Run("mtime", func(t *testing.T) {
_, err := Eval(tmpl, []config.File{{
Source: "./testdata/**/d.txt",
Destination: "var/foobar/d.txt",
Info: config.FileInfo{
MTime: "{{ .Env.NOPE }}",
},
}})
testlib.RequireTemplateError(t, err)
})
t.Run("mtime format", func(t *testing.T) {
_, err := Eval(tmpl, []config.File{{
Source: "./testdata/**/d.txt",
Destination: "var/foobar/d.txt",
Info: config.FileInfo{
MTime: "2005-123-123",
},
}})
require.Error(t, err)
})
})

t.Run("single file", func(t *testing.T) {
result, err := Eval(tmpl, []config.File{
Expand Down Expand Up @@ -68,10 +144,10 @@ func TestEval(t *testing.T) {
Source: "./testdata/a",
Destination: "usr/local/test",
Info: config.FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o755,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o755,
ParsedMTime: now,
},
},
})
Expand All @@ -82,30 +158,30 @@ func TestEval(t *testing.T) {
Source: "testdata/a/a.txt",
Destination: "usr/local/test/testdata/a/a.txt",
Info: config.FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o755,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o755,
ParsedMTime: now,
},
},
{
Source: "testdata/a/b/a.txt",
Destination: "usr/local/test/testdata/a/b/a.txt",
Info: config.FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o755,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o755,
ParsedMTime: now,
},
},
{
Source: "testdata/a/b/c/d.txt",
Destination: "usr/local/test/testdata/a/b/c/d.txt",
Info: config.FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o755,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o755,
ParsedMTime: now,
},
},
}, result)
Expand All @@ -118,10 +194,10 @@ func TestEval(t *testing.T) {
Destination: "usr/local/test",
StripParent: true,
Info: config.FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o755,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o755,
ParsedMTime: now,
},
},
})
Expand All @@ -132,20 +208,20 @@ func TestEval(t *testing.T) {
Source: "testdata/a/a.txt",
Destination: "usr/local/test/a.txt",
Info: config.FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o755,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o755,
ParsedMTime: now,
},
},
{
Source: "testdata/a/b/c/d.txt",
Destination: "usr/local/test/d.txt",
Info: config.FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o755,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o755,
ParsedMTime: now,
},
},
}, result)
Expand Down
4 changes: 2 additions & 2 deletions pkg/archive/gzip/gzip.go
Expand Up @@ -48,10 +48,10 @@ func (a Archive) Add(f config.File) error {
return nil
}
a.gw.Header.Name = f.Destination
if f.Info.MTime.IsZero() {
if f.Info.ParsedMTime.IsZero() {
a.gw.Header.ModTime = info.ModTime()
} else {
a.gw.Header.ModTime = f.Info.MTime
a.gw.Header.ModTime = f.Info.ParsedMTime
}
_, err = io.Copy(a.gw, file)
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/archive/gzip/gzip_test.go
Expand Up @@ -63,7 +63,7 @@ func TestGzFileCustomMtime(t *testing.T) {
Destination: "sub1/sub2/subfoo.txt",
Source: "../testdata/sub1/sub2/subfoo.txt",
Info: config.FileInfo{
MTime: now,
ParsedMTime: now,
},
}))
require.NoError(t, archive.Close())
Expand Down
4 changes: 2 additions & 2 deletions pkg/archive/tar/tar.go
Expand Up @@ -45,8 +45,8 @@ func (a Archive) Add(f config.File) error {
return fmt.Errorf("%s: %w", f.Source, err)
}
header.Name = f.Destination
if !f.Info.MTime.IsZero() {
header.ModTime = f.Info.MTime
if !f.Info.ParsedMTime.IsZero() {
header.ModTime = f.Info.ParsedMTime
}
if f.Info.Mode != 0 {
header.Mode = int64(f.Info.Mode)
Expand Down
8 changes: 4 additions & 4 deletions pkg/archive/tar/tar_test.go
Expand Up @@ -114,10 +114,10 @@ func TestTarFileInfo(t *testing.T) {
Source: "../testdata/foo.txt",
Destination: "nope.txt",
Info: config.FileInfo{
Mode: 0o755,
Owner: "carlos",
Group: "root",
MTime: now,
Mode: 0o755,
Owner: "carlos",
Group: "root",
ParsedMTime: now,
},
}))

Expand Down
8 changes: 4 additions & 4 deletions pkg/archive/targz/targz_test.go
Expand Up @@ -119,10 +119,10 @@ func TestTarGzFileInfo(t *testing.T) {
Source: "../testdata/foo.txt",
Destination: "nope.txt",
Info: config.FileInfo{
Mode: 0o755,
Owner: "carlos",
Group: "root",
MTime: now,
Mode: 0o755,
Owner: "carlos",
Group: "root",
ParsedMTime: now,
},
}))

Expand Down
8 changes: 4 additions & 4 deletions pkg/archive/tarxz/tarxz_test.go
Expand Up @@ -118,10 +118,10 @@ func TestTarXzFileInfo(t *testing.T) {
Source: "../testdata/foo.txt",
Destination: "nope.txt",
Info: config.FileInfo{
Mode: 0o755,
Owner: "carlos",
Group: "root",
MTime: now,
Mode: 0o755,
Owner: "carlos",
Group: "root",
ParsedMTime: now,
},
}))

Expand Down
4 changes: 2 additions & 2 deletions pkg/archive/zip/zip.go
Expand Up @@ -49,8 +49,8 @@ func (a Archive) Add(f config.File) error {
}
header.Name = f.Destination
header.Method = zip.Deflate
if !f.Info.MTime.IsZero() {
header.Modified = f.Info.MTime
if !f.Info.ParsedMTime.IsZero() {
header.Modified = f.Info.ParsedMTime
}
if f.Info.Mode != 0 {
header.SetMode(f.Info.Mode)
Expand Down
8 changes: 4 additions & 4 deletions pkg/archive/zip/zip_test.go
Expand Up @@ -117,10 +117,10 @@ func TestZipFileInfo(t *testing.T) {
Source: "../testdata/foo.txt",
Destination: "nope.txt",
Info: config.FileInfo{
Mode: 0o755,
Owner: "carlos",
Group: "root",
MTime: now,
Mode: 0o755,
Owner: "carlos",
Group: "root",
ParsedMTime: now,
},
}))

Expand Down
9 changes: 5 additions & 4 deletions pkg/config/config.go
Expand Up @@ -428,10 +428,11 @@ type File struct {

// FileInfo is the file info of a file.
type FileInfo struct {
Owner string `yaml:"owner,omitempty" json:"owner,omitempty"`
Group string `yaml:"group,omitempty" json:"group,omitempty"`
Mode os.FileMode `yaml:"mode,omitempty" json:"mode,omitempty"`
MTime time.Time `yaml:"mtime,omitempty" json:"mtime,omitempty"`
Owner string `yaml:"owner,omitempty" json:"owner,omitempty"`
Group string `yaml:"group,omitempty" json:"group,omitempty"`
Mode os.FileMode `yaml:"mode,omitempty" json:"mode,omitempty"`
MTime string `yaml:"mtime,omitempty" json:"mtime,omitempty"`
ParsedMTime time.Time `yaml:"-" json:"-"`
}

// UnmarshalYAML is a custom unmarshaler that wraps strings in arrays.
Expand Down
9 changes: 5 additions & 4 deletions pkg/config/config_archive_files_test.go
Expand Up @@ -84,10 +84,11 @@ files:
Source: "./foobar",
Destination: "./barzaz",
Info: FileInfo{
Owner: "carlos",
Group: "users",
Mode: 0o644,
MTime: now,
Owner: "carlos",
Group: "users",
Mode: 0o644,
MTime: now.Format(time.RFC3339Nano),
ParsedMTime: time.Time{},
},
},
}, actual.Files)
Expand Down
11 changes: 9 additions & 2 deletions www/docs/customization/archive.md
Expand Up @@ -83,11 +83,18 @@ archives:
# Not all fields are supported by all formats available formats.
# Defaults to the file info of the actual file if not provided.
info:
# Templateable (since v1.14.0)
owner: root

# Templateable (since v1.14.0)
group: root

# Must be in time.RFC3339Nano format.
# Templateable (since v1.14.0)
mtime: '{{ .CommitDate }}'

# File mode.
mode: 0644
# format is `time.RFC3339Nano`
mtime: 2008-01-02T15:04:05Z

# Before and after hooks for each archive.
# Skipped if archive format is binary.
Expand Down

0 comments on commit 9b82464

Please sign in to comment.