Skip to content
Permalink
Browse files

feat: global env and template-able before hooks (#974)

* feat: global env

* docs: hooks templateable, global env

* docs: hooks templateable, global env

* feat: templas on before hooks

* docs: revert unwanted change

* fix: use os.environ too

* chore: travis

* fix: goreleaser.yml
  • Loading branch information...
caarlos0 committed Mar 3, 2019
1 parent 01249b2 commit cf4aba68d3c9a0a8d8e788a7998940397d424076
@@ -1,6 +1,8 @@
env:
- GO111MODULE=on
before:
hooks:
- go mod download
- go mod download
builds:
- env:
- CGO_ENABLED=0
@@ -10,14 +10,14 @@ addons:
- rpm
- snapd
env:
- PATH=/snap/bin:$PATH GO111MODULE=on
- PATH=/snap/bin:$PATH
install:
- make setup
- npm install -g prettier
- sudo snap install snapcraft --classic
script:
- make ci
- test -n "$TRAVIS_TAG" || go run main.go --snapshot --debug
- test -n "$TRAVIS_TAG" || ./goreleaser --snapshot --debug
after_success:
- bash <(curl -s https://codecov.io/bash)
- make static
@@ -90,7 +90,8 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
if err != nil {
return err
}
var env = append(build.Env, target.Env()...)
var env = append(ctx.Config.Env, build.Env...)
env = append(env, target.Env()...)
if err := run(ctx, cmd, env); err != nil {
return errors.Wrapf(err, "failed to build for %s", options.Target)
}
@@ -2,11 +2,13 @@ package before

import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/apex/log"
"github.com/fatih/color"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/context"
)

@@ -20,11 +22,17 @@ func (Pipe) String() string {

// Run executes the hooks
func (Pipe) Run(ctx *context.Context) error {
var tmpl = tmpl.New(ctx)
/* #nosec */
for _, step := range ctx.Config.Before.Hooks {
args := strings.Fields(step)
s, err := tmpl.Apply(step)
if err != nil {
return err
}
args := strings.Fields(s)
log.Infof("running %s", color.CyanString(step))
cmd := exec.Command(args[0], args[1:]...)
cmd.Env = append(os.Environ(), ctx.Config.Env...)
out, err := cmd.CombinedOutput()
log.Debug(string(out))
if err != nil {
@@ -1,15 +1,17 @@
package before

import (
"io/ioutil"
"os"
"testing"

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

func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.String())
require.NotEmpty(t, Pipe{}.String())
}

func TestRunPipe(t *testing.T) {
@@ -26,7 +28,7 @@ func TestRunPipe(t *testing.T) {
},
},
)
assert.NoError(t, Pipe{}.Run(ctx))
require.NoError(t, Pipe{}.Run(ctx))
}
}

@@ -41,6 +43,34 @@ func TestRunPipeFail(t *testing.T) {
},
},
)
assert.Error(t, Pipe{}.Run(ctx))
require.Error(t, Pipe{}.Run(ctx))
}
}

func TestRunWithEnv(t *testing.T) {
f, err := ioutil.TempFile("", "")
require.NoError(t, err)
require.NoError(t, os.Remove(f.Name()))
defer os.Remove(f.Name())
require.NoError(t, Pipe{}.Run(context.New(
config.Project{
Env: []string{
"TEST_FILE=" + f.Name(),
},
Before: config.Before{
Hooks: []string{"touch {{ .Env.TEST_FILE }}"},
},
},
)))
require.FileExists(t, f.Name())
}

func TestInvalidTemplate(t *testing.T) {
require.EqualError(t, Pipe{}.Run(context.New(
config.Project{
Before: config.Before{
Hooks: []string{"touch {{ .fasdsd }"},
},
},
)), `template: tmpl:1: unexpected "}" in operand`)
}
@@ -305,6 +305,7 @@ type Put struct {
// Project includes all project configuration
type Project struct {
ProjectName string `yaml:"project_name,omitempty"`
Env []string `yaml:",omitempty"`
Release Release `yaml:",omitempty"`
Brew Homebrew `yaml:",omitempty"`
Scoop Scoop `yaml:",omitempty"`
@@ -69,7 +69,7 @@ func Wrap(ctx ctx.Context, config config.Project) *Context {
return &Context{
Context: ctx,
Config: config,
Env: splitEnv(os.Environ()),
Env: splitEnv(append(os.Environ(), config.Env...)),
Parallelism: 4,
Artifacts: artifact.New(),
}
@@ -1,6 +1,7 @@
package context

import (
"os"
"testing"
"time"

@@ -9,8 +10,15 @@ import (
)

func TestNew(t *testing.T) {
var ctx = New(config.Project{})
assert.NotEmpty(t, ctx.Env)
assert.NoError(t, os.Setenv("FOO", "NOT BAR"))
assert.NoError(t, os.Setenv("BAR", "1"))
var ctx = New(config.Project{
Env: []string{
"FOO=BAR",
},
})
assert.Equal(t, "BAR", ctx.Env["FOO"])
assert.Equal(t, "1", ctx.Env["BAR"])
assert.Equal(t, 4, ctx.Parallelism)
}

@@ -0,0 +1,26 @@
---
title: Environment Variables
series: customization
hideFromIndex: true
weight: 30
---

Global environment variables to be passed down to all hooks and builds.

This is useful for `GO111MODULE`, for example. You can have your
`.goreleaser.yaml` file like the following:

```yaml
# .goreleaser.yml
env:
- GO111MODULE=on
before:
hooks:
- go mod download
builds:
- binary: program
```

This way, both `go mod download` and the underlying `go build` will have
`GO111MODULE` set to `on`.

@@ -14,10 +14,12 @@ The configuration is very simple, here is a complete example:
```yml
# .goreleaser.yml
before:
# Templates for the commands to be ran.
hooks:
- make clean
- go generate ./...
- go mod download
- touch {{ .Env.FILE_TO_TOUCH }}
```

If any of the hooks fails the build process is aborted.
@@ -26,3 +28,5 @@ It is important to note that you can't have "complex" commands, like
`bash -c "echo foo bar"` or `foo | bar` or anything like that. If you need
to do things that are more complex than just calling a command with some
attributes, wrap it in a shell script or into your `Makefile`.

> Learn more about the [name template engine](/templates).
BIN +0 Bytes (100%) www/static/apple-touch-icon.png
Binary file not shown.

0 comments on commit cf4aba6

Please sign in to comment.
You can’t perform that action at this time.