1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-17 20:47:50 +02:00

feat(build): allow to template env (#3592)

GoReleaser evolved a lot since the last time I tried to implement this
>1 year ago.
Now its 100% possible, and way simpler to do it!

closes #3580
refs #2583

Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
Carlos Alexandro Becker 2022-11-25 15:26:29 -03:00 committed by GitHub
parent e54656438b
commit 1b8395d6b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 168 additions and 5 deletions

View File

@ -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,
@ -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

View File

@ -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}}"},
@ -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"},
},
},
{
@ -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"},
},
},
{
@ -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"},
},
},
{
@ -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"},
},
},
{
@ -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"},
},
},
{
@ -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"},
},
},
{
@ -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="},
},
},
})
@ -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")

View File

@ -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

View File

@ -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{
{
@ -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"},
@ -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"))
}

View File

@ -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
@ -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 }}
```