Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(build): allow to template env #3592

Merged
merged 3 commits into from Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 21 additions & 1 deletion internal/builders/golang/build.go
Expand Up @@ -165,7 +165,23 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
return err
}

env := append(ctx.Env.Strings(), details.Env...)
env := []string{}
// used for unit testing only
testEnvs := []string{}
env = append(env, ctx.Env.Strings()...)
for _, e := range details.Env {
ee, err := tmpl.New(ctx).WithEnvS(env).WithArtifact(a, nil).Apply(e)
if err != nil {
return err
}
log.Debugf("env %q evaluated to %q", e, ee)
if ee != "" {
env = append(env, ee)
if strings.HasPrefix(e, "TEST_") {
testEnvs = append(testEnvs, ee)
}
}
}
env = append(
env,
"GOOS="+options.Goos,
Expand All @@ -176,6 +192,10 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
"GOAMD64="+options.Goamd64,
)

if len(testEnvs) > 0 {
a.Extra["testEnvs"] = testEnvs
}

cmd, err := buildGoBuildLine(ctx, build, details, options, a, env)
if err != nil {
return err
Expand Down
49 changes: 48 additions & 1 deletion internal/builders/golang/build_test.go
Expand Up @@ -363,7 +363,16 @@ func TestBuild(t *testing.T) {
GoBinary: "go",
Command: "build",
BuildDetails: config.BuildDetails{
Env: []string{"GO111MODULE=off"},
Env: []string{
"GO111MODULE=off",
`TEST_T={{- if eq .Os "windows" -}}
w
{{- else if eq .Os "darwin" -}}
d
{{- else if eq .Os "linux" -}}
l
{{- end -}}`,
},
Asmflags: []string{".=", "all="},
Gcflags: []string{"all="},
Flags: []string{"{{.Env.GO_FLAGS}}"},
Expand Down Expand Up @@ -426,6 +435,7 @@ func TestBuild(t *testing.T) {
artifact.ExtraExt: "",
artifact.ExtraBinary: "foo-v5.6.7",
artifact.ExtraID: "foo",
"testEnvs": []string{"TEST_T=l"},
},
},
{
Expand All @@ -439,6 +449,7 @@ func TestBuild(t *testing.T) {
artifact.ExtraExt: "",
artifact.ExtraBinary: "foo-v5.6.7",
artifact.ExtraID: "foo",
"testEnvs": []string{"TEST_T=l"},
},
},
{
Expand All @@ -452,6 +463,7 @@ func TestBuild(t *testing.T) {
artifact.ExtraExt: "",
artifact.ExtraBinary: "foo-v5.6.7",
artifact.ExtraID: "foo",
"testEnvs": []string{"TEST_T=l"},
},
},
{
Expand All @@ -464,6 +476,7 @@ func TestBuild(t *testing.T) {
artifact.ExtraExt: "",
artifact.ExtraBinary: "foo-v5.6.7",
artifact.ExtraID: "foo",
"testEnvs": []string{"TEST_T=d"},
},
},
{
Expand All @@ -477,6 +490,7 @@ func TestBuild(t *testing.T) {
artifact.ExtraExt: "",
artifact.ExtraBinary: "foo-v5.6.7",
artifact.ExtraID: "foo",
"testEnvs": []string{"TEST_T=l"},
},
},
{
Expand All @@ -489,6 +503,7 @@ func TestBuild(t *testing.T) {
artifact.ExtraExt: ".exe",
artifact.ExtraBinary: "foo-v5.6.7",
artifact.ExtraID: "foo",
"testEnvs": []string{"TEST_T=w"},
},
},
{
Expand All @@ -501,6 +516,7 @@ func TestBuild(t *testing.T) {
artifact.ExtraExt: ".wasm",
artifact.ExtraBinary: "foo-v5.6.7",
artifact.ExtraID: "foo",
"testEnvs": []string{"TEST_T="},
},
},
})
Expand All @@ -524,6 +540,37 @@ func TestBuild(t *testing.T) {
}
}

func TestBuildInvalidEnv(t *testing.T) {
folder := testlib.Mktmp(t)
writeGoodMain(t, folder)
config := config.Project{
Builds: []config.Build{
{
ID: "foo",
Dir: ".",
Binary: "foo",
Targets: []string{
runtimeTarget,
},
GoBinary: "go",
BuildDetails: config.BuildDetails{
Env: []string{"GO111MODULE={{ .Nope }}"},
},
},
},
}
ctx := context.New(config)
ctx.Git.CurrentTag = "5.6.7"
build := ctx.Config.Builds[0]
err := Default.Build(ctx, build, api.Options{
Target: runtimeTarget,
Name: build.Binary,
Path: filepath.Join(folder, "dist", runtimeTarget, build.Binary),
Ext: "",
})
testlib.RequireTemplateError(t, err)
}

