1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-01-06 03:13:48 +02:00

Merge branch 'master' into sem

This commit is contained in:
Carlos Alexandro Becker 2018-07-09 21:11:51 -07:00
commit ccdd761c50
No known key found for this signature in database
GPG Key ID: E61E2F7DC14AB940
38 changed files with 451 additions and 625 deletions

View File

@ -9,8 +9,6 @@ export PATH := ./bin:$(PATH)
setup:
go get -u golang.org/x/tools/cmd/stringer
go get -u golang.org/x/tools/cmd/cover
# TODO: temporary hack for https://github.com/golang/go/issues/21387
(cd $$GOPATH/src/golang.org/x/tools; git checkout ae8cc594552814363a7aeeb4f2825515a771fa38; go install ./cmd/stringer/... ; go install ./cmd/cover/...)
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh
curl -sfL https://install.goreleaser.com/github.com/gohugoio/hugo.sh | sh
curl -sfL https://install.goreleaser.com/github.com/caarlos0/bandep.sh | sh

View File

@ -1,7 +1,6 @@
package golang
import (
"bytes"
"fmt"
"go/ast"
"go/parser"
@ -9,14 +8,13 @@ import (
"os"
"os/exec"
"strings"
"text/template"
"time"
"github.com/apex/log"
api "github.com/goreleaser/goreleaser/build"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/pkg/errors"
)
@ -62,19 +60,19 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
cmd = append(cmd, build.Flags...)
asmflags, err := processFlags(ctx, build.Asmflags, "asmflags", "-asmflags=")
asmflags, err := processFlags(ctx, build.Asmflags, "-asmflags=")
if err != nil {
return err
}
cmd = append(cmd, asmflags...)
gcflags, err := processFlags(ctx, build.Gcflags, "gcflags", "-gcflags=")
gcflags, err := processFlags(ctx, build.Gcflags, "-gcflags=")
if err != nil {
return err
}
cmd = append(cmd, gcflags...)
ldflags, err := processFlags(ctx, build.Ldflags, "ldflags", "-ldflags=")
ldflags, err := processFlags(ctx, build.Ldflags, "-ldflags=")
if err != nil {
return err
}
@ -105,10 +103,10 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
return nil
}
func processFlags(ctx *context.Context, flags []string, flagName string, flagPrefix string) ([]string, error) {
func processFlags(ctx *context.Context, flags []string, flagPrefix string) ([]string, error) {
processed := make([]string, 0, len(flags))
for _, rawFlag := range flags {
flag, err := processField(ctx, rawFlag, flagName)
flag, err := tmpl.New(ctx).Apply(rawFlag)
if err != nil {
return nil, err
}
@ -117,36 +115,6 @@ func processFlags(ctx *context.Context, flags []string, flagName string, flagPre
return processed, nil
}
func processField(ctx *context.Context, field string, fieldName string) (string, error) {
var data = struct {
Commit string
Tag string
Version string
Date string
Env map[string]string
}{
Commit: ctx.Git.Commit,
Tag: ctx.Git.CurrentTag,
Version: ctx.Version,
Date: time.Now().UTC().Format(time.RFC3339),
Env: ctx.Env,
}
var out bytes.Buffer
t, err := template.New(fieldName).
Funcs(template.FuncMap{
"time": func(s string) string {
return time.Now().UTC().Format(s)
},
}).
Option("missingkey=error").
Parse(field)
if err != nil {
return "", err
}
err = t.Execute(&out, data)
return out.String(), err
}
func run(ctx *context.Context, command, env []string) error {
/* #nosec */
var cmd = exec.CommandContext(ctx, command[0], command[1:]...)

View File

@ -12,6 +12,7 @@ import (
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/stretchr/testify/assert"
)
@ -64,6 +65,7 @@ func TestWithDefaults(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var build = Default.WithDefaults(ctx.Config.Builds[0])
assert.ElementsMatch(t, build.Targets, testcase.targets)
})
@ -90,6 +92,7 @@ func TestBuild(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var build = ctx.Config.Builds[0]
for _, target := range build.Targets {
var ext string
@ -168,6 +171,7 @@ func TestBuildFailed(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var err = Default.Build(ctx, ctx.Config.Builds[0], api.Options{
Target: "darwin_amd64",
})
@ -189,6 +193,7 @@ func TestBuildInvalidTarget(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var build = ctx.Config.Builds[0]
var err = Default.Build(ctx, build, api.Options{
Target: target,
@ -215,10 +220,11 @@ func TestRunInvalidAsmflags(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var err = Default.Build(ctx, ctx.Config.Builds[0], api.Options{
Target: runtimeTarget,
})
assert.EqualError(t, err, `template: asmflags:1: unexpected "}" in operand`)
assert.EqualError(t, err, `template: tmpl:1: unexpected "}" in operand`)
}
func TestRunInvalidGcflags(t *testing.T) {
@ -237,10 +243,11 @@ func TestRunInvalidGcflags(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var err = Default.Build(ctx, ctx.Config.Builds[0], api.Options{
Target: runtimeTarget,
})
assert.EqualError(t, err, `template: gcflags:1: unexpected "}" in operand`)
assert.EqualError(t, err, `template: tmpl:1: unexpected "}" in operand`)
}
func TestRunInvalidLdflags(t *testing.T) {
@ -260,10 +267,11 @@ func TestRunInvalidLdflags(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
var err = Default.Build(ctx, ctx.Config.Builds[0], api.Options{
Target: runtimeTarget,
})
assert.EqualError(t, err, `template: ldflags:1: unexpected "}" in operand`)
assert.EqualError(t, err, `template: tmpl:1: unexpected "}" in operand`)
}
func TestRunPipeWithoutMainFunc(t *testing.T) {
@ -282,6 +290,7 @@ func TestRunPipeWithoutMainFunc(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
t.Run("empty", func(t *testing.T) {
ctx.Config.Builds[0].Main = ""
assert.EqualError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
@ -328,6 +337,7 @@ func TestRunPipeWithMainFuncNotInMainGoFile(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "5.6.7"
t.Run("empty", func(t *testing.T) {
ctx.Config.Builds[0].Main = ""
assert.NoError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
@ -349,25 +359,16 @@ func TestRunPipeWithMainFuncNotInMainGoFile(t *testing.T) {
}
func TestLdFlagsFullTemplate(t *testing.T) {
var config = config.Project{
Builds: []config.Build{
{
Ldflags: []string{
`-s -w -X main.version={{.Version}} -X main.tag={{.Tag}} -X main.date={{.Date}} -X main.commit={{.Commit}} -X "main.foo={{.Env.FOO}}" -X main.time={{ time "20060102" }}`,
},
},
},
}
var ctx = &context.Context{
Git: context.GitInfo{
CurrentTag: "v1.2.3",
Commit: "123",
},
Version: "1.2.3",
Config: config,
Env: map[string]string{"FOO": "123"},
}
flags, err := processField(ctx, ctx.Config.Builds[0].Ldflags[0], "ldflags")
flags, err := tmpl.New(ctx).
Apply(`-s -w -X main.version={{.Version}} -X main.tag={{.Tag}} -X main.date={{.Date}} -X main.commit={{.Commit}} -X "main.foo={{.Env.FOO}}" -X main.time={{ time "20060102" }}`)
assert.NoError(t, err)
assert.Contains(t, flags, "-s -w")
assert.Contains(t, flags, "-X main.version=1.2.3")
@ -381,19 +382,13 @@ func TestLdFlagsFullTemplate(t *testing.T) {
func TestInvalidTemplate(t *testing.T) {
for template, eerr := range map[string]string{
"{{ .Nope }": `template: ldflags:1: unexpected "}" in operand`,
"{{.Env.NOPE}}": `template: ldflags:1:6: executing "ldflags" at <.Env.NOPE>: map has no entry for key "NOPE"`,
"{{ .Nope }": `template: tmpl:1: unexpected "}" in operand`,
"{{.Env.NOPE}}": `template: tmpl:1:6: executing "tmpl" at <.Env.NOPE>: map has no entry for key "NOPE"`,
} {
t.Run(template, func(tt *testing.T) {
var config = config.Project{
Builds: []config.Build{
{Ldflags: []string{template}},
},
}
var ctx = &context.Context{
Config: config,
}
flags, err := processField(ctx, template, "ldflags")
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "3.4.1"
flags, err := tmpl.New(ctx).Apply(template)
assert.EqualError(tt, err, eerr)
assert.Empty(tt, flags)
})
@ -404,6 +399,7 @@ func TestProcessFlags(t *testing.T) {
var ctx = &context.Context{
Version: "1.2.3",
}
ctx.Git.CurrentTag = "5.6.7"
var source = []string{
"{{.Version}}",
@ -415,7 +411,7 @@ func TestProcessFlags(t *testing.T) {
"-testflag=flag",
}
flags, err := processFlags(ctx, source, "testflag", "-testflag=")
flags, err := processFlags(ctx, source, "-testflag=")
assert.NoError(t, err)
assert.Len(t, flags, 2)
assert.Equal(t, expected, flags)
@ -428,9 +424,9 @@ func TestProcessFlagsInvalid(t *testing.T) {
"{{.Version}",
}
var expected = `template: testflag:1: unexpected "}" in operand`
var expected = `template: tmpl:1: unexpected "}" in operand`
flags, err := processFlags(ctx, source, "testflag", "-testflag=")
flags, err := processFlags(ctx, source, "-testflag=")
assert.EqualError(t, err, expected)
assert.Nil(t, flags)
}

View File

@ -9,7 +9,7 @@ import (
"github.com/google/go-github/github"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/nametemplate"
"github.com/goreleaser/goreleaser/internal/tmpl"
"golang.org/x/oauth2"
)
@ -90,7 +90,7 @@ func (c *githubClient) CreateFile(
func (c *githubClient) CreateRelease(ctx *context.Context, body string) (int64, error) {
var release *github.RepositoryRelease
title, err := nametemplate.Apply(ctx, ctx.Config.Release.NameTemplate)
title, err := tmpl.New(ctx).Apply(ctx.Config.Release.NameTemplate)
if err != nil {
return 0, err
}

View File

@ -1,62 +0,0 @@
// Package filenametemplate contains the code used to template names of
// goreleaser's packages and archives.
package filenametemplate
import (
"bytes"
"text/template"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
)
// Fields contains all accepted fields in the template string
type Fields struct {
Version string
Tag string
ProjectName string
Env map[string]string
Os string
Arch string
Arm string
Binary string
}
// NewFields returns a Fields instances filled with the data provided
func NewFields(ctx *context.Context, replacements map[string]string, artifacts ...artifact.Artifact) Fields {
// This will fail if artifacts is empty - should never be though...
var binary = artifacts[0].Extra["Binary"]
if len(artifacts) > 1 {
binary = ctx.Config.ProjectName
}
return Fields{
Env: ctx.Env,
Version: ctx.Version,
Tag: ctx.Git.CurrentTag,
ProjectName: ctx.Config.ProjectName,
Os: replace(replacements, artifacts[0].Goos),
Arch: replace(replacements, artifacts[0].Goarch),
Arm: replace(replacements, artifacts[0].Goarm),
Binary: binary,
}
}
// Apply applies the given fields to the given template and returns the
// evaluation and any error that might occur.
func Apply(tmpl string, fields Fields) (string, error) {
t, err := template.New(tmpl).Option("missingkey=error").Parse(tmpl)
if err != nil {
return "", err
}
var out bytes.Buffer
err = t.Execute(&out, fields)
return out.String(), err
}
func replace(replacements map[string]string, original string) string {
result := replacements[original]
if result == "" {
return original
}
return result
}

View File

@ -1,85 +0,0 @@
package filenametemplate
import (
"testing"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/stretchr/testify/assert"
)
func TestTemplate(t *testing.T) {
var ctx = context.New(config.Project{
ProjectName: "proj",
})
ctx.Env = map[string]string{
"FOO": "bar",
}
ctx.Version = "1.0.0"
ctx.Git.CurrentTag = "v1.0.0"
var artifact = artifact.Artifact{
Name: "not-this-binary",
Goarch: "amd64",
Goos: "linux",
Goarm: "6",
Extra: map[string]string{
"Binary": "binary",
},
}
var fields = NewFields(ctx, map[string]string{"linux": "Linux"}, artifact)
for expect, tmpl := range map[string]string{
"bar": "{{.Env.FOO}}",
"Linux": "{{.Os}}",
"amd64": "{{.Arch}}",
"6": "{{.Arm}}",
"1.0.0": "{{.Version}}",
"v1.0.0": "{{.Tag}}",
"binary": "{{.Binary}}",
"proj": "{{.ProjectName}}",
} {
tmpl := tmpl
expect := expect
t.Run(expect, func(tt *testing.T) {
tt.Parallel()
result, err := Apply(tmpl, fields)
assert.NoError(tt, err)
assert.Equal(tt, expect, result)
})
}
}
func TestNewFields(t *testing.T) {
var ctx = context.New(config.Project{
ProjectName: "proj",
})
ctx.Version = "1.0.0"
ctx.Git.CurrentTag = "v1.0.0"
var artifact = artifact.Artifact{
Name: "not-this-binary",
Goarch: "amd64",
Goos: "linux",
Goarm: "6",
Extra: map[string]string{
"Binary": "binary",
},
}
var fields = NewFields(ctx, map[string]string{}, artifact, artifact)
assert.Equal(t, "proj", fields.Binary)
}
func TestInvalidTemplate(t *testing.T) {
var ctx = context.New(config.Project{})
var fields = NewFields(ctx, map[string]string{}, artifact.Artifact{})
result, err := Apply("{{.Foo}", fields)
assert.Empty(t, result)
assert.EqualError(t, err, `template: {{.Foo}:1: unexpected "}" in operand`)
}
func TestEnvNotFound(t *testing.T) {
var ctx = context.New(config.Project{})
var fields = NewFields(ctx, map[string]string{}, artifact.Artifact{})
result, err := Apply("{{.Env.FOO}}", fields)
assert.Empty(t, result)
assert.EqualError(t, err, `template: {{.Env.FOO}}:1:6: executing "{{.Env.FOO}}" at <.Env.FOO>: map has no entry for key "FOO"`)
}

View File

@ -1,38 +0,0 @@
// Package nametemplate provides common template function for releases and etc.
package nametemplate
import (
"bytes"
"text/template"
"time"
"github.com/goreleaser/goreleaser/context"
)
// Apply applies the given name template using the context as source.
func Apply(ctx *context.Context, tmpl string) (string, error) {
var out bytes.Buffer
t, err := template.New("release").
Option("missingkey=error").
Funcs(template.FuncMap{
"time": func(s string) string {
return time.Now().UTC().Format(s)
},
}).
Parse(tmpl)
if err != nil {
return "", err
}
err = t.Execute(&out, struct {
ProjectName string
Tag string
Version string
Env map[string]string
}{
ProjectName: ctx.Config.ProjectName,
Tag: ctx.Git.CurrentTag,
Version: ctx.Version,
Env: ctx.Env,
})
return out.String(), err
}

View File

@ -1,70 +0,0 @@
package nametemplate
import (
"testing"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/stretchr/testify/assert"
)
func TestEnv(t *testing.T) {
testCases := []struct {
desc string
in string
out string
}{
{
desc: "with env",
in: "{{ .Env.FOO }}",
out: "BAR",
},
{
desc: "with env",
in: "{{ .Env.BAR }}",
out: "",
},
}
var ctx = context.New(config.Project{})
ctx.Env = map[string]string{
"FOO": "BAR",
}
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
out, _ := Apply(ctx, tC.in)
assert.Equal(t, tC.out, out)
})
}
}
func TestFuncMap(t *testing.T) {
var ctx = context.New(config.Project{
ProjectName: "proj",
})
for _, tc := range []struct {
Template string
Name string
}{
{
Template: `{{ time "2006-01-02" }}`,
Name: "YYYY-MM-DD",
},
{
Template: `{{ time "01/02/2006" }}`,
Name: "MM/DD/YYYY",
},
{
Template: `{{ time "01/02/2006" }}`,
Name: "MM/DD/YYYY",
},
} {
out, err := Apply(ctx, tc.Template)
assert.NoError(t, err)
assert.NotEmpty(t, out)
}
}
func TestInvalidTemplate(t *testing.T) {
_, err := Apply(context.New(config.Project{}), "{{{.Foo}")
assert.EqualError(t, err, "template: release:1: unexpected \"{\" in command")
}

103
internal/tmpl/tmpl.go Normal file
View File

@ -0,0 +1,103 @@
// Package tmpl provides templating utilities for goreleser
package tmpl
import (
"bytes"
"text/template"
"time"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/masterminds/semver"
"github.com/pkg/errors"
)
// Template holds data that can be applied to a template string
type Template struct {
fields fields
}
type fields map[string]interface{}
const (
// general keys
projectName = "ProjectName"
version = "Version"
tag = "Tag"
commit = "Commit"
major = "Major"
minor = "Minor"
patch = "Patch"
env = "Env"
date = "Date"
timestamp = "Timestamp"
// artifact-only keys
os = "Os"
arch = "Arch"
arm = "Arm"
binary = "Binary"
)
// New Template
func New(ctx *context.Context) *Template {
return &Template{
fields: fields{
projectName: ctx.Config.ProjectName,
version: ctx.Version,
tag: ctx.Git.CurrentTag,
commit: ctx.Git.Commit,
env: ctx.Env,
date: time.Now().UTC().Format(time.RFC3339),
timestamp: time.Now().UTC().Unix(),
},
}
}
// WithArtifacts populate fields from the artifact and replacements
func (t *Template) WithArtifact(a artifact.Artifact, replacements map[string]string) *Template {
var bin = a.Extra[binary]
if bin == "" {
bin = t.fields[projectName].(string)
}
t.fields[os] = replace(replacements, a.Goos)
t.fields[arch] = replace(replacements, a.Goarch)
t.fields[arm] = replace(replacements, a.Goarm)
t.fields[binary] = bin
return t
}
// Apply applies the given string against the fields stored in the template.
func (t *Template) Apply(s string) (string, error) {
var out bytes.Buffer
tmpl, err := template.New("tmpl").
Option("missingkey=error").
Funcs(template.FuncMap{
"time": func(s string) string {
return time.Now().UTC().Format(s)
},
}).
Parse(s)
if err != nil {
return "", err
}
sv, err := semver.NewVersion(t.fields[tag].(string))
if err != nil {
return "", errors.Wrap(err, "tmpl")
}
t.fields[major] = sv.Major()
t.fields[minor] = sv.Minor()
t.fields[patch] = sv.Patch()
err = tmpl.Execute(&out, t.fields)
return out.String(), err
}
func replace(replacements map[string]string, original string) string {
result := replacements[original]
if result == "" {
return original
}
return result
}

152
internal/tmpl/tmpl_test.go Normal file
View File

@ -0,0 +1,152 @@
package tmpl
import (
"testing"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/stretchr/testify/assert"
)
func TestWithArtifact(t *testing.T) {
var ctx = context.New(config.Project{
ProjectName: "proj",
})
ctx.Env = map[string]string{
"FOO": "bar",
}
ctx.Version = "1.0.0"
ctx.Git.CurrentTag = "v1.0.0"
for expect, tmpl := range map[string]string{
"bar": "{{.Env.FOO}}",
"Linux": "{{.Os}}",
"amd64": "{{.Arch}}",
"6": "{{.Arm}}",
"1.0.0": "{{.Version}}",
"v1.0.0": "{{.Tag}}",
"binary": "{{.Binary}}",
"proj": "{{.ProjectName}}",
} {
tmpl := tmpl
expect := expect
t.Run(expect, func(tt *testing.T) {
tt.Parallel()
result, err := New(ctx).WithArtifact(
artifact.Artifact{
Name: "not-this-binary",
Goarch: "amd64",
Goos: "linux",
Goarm: "6",
Extra: map[string]string{
"Binary": "binary",
},
},
map[string]string{"linux": "Linux"},
).Apply(tmpl)
assert.NoError(tt, err)
assert.Equal(tt, expect, result)
})
}
t.Run("artifact without binary name", func(tt *testing.T) {
tt.Parallel()
result, err := New(ctx).WithArtifact(
artifact.Artifact{
Name: "another-binary",
Goarch: "amd64",
Goos: "linux",
Goarm: "6",
}, map[string]string{},
).Apply("{{ .Binary }}")
assert.NoError(tt, err)
assert.Equal(tt, ctx.Config.ProjectName, result)
})
t.Run("template using artifact fields with no artifact", func(tt *testing.T) {
tt.Parallel()
result, err := New(ctx).Apply("{{ .Os }}")
assert.EqualError(tt, err, `template: tmpl:1:3: executing "tmpl" at <.Os>: map has no entry for key "Os"`)
assert.Empty(tt, result)
})
}
func TestEnv(t *testing.T) {
testCases := []struct {
desc string
in string
out string
}{
{
desc: "with env",
in: "{{ .Env.FOO }}",
out: "BAR",
},
{
desc: "with env",
in: "{{ .Env.BAR }}",
out: "",
},
}
var ctx = context.New(config.Project{})
ctx.Env = map[string]string{
"FOO": "BAR",
}
ctx.Git.CurrentTag = "v1.2.3"
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
out, _ := New(ctx).Apply(tC.in)
assert.Equal(t, tC.out, out)
})
}
}
func TestFuncMap(t *testing.T) {
var ctx = context.New(config.Project{
ProjectName: "proj",
})
ctx.Git.CurrentTag = "v1.2.4"
for _, tc := range []struct {
Template string
Name string
}{
{
Template: `{{ time "2006-01-02" }}`,
Name: "YYYY-MM-DD",
},
{
Template: `{{ time "01/02/2006" }}`,
Name: "MM/DD/YYYY",
},
{
Template: `{{ time "01/02/2006" }}`,
Name: "MM/DD/YYYY",
},
} {
out, err := New(ctx).Apply(tc.Template)
assert.NoError(t, err)
assert.NotEmpty(t, out)
}
}
func TestInvalidTemplate(t *testing.T) {
_, err := New(context.New(config.Project{})).Apply("{{{.Foo}")
assert.EqualError(t, err, "template: tmpl:1: unexpected \"{\" in command")
}
func TestEnvNotFound(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "v1.2.4"
result, err := New(ctx).Apply("{{.Env.FOO}}")
assert.Empty(t, result)
assert.EqualError(t, err, `template: tmpl:1:6: executing "tmpl" at <.Env.FOO>: map has no entry for key "FOO"`)
}
// This should actually never happen...
func TestInvalidSemver(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "v1_2_3"
result, err := New(ctx).Apply("{{.Major}}")
assert.Empty(t, result)
assert.EqualError(t, err, `tmpl: Invalid Semantic Version`)
}

View File

@ -17,7 +17,7 @@ import (
"github.com/goreleaser/archive"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/filenametemplate"
"github.com/goreleaser/goreleaser/internal/tmpl"
)
const (
@ -77,10 +77,9 @@ func (Pipe) Run(ctx *context.Context) error {
func create(ctx *context.Context, binaries []artifact.Artifact) error {
var format = packageFormat(ctx, binaries[0].Goos)
folder, err := filenametemplate.Apply(
ctx.Config.Archive.NameTemplate,
filenametemplate.NewFields(ctx, ctx.Config.Archive.Replacements, binaries...),
)
folder, err := tmpl.New(ctx).
WithArtifact(binaries[0], ctx.Config.Archive.Replacements).
Apply(ctx.Config.Archive.NameTemplate)
if err != nil {
return err
}
@ -125,8 +124,9 @@ func create(ctx *context.Context, binaries []artifact.Artifact) error {
func skip(ctx *context.Context, binaries []artifact.Artifact) error {
for _, binary := range binaries {
log.WithField("binary", binary.Name).Info("skip archiving")
var fields = filenametemplate.NewFields(ctx, ctx.Config.Archive.Replacements, binary)
name, err := filenametemplate.Apply(ctx.Config.Archive.NameTemplate, fields)
name, err := tmpl.New(ctx).
WithArtifact(binary, ctx.Config.Archive.Replacements).
Apply(ctx.Config.Archive.NameTemplate)
if err != nil {
return err
}

View File

@ -13,6 +13,7 @@ import (
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDescription(t *testing.T) {
@ -74,14 +75,15 @@ func TestRunPipe(t *testing.T) {
},
})
ctx.Version = "0.0.1"
ctx.Git.CurrentTag = "v0.0.1"
ctx.Config.Archive.Format = format
assert.NoError(tt, Pipe{}.Run(ctx))
var archives = ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableArchive))
require.Len(tt, archives.List(), 2)
darwin := archives.Filter(artifact.ByGoos("darwin")).List()[0]
windows := archives.Filter(artifact.ByGoos("windows")).List()[0]
assert.Equal(tt, "foobar_0.0.1_darwin_amd64."+format, darwin.Name)
assert.Equal(tt, "foobar_0.0.1_windows_amd64.zip", windows.Name)
assert.Len(tt, archives.List(), 2)
})
}
@ -126,6 +128,7 @@ func TestRunPipeBinary(t *testing.T) {
},
)
ctx.Version = "0.0.1"
ctx.Git.CurrentTag = "v0.0.1"
ctx.Artifacts.Add(artifact.Artifact{
Goos: "darwin",
Goarch: "amd64",
@ -166,6 +169,7 @@ func TestRunPipeDistRemoved(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "v0.0.1"
ctx.Artifacts.Add(artifact.Artifact{
Goos: "windows",
Goarch: "amd64",
@ -200,6 +204,7 @@ func TestRunPipeInvalidGlob(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "v0.0.1"
ctx.Artifacts.Add(artifact.Artifact{
Goos: "darwin",
Goarch: "amd64",
@ -236,6 +241,7 @@ func TestRunPipeWrap(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "v0.0.1"
ctx.Artifacts.Add(artifact.Artifact{
Goos: "darwin",
Goarch: "amd64",
@ -359,6 +365,7 @@ func TestBinaryOverride(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "v0.0.1"
ctx.Artifacts.Add(artifact.Artifact{
Goos: "darwin",
Goarch: "amd64",

View File

@ -3,13 +3,10 @@
package build
import (
"bytes"
"os"
"os/exec"
"path/filepath"
"strings"
"text/template"
"time"
"github.com/apex/log"
"github.com/pkg/errors"
@ -22,6 +19,7 @@ import (
// langs to init
_ "github.com/goreleaser/goreleaser/internal/builders/golang"
"github.com/goreleaser/goreleaser/internal/semaphore"
"github.com/goreleaser/goreleaser/internal/tmpl"
)
// Pipe for build
@ -101,7 +99,7 @@ func runHook(ctx *context.Context, env []string, hook string) error {
func doBuild(ctx *context.Context, build config.Build, target string) error {
var ext = extFor(target)
binary, err := binary(ctx, build)
binary, err := tmpl.New(ctx).Apply(build.Binary)
if err != nil {
return err
}
@ -118,31 +116,6 @@ func doBuild(ctx *context.Context, build config.Build, target string) error {
})
}
func binary(ctx *context.Context, build config.Build) (string, error) {
var data = struct {
Commit string
Tag string
Version string
Date string
Env map[string]string
}{
Commit: ctx.Git.Commit,
Tag: ctx.Git.CurrentTag,
Version: ctx.Version,
Date: time.Now().UTC().Format(time.RFC3339),
Env: ctx.Env,
}
var out bytes.Buffer
t, err := template.New("binary").
Option("missingkey=error").
Parse(build.Binary)
if err != nil {
return "", err
}
err = t.Execute(&out, data)
return out.String(), err
}
func extFor(target string) string {
if strings.Contains(target, "windows") {
return ".exe"

View File

@ -11,6 +11,7 @@ import (
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/testlib"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/stretchr/testify/assert"
)
@ -84,6 +85,7 @@ func TestRunPipe(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "2.4.5"
assert.NoError(t, Pipe{}.Run(ctx))
assert.Equal(t, ctx.Artifacts.List(), []artifact.Artifact{fakeArtifact})
}
@ -109,6 +111,7 @@ func TestRunFullPipe(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "2.4.5"
assert.NoError(t, Pipe{}.Run(ctx))
assert.Equal(t, ctx.Artifacts.List(), []artifact.Artifact{fakeArtifact})
assert.True(t, exists(pre), pre)
@ -136,6 +139,7 @@ func TestRunFullPipeFail(t *testing.T) {
},
}
var ctx = context.New(config)
ctx.Git.CurrentTag = "2.4.5"
assert.EqualError(t, Pipe{}.Run(ctx), errFailedBuild.Error())
assert.Empty(t, ctx.Artifacts.List())
assert.True(t, exists(pre), pre)
@ -155,12 +159,14 @@ func TestRunPipeFailingHooks(t *testing.T) {
}
t.Run("pre-hook", func(t *testing.T) {
var ctx = context.New(config)
ctx.Git.CurrentTag = "2.3.4"
ctx.Config.Builds[0].Hooks.Pre = "exit 1"
ctx.Config.Builds[0].Hooks.Post = "echo post"
assert.EqualError(t, Pipe{}.Run(ctx), `pre hook failed: `)
})
t.Run("post-hook", func(t *testing.T) {
var ctx = context.New(config)
ctx.Git.CurrentTag = "2.3.4"
ctx.Config.Builds[0].Hooks.Pre = "echo pre"
ctx.Config.Builds[0].Hooks.Post = "exit 1"
assert.EqualError(t, Pipe{}.Run(ctx), `post hook failed: `)
@ -288,24 +294,16 @@ func TestExtOthers(t *testing.T) {
assert.Empty(t, "", extFor("winasdasd_sad"))
}
func TestBinaryFullTemplate(t *testing.T) {
var config = config.Project{
Builds: []config.Build{
{
Binary: `-s -w -X main.version={{.Version}} -X main.tag={{.Tag}} -X main.date={{.Date}} -X main.commit={{.Commit}} -X "main.foo={{.Env.FOO}}"`,
},
},
func TestTemplate(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git = context.GitInfo{
CurrentTag: "v1.2.3",
Commit: "123",
}
var ctx = &context.Context{
Git: context.GitInfo{
CurrentTag: "v1.2.3",
Commit: "123",
},
Version: "1.2.3",
Config: config,
Env: map[string]string{"FOO": "123"},
}
binary, err := binary(ctx, ctx.Config.Builds[0])
ctx.Version = "1.2.3"
ctx.Env = map[string]string{"FOO": "123"}
binary, err := tmpl.New(ctx).
Apply(`-s -w -X main.version={{.Version}} -X main.tag={{.Tag}} -X main.date={{.Date}} -X main.commit={{.Commit}} -X "main.foo={{.Env.FOO}}"`)
assert.NoError(t, err)
assert.Contains(t, binary, "-s -w")
assert.Contains(t, binary, "-X main.version=1.2.3")

View File

@ -3,11 +3,9 @@
package checksums
import (
"bytes"
"fmt"
"os"
"path/filepath"
"text/template"
"github.com/apex/log"
"golang.org/x/sync/errgroup"
@ -16,6 +14,7 @@ import (
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/semaphore"
"github.com/goreleaser/goreleaser/internal/tmpl"
)
// Pipe for checksums
@ -35,7 +34,7 @@ func (Pipe) Default(ctx *context.Context) error {
// Run the pipe
func (Pipe) Run(ctx *context.Context) (err error) {
filename, err := filenameFor(ctx)
filename, err := tmpl.New(ctx).Apply(ctx.Config.Checksum.NameTemplate)
if err != nil {
return err
}
@ -82,25 +81,3 @@ func checksums(file *os.File, artifact artifact.Artifact) error {
_, err = file.WriteString(fmt.Sprintf("%v %v\n", sha, artifact.Name))
return err
}
func filenameFor(ctx *context.Context) (string, error) {
var out bytes.Buffer
t, err := template.New("checksums").
Option("missingkey=error").
Parse(ctx.Config.Checksum.NameTemplate)
if err != nil {
return "", err
}
err = t.Execute(&out, struct {
ProjectName string
Tag string
Version string
Env map[string]string
}{
ProjectName: ctx.Config.ProjectName,
Tag: ctx.Git.CurrentTag,
Version: ctx.Version,
Env: ctx.Env,
})
return out.String(), err
}

View File

@ -31,6 +31,7 @@ func TestPipe(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "1.2.3"
ctx.Env = map[string]string{"FOO": "bar"}
ctx.Artifacts.Add(artifact.Artifact{
Name: binary,
@ -65,6 +66,7 @@ func TestPipeFileNotExist(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "1.2.3"
ctx.Artifacts.Add(artifact.Artifact{
Name: "nope",
Path: "/nope",
@ -77,8 +79,8 @@ func TestPipeFileNotExist(t *testing.T) {
func TestPipeInvalidNameTemplate(t *testing.T) {
for template, eerr := range map[string]string{
"{{ .Pro }_checksums.txt": `template: checksums:1: unexpected "}" in operand`,
"{{.Env.NOPE}}": `template: checksums:1:6: executing "checksums" at <.Env.NOPE>: map has no entry for key "NOPE"`,
"{{ .Pro }_checksums.txt": `template: tmpl:1: unexpected "}" in operand`,
"{{.Env.NOPE}}": `template: tmpl:1:6: executing "tmpl" at <.Env.NOPE>: map has no entry for key "NOPE"`,
} {
t.Run(template, func(tt *testing.T) {
folder, err := ioutil.TempDir("", "goreleasertest")
@ -92,6 +94,7 @@ func TestPipeInvalidNameTemplate(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "1.2.3"
ctx.Artifacts.Add(artifact.Artifact{
Name: "whatever",
Type: artifact.UploadableBinary,
@ -116,6 +119,7 @@ func TestPipeCouldNotOpenChecksumsTxt(t *testing.T) {
},
},
)
ctx.Git.CurrentTag = "1.2.3"
ctx.Artifacts.Add(artifact.Artifact{
Name: "whatever",
Type: artifact.UploadableBinary,

View File

@ -2,16 +2,13 @@
package docker
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"text/template"
"github.com/apex/log"
"github.com/masterminds/semver"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
@ -20,6 +17,7 @@ import (
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/deprecate"
"github.com/goreleaser/goreleaser/internal/semaphore"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pipeline"
)
@ -115,44 +113,16 @@ func doRun(ctx *context.Context) error {
return g.Wait()
}
func tagName(ctx *context.Context, tagTemplate string) (string, error) {
var out bytes.Buffer
t, err := template.New("tag").Option("missingkey=error").Parse(tagTemplate)
if err != nil {
return "", err
}
sv, err := semver.NewVersion(ctx.Git.CurrentTag)
if err != nil {
return "", err
}
data := struct {
Version string
Tag string
Commit string
Major int64
Minor int64
Patch int64
Env map[string]string
}{
Version: ctx.Version,
Commit: ctx.Git.Commit,
Tag: ctx.Git.CurrentTag,
Env: ctx.Env,
Major: sv.Major(),
Minor: sv.Minor(),
Patch: sv.Patch(),
}
err = t.Execute(&out, data)
return out.String(), err
}
func process(ctx *context.Context, docker config.Docker, artifact artifact.Artifact, seed int) error {
var root = filepath.Dir(artifact.Path)
var dockerfile = filepath.Join(root, filepath.Base(docker.Dockerfile)) + fmt.Sprintf(".%d", seed)
// nolint:prealloc
var images []string
for _, tagTemplate := range docker.TagTemplates {
tag, err := tagName(ctx, tagTemplate)
// TODO: add overrides support to config
tag, err := tmpl.New(ctx).
WithArtifact(artifact, map[string]string{}).
Apply(tagTemplate)
if err != nil {
return errors.Wrapf(err, "failed to execute tag template '%s'", tagTemplate)
}

View File

@ -80,6 +80,7 @@ func TestRunPipe(t *testing.T) {
"v{{.Major}}",
"v{{.Major}}.{{.Minor}}",
"commint-{{.Commit}}",
"le-{{.Os}}",
"latest",
},
Files: []string{
@ -91,6 +92,7 @@ func TestRunPipe(t *testing.T) {
registry + "goreleaser/test_run_pipe:v1.0.0-123",
registry + "goreleaser/test_run_pipe:v1",
registry + "goreleaser/test_run_pipe:v1.0",
registry + "goreleaser/test_run_pipe:le-linux",
registry + "goreleaser/test_run_pipe:latest",
},
assertError: shouldNotErr,
@ -226,7 +228,7 @@ func TestRunPipe(t *testing.T) {
},
},
},
assertError: shouldErr(`template: tag:1: unexpected "}" in operand`),
assertError: shouldErr(`template: tmpl:1: unexpected "}" in operand`),
},
"missing_env_on_template": {
publish: true,
@ -242,7 +244,7 @@ func TestRunPipe(t *testing.T) {
},
},
},
assertError: shouldErr(`template: tag:1:6: executing "tag" at <.Env.NOPE>: map has no entry for key "NOPE"`),
assertError: shouldErr(`template: tmpl:1:6: executing "tmpl" at <.Env.NOPE>: map has no entry for key "NOPE"`),
},
"no_permissions": {
publish: true,

View File

@ -1,16 +1,14 @@
package git
import (
"bytes"
"fmt"
"regexp"
"strings"
"text/template"
"time"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/git"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pipeline"
"github.com/pkg/errors"
)
@ -80,7 +78,7 @@ func getGitInfo(ctx *context.Context) (context.GitInfo, error) {
func setVersion(ctx *context.Context) error {
if ctx.Snapshot {
snapshotName, err := getSnapshotName(ctx)
snapshotName, err := tmpl.New(ctx).Apply(ctx.Config.Snapshot.NameTemplate)
if err != nil {
return errors.Wrap(err, "failed to generate snapshot name")
}
@ -92,27 +90,6 @@ func setVersion(ctx *context.Context) error {
return nil
}
type snapshotNameData struct {
Commit string
Tag string
Timestamp int64
}
func getSnapshotName(ctx *context.Context) (string, error) {
tmpl, err := template.New("snapshot").Parse(ctx.Config.Snapshot.NameTemplate)
var out bytes.Buffer
if err != nil {
return "", err
}
var data = snapshotNameData{
Commit: ctx.Git.Commit,
Tag: ctx.Git.CurrentTag,
Timestamp: time.Now().Unix(),
}
err = tmpl.Execute(&out, data)
return out.String(), err
}
func validate(ctx *context.Context) error {
if ctx.Snapshot {
return pipeline.ErrSnapshotEnabled

View File

@ -75,7 +75,7 @@ func TestNoTagsSnapshotInvalidTemplate(t *testing.T) {
},
})
ctx.Snapshot = true
assert.EqualError(t, Pipe{}.Run(ctx), `failed to generate snapshot name: template: snapshot:1: unexpected unclosed action in command`)
assert.EqualError(t, Pipe{}.Run(ctx), `failed to generate snapshot name: template: tmpl:1: unexpected unclosed action in command`)
}
// TestNoTagsNoSnapshot covers the situation where a repository

View File

@ -20,9 +20,9 @@ import (
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/filenametemplate"
"github.com/goreleaser/goreleaser/internal/linux"
"github.com/goreleaser/goreleaser/internal/semaphore"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pipeline"
)
@ -100,10 +100,9 @@ func create(ctx *context.Context, format, arch string, binaries []artifact.Artif
if err != nil {
return err
}
name, err := filenametemplate.Apply(
overrided.NameTemplate,
filenametemplate.NewFields(ctx, overrided.Replacements, binaries...),
)
name, err := tmpl.New(ctx).
WithArtifact(binaries[0], overrided.Replacements).
Apply(overrided.NameTemplate)
if err != nil {
return err
}

View File

@ -143,7 +143,7 @@ func TestInvalidNameTemplate(t *testing.T) {
Goarch: "amd64",
Type: artifact.Binary,
})
assert.Contains(t, Pipe{}.Run(ctx).Error(), `template: {{.Foo}:1: unexpected "}" in operand`)
assert.Contains(t, Pipe{}.Run(ctx).Error(), `template: tmpl:1: unexpected "}" in operand`)
}
func TestCreateFileDoesntExist(t *testing.T) {
@ -189,6 +189,8 @@ func TestInvalidConfig(t *testing.T) {
Formats: []string{"deb"},
},
})
ctx.Git.CurrentTag = "v1.2.3"
ctx.Version = "v1.2.3"
ctx.Artifacts.Add(artifact.Artifact{
Name: "mybin",
Path: filepath.Join(dist, "mybin", "mybin"),

View File

@ -13,8 +13,8 @@ import (
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/nametemplate"
"github.com/goreleaser/goreleaser/internal/semaphore"
"github.com/goreleaser/goreleaser/internal/tmpl"
"golang.org/x/sync/errgroup"
)
@ -73,7 +73,7 @@ func upload(ctx *context.Context, conf config.S3) error {
svc := s3.New(sess, &aws.Config{
Region: aws.String(conf.Region),
})
folder, err := nametemplate.Apply(ctx, conf.Folder)
folder, err := tmpl.New(ctx).Apply(conf.Folder)
if err != nil {
return err
}

View File

@ -16,9 +16,9 @@ import (
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/filenametemplate"
"github.com/goreleaser/goreleaser/internal/linux"
"github.com/goreleaser/goreleaser/internal/semaphore"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pipeline"
)
@ -109,10 +109,9 @@ func (Pipe) Run(ctx *context.Context) error {
func create(ctx *context.Context, arch string, binaries []artifact.Artifact) error {
var log = log.WithField("arch", arch)
folder, err := filenametemplate.Apply(
ctx.Config.Snapcraft.NameTemplate,
filenametemplate.NewFields(ctx, ctx.Config.Snapcraft.Replacements, binaries...),
)
folder, err := tmpl.New(ctx).
WithArtifact(binaries[0], ctx.Config.Snapcraft.Replacements).
Apply(ctx.Config.Snapcraft.NameTemplate)
if err != nil {
return err
}

View File

@ -55,7 +55,8 @@ func TestRunPipe(t *testing.T) {
Description: "test description",
},
})
ctx.Version = "testversion"
ctx.Git.CurrentTag = "v1.2.3"
ctx.Version = "v1.2.3"
addBinaries(t, ctx, "mybin", dist)
assert.NoError(t, Pipe{}.Run(ctx))
}
@ -75,9 +76,10 @@ func TestRunPipeInvalidNameTemplate(t *testing.T) {
Description: "test description",
},
})
ctx.Version = "testversion"
ctx.Git.CurrentTag = "v1.2.3"
ctx.Version = "v1.2.3"
addBinaries(t, ctx, "mybin", dist)
assert.EqualError(t, Pipe{}.Run(ctx), `template: foo_{{.Arch}:1: unexpected "}" in operand`)
assert.EqualError(t, Pipe{}.Run(ctx), `template: tmpl:1: unexpected "}" in operand`)
}
func TestRunPipeWithName(t *testing.T) {
@ -96,7 +98,8 @@ func TestRunPipeWithName(t *testing.T) {
Description: "test description",
},
})
ctx.Version = "testversion"
ctx.Git.CurrentTag = "v1.2.3"
ctx.Version = "v1.2.3"
addBinaries(t, ctx, "testprojectname", dist)
assert.NoError(t, Pipe{}.Run(ctx))
yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
@ -129,7 +132,8 @@ func TestRunPipeMetadata(t *testing.T) {
},
},
})
ctx.Version = "testversion"
ctx.Git.CurrentTag = "v1.2.3"
ctx.Version = "v1.2.3"
addBinaries(t, ctx, "mybin", dist)
assert.NoError(t, Pipe{}.Run(ctx))
yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))

View File

@ -14,17 +14,7 @@ Here is a commented `archive` section with all fields specified:
```yml
# .goreleaser.yml
archive:
# You can change the name of the archive.
# This is parsed with the Go template engine and the following variables
# are available:
# - ProjectName
# - Binary (Name of the binary if the packaging format is binary)
# - Tag
# - Version (Git tag without `v` prefix)
# - Os
# - Arch
# - Arm (ARM version)
# - Env (environment variables)
# Archive name template.
# Defaults:
# - if format is `tar.gz` or `zip`:
# - `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
@ -73,21 +63,7 @@ archive:
- design/*.png
```
## Passing environment variables to name_template
You can do that by using `{{ .Env.VARIABLE_NAME }}` in the template, for
example:
```yaml
archive:
name_template: '{{.ProjectName}}-{{.Version}}-{{.Env.GOVERSION_NR}}'
```
Then you can run:
```console
GOVERSION_NR=$(go version | awk '{print $3;}') goreleaser
```
> Learn more about the [name template engine](/templates).
## Packaging only the binaries

View File

@ -19,14 +19,7 @@ builds:
# Default is `.`.
main: ./cmd/main.go
# Name of the binary.
# This is parsed with the Go template engine and the following variables
# are available:
# - Date
# - Commit
# - Tag
# - Version (Git tag without `v` prefix)
# Date format is `2006-01-02_15:04:05`.
# Name template for the binary final name.
# Default is the name of the project directory.
binary: program
@ -37,51 +30,18 @@ builds:
- dev
# Custom asmflags templates.
# These are parsed with the Go template engine and the following variables
# are available:
# - Date
# - Commit
# - Tag
# - Version (Git tag without `v` prefix)
# - Env (environment variables)
# Date format is `2006-01-02_15:04:05`.
# You can use the `time` function instead of `Date`, for example:
# `time "2006-01-02"` too if you need custom formats
#
# Default is empty.
asmflags:
- -D mysymbol
- all=-trimpath={{.Env.GOPATH}}
# Custom gcflags templates.
# These are parsed with the Go template engine and the following variables
# are available:
# - Date
# - Commit
# - Tag
# - Version (Git tag without `v` prefix)
# - Env (environment variables)
# Date format is `2006-01-02_15:04:05`.
# You can use the `time` function instead of `Date`, for example:
# `time "2006-01-02"` too if you need custom formats
#
# Default is empty.
gcflags:
- all=-trimpath={{.Env.GOPATH}}
- ./dontoptimizeme=-N
# Custom ldflags templates.
# These are parsed with the Go template engine and the following variables
# are available:
# - Date
# - Commit
# - Tag
# - Version (Git tag without `v` prefix)
# - Env (environment variables)
# Date format is `2006-01-02_15:04:05`.
# You can use the `time` function instead of `Date`, for example:
# `time "2006-01-02"` too if you need custom formats
#
# Default is `-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}`.
ldflags:
- -s -w -X main.build={{.Version}}
@ -131,6 +91,8 @@ builds:
post: ./script.sh
```
> Learn more about the [name template engine](/templates).
## Passing environment variables to ldflags
You can do that by using `{{ .Env.VARIABLE_NAME }}` in the template, for

View File

@ -14,12 +14,8 @@ The `checksum` section allows customizations of the filename:
# .goreleaser.yml
checksum:
# You can change the name of the checksums file.
# This is parsed with the Go template engine and the following variables
# are available:
# - ProjectName
# - Tag
# - Version (Git tag without `v` prefix)
# - Env (environment variables)
# Default is `{{ .ProjectName }}_{{ .Version }}_checksums.txt`.
name_template: "{{ .ProjectName }}_checksums.txt"
```
> Learn more about the [name template engine](/templates).

View File

@ -61,13 +61,6 @@ dockers:
# Path to the Dockerfile (from the project root).
dockerfile: Dockerfile
# Template of the docker tag. Defaults to `{{ .Version }}`.
# Other allowed fields are:
# - `.Commint`
# - `.Tag`
# - `.Major`
# - `.Minor`
# - `.Patch`
# - `.Env.VARIABLE_NAME`
tag_templates:
- "{{ .Tag }}"
- "{{ .Tag }}-{{ .Env.GO_VERSION }}"
@ -79,27 +72,12 @@ dockers:
- config.yml
```
> Learn more about the [name template engine](/templates).
These settings should allow you to generate multiple Docker images,
for example, using multiple `FROM` statements,
as well as generate one image for each binary in your project.
## Passing environment variables to tag_template
You can do that by using `{{ .Env.VARIABLE_NAME }}` in the template, for
example:
```yaml
dockers:
-
tag_template: "{{ .Tag }}-{{ .Env.GOVERSION_NR }}"
```
Then you can run:
```console
GOVERSION_NR=$(go version | awk '{print $3}') goreleaser
```
## Keeping docker images updated for current major
Some users might want to when version to push docker tags `:v1`, `:v1.6`,

View File

@ -18,7 +18,7 @@ for more details.
```yml
# .goreleaser.yml
brew:
# Name of the recipe
# Name template of the recipe
# Default to project name
name: myproject
@ -88,6 +88,8 @@ brew:
...
```
> Learn more about the [name template engine](/templates).
By defining the `brew` section, GoReleaser will take care of publishing the
Homebrew tap.
Assuming that the current tag is `v1.2.3`, the above configuration will generate a

View File

@ -14,15 +14,6 @@ Available options:
# .goreleaser.yml
nfpm:
# You can change the name of the package.
# This is parsed with the Go template engine and the following variables
# are available:
# - ProjectName
# - Tag
# - Version (Git tag without `v` prefix)
# - Os
# - Arch
# - Arm (ARM version)
# - Env (environment variables)
# Default: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
@ -141,6 +132,8 @@ nfpm:
preinstall: "scripts/preinstall-rpm.sh"
```
> Learn more about the [name template engine](/templates).
Note that GoReleaser will not install `rpmbuild` or any dependencies for you.
As for now, `rpmbuild` is recommended if you want to generate rpm packages.
You can install it with `apt-get install rpm` or `brew install rpm`.

View File

@ -1,5 +1,5 @@
---
title: Put
title: HTTP Put
series: customization
hideFromIndex: true
weight: 120

View File

@ -29,14 +29,6 @@ release:
prerelease: true
# You can change the name of the GitHub release.
# This is parsed with the Go template engine and the following variables
# are available:
# - ProjectName
# - Tag
# - Version (Git tag without `v` prefix)
# - Env (environment variables)
# There is also a template function "time" that takes a Go time format
# string to insert a formated timestamp into the release name.
# Default is ``
name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}"
@ -46,6 +38,8 @@ release:
disable: true
```
> Learn more about the [name template engine](/templates).
## Customize the changelog
You can customize how the changelog is generated using the

View File

@ -27,14 +27,7 @@ s3:
# AWS Region to use.
# Defaults is us-east-1
region: us-east-1
# path inside the bucket.
# This is parsed with the Go template engine and the following variables
# are available:
# - ProjectName
# - Tag
# - Version (Git tag without `v` prefix)
# There is also a template function "time" that takes a Go time format
# string to insert a formated timestamp into the release name.
# Template for the path/name inside the bucket.
# Default is `{{ .ProjectName }}/{{ .Tag }}`
folder: "foo/bar/{{.Version}}"
# Set a custom profile to use for this s3 config. If you have multiple
@ -48,6 +41,8 @@ s3:
endpoint: "http://minio.foo.com"
```
> Learn more about the [name template engine](/templates).
## Authentication
GoReleaser will authenticate using the [same methods defined by aws-cli][auth].

View File

@ -20,15 +20,6 @@ Available options:
# .goreleaser.yml
snapcraft:
# You can change the name of the package.
# This is parsed with the Go template engine and the following variables
# are available:
# - ProjectName
# - Tag
# - Version (Git tag without `v` prefix)
# - Os
# - Arch
# - Arm (ARM version)
# - Env (environment variables)
# Default: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
@ -97,5 +88,7 @@ snapcraft:
args: --foo
```
> Learn more about the [name template engine](/templates).
Note that GoReleaser will not install `snapcraft` nor any of its dependencies
for you.

View File

@ -14,10 +14,8 @@ and also with the `snapshot` customization section:
# .goreleaser.yml
snapshot:
# Allows you to change the name of the generated snapshot
# releases. The following variables are available:
# - Commit
# - Tag
# - Timestamp
# Default is `SNAPSHOT-{{.Commit}}`.
name_template: SNAPSHOT-{{.Commit}}
```
> Learn more about the [name template engine](/templates).

65
www/content/templates.md Normal file
View File

@ -0,0 +1,65 @@
---
title: Name Templates
series: customization
hideFromIndex: true
weight: 25
---
Several fields in GoReleaser's config file support templating.
Those fields are often suffixed with `_template`, but sometimes they may not
be. The documentation of each section should explicit in which fields
templating is available.
On fields that support templating, this fields are always available:
| Key | Description |
| :------------: | :----------------------------------------------: |
| `.ProjectName` | the project name |
| `.Version` | the version being released (`v` prefix stripped) |
| `.Tag` | the current git tag |
| `.Commit` | the git commit hash |
| `.Major` | the major part of the version |
| `.Minor` | the minor part of the version |
| `.Patch` | the patch part of the version |
| `.Env` | a map with system's environment variables |
| `.Date` | current UTC date in RFC3339 format |
| `.Timestamp` | current UTC time in Unix format |
On fields that are related to a single artifact (e.g., the binary name), you
may have some extra fields:
| Key | Description |
| :-------: | :-----------------------------------: |
| `.Os` | `GOOS` (usually allow replacements) |
| `.Arch` | `GOARCH` (usually allow replacements) |
| `.Arm` | `GOARM` (usually allow replacements) |
| `.Binary` | Binary name |
On all fields, you have these available functions:
| Usage | Description |
| :-----------------: | :--------------------------------------: |
| `time "01/02/2006"` | current UTC time in the specified format |
With all those fields, you may be able to compose the name of your artifacts
pretty much the way you want:
```yaml
example_template: '{{ .ProjectName }}_{{ .Env.USER }}_{{ time "2006" }}'
```
For example, if you want to add the go version to some artifact:
```yaml
foo_template: 'foo_{{ .Env.GOVERSION }}'
```
And then you can run:
```console
GOVERSION_NR=$(go version | awk '{print $3;}') goreleaser
```
> Note that those are hypothetical examples and the fields `foo_template` and
> `example_template` are not valid GoReleaser configurations.

@ -1 +1 @@
Subproject commit cb87b6b1368824d743a5d31d824eaecd2351b783
Subproject commit 7a952e65f3dcdc1023f35a7faf83b7b70de4631a