func TestBuildCodeInSubdir(t *testing.T) {
folder := testlib.Mktmp(t)
subdir := filepath.Join(folder, "bar")
Expand Down
4 changes: 1 addition & 3 deletions internal/pipe/build/build.go
Expand Up @@ -115,9 +115,7 @@ func runHook(ctx *context.Context, opts builders.Options, buildEnv []string, hoo
var env []string

env = append(env, ctx.Env.Strings()...)
env = append(env, buildEnv...)

for _, rawEnv := range hook.Env {
for _, rawEnv := range append(buildEnv, hook.Env...) {
e, err := tmpl.New(ctx).WithBuildOptions(opts).Apply(rawEnv)
if err != nil {
return err
Expand Down
7 changes: 7 additions & 0 deletions internal/pipe/build/build_test.go
Expand Up @@ -121,6 +121,8 @@ func TestRunFullPipe(t *testing.T) {
folder := testlib.Mktmp(t)
pre := filepath.Join(folder, "pre")
post := filepath.Join(folder, "post")
preOS := filepath.Join(folder, "pre_linux")
postOS := filepath.Join(folder, "post_linux")
config := config.Project{
Builds: []config.Build{
{
Expand All @@ -130,13 +132,16 @@ func TestRunFullPipe(t *testing.T) {
BuildDetails: config.BuildDetails{
Flags: []string{"-v"},
Ldflags: []string{"-X main.test=testing"},
Env: []string{"THE_OS={{ .Os }}"},
},
Hooks: config.BuildHookConfig{
Pre: []config.Hook{
{Cmd: "touch " + pre},
{Cmd: "touch pre_{{ .Env.THE_OS}}"},
},
Post: []config.Hook{
{Cmd: "touch " + post},
{Cmd: "touch post_{{ .Env.THE_OS}}"},
},
},
Targets: []string{"linux_amd64"},
Expand All @@ -153,6 +158,8 @@ func TestRunFullPipe(t *testing.T) {
}})
require.FileExists(t, post)
require.FileExists(t, pre)
require.FileExists(t, postOS)
require.FileExists(t, preOS)
require.FileExists(t, filepath.Join(folder, "build1_linux_amd64", "testing"))
}

Expand Down
91 changes: 91 additions & 0 deletions www/docs/customization/build.md
Expand Up @@ -71,11 +71,22 @@ builds:

# Custom environment variables to be set during the builds.
#
# This field is templateable. Since v1.14.
#
# Invalid environment variables will be ignored.
#
# Default: `os.Environ()` merged with what you set the root `env` section.
env:
- CGO_ENABLED=0
# complex, templated envs (v1.14+):
- >-
{{- if eq .Os "darwin" }}
{{- if eq .Arch "amd64"}}CC=o64-clang{{- end }}
{{- if eq .Arch "arm64"}}CC=aarch64-apple-darwin20.2-clang{{- end }}
{{- end }}
{{- if eq .Os "windows" }}
{{- if eq .Arch "amd64" }}CC=x86_64-w64-mingw32-gcc{{- end }}
{{- end }}

# GOOS list to build for.
# For more info refer to: https://golang.org/doc/install/source#environment
Expand Down Expand Up @@ -558,3 +569,83 @@ builds:
# Configure the buildmode flag to output a shared library
buildmode: "c-shared" # or "c-archive" for a static library
```

## Complex templated environment variables

> Since v1.14.

Builds environment variables are templateable.

You can leverage that to have a single build configuration with different
environment variables for each platform, for example.

A common example of this is the variables `CC` and `CCX`.

Here are two different examples:

### Using multiple envs

This example creates once `CC_` and `CCX_` variable for each platform, and then
set `CC` and `CCX` to the right one:

```yaml
# .goreleaser.yml
builds:
- id: mybin
binary: mybin
main: .
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64
env:
- CGO_ENABLED=0
- CC_darwin_amd64=o64-clang
- CCX_darwin_amd64=o64-clang+
- CC_darwin_arm64=aarch64-apple-darwin20.2-clang
- CCX_darwin_arm64=aarch64-apple-darwin20.2-clang++
- CC_windows_amd64=x86_64-w64-mingw32-gc
- CCX_windows_amd64=x86_64-w64-mingw32-g++
- 'CC={{ index .Env (print "CC_" .Os "_" .Arch) }}'
- 'CCX={{ index .Env (print "CCX_" .Os "_" .Arch) }}'
```

### Using `if` statements

This example uses `if` statements to set `CC` and `CCX`:

```yaml
# .goreleaser.yml
builds:
- id: mybin
binary: mybin
main: .
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64
env:
- CGO_ENABLED=0
- >-
{{- if eq .Os "darwin" }}
{{- if eq .Arch "amd64"}}CC=o64-clang{{- end }}
{{- if eq .Arch "arm64"}}CC=aarch64-apple-darwin20.2-clang{{- end }}
{{- end }}
{{- if eq .Os "windows" }}
{{- if eq .Arch "amd64" }}CC=x86_64-w64-mingw32-gcc{{- end }}
{{- end }}
- >-
{{- if eq .Os "darwin" }}
{{- if eq .Arch "amd64"}}CXX=o64-clang+{{- end }}
{{- if eq .Arch "arm64"}}CXX=aarch64-apple-darwin20.2-clang++{{- end }}
{{- end }}
{{- if eq .Os "windows" }}
{{- if eq .Arch "amd64" }}CXX=x86_64-w64-mingw32-g++{{- end }}
{{- end }}
```