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

Enable setting environment variables in .ko.yaml ()

* Enable setting environment variables in .ko.yaml

Matches the GoReleaser format.

Related: 

* Use different env example
This commit is contained in:
Halvard Skogsrud 2021-08-24 01:05:01 +10:00 committed by GitHub
parent 040b7c7698
commit 9a256a4b19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 19 deletions

@ -135,6 +135,8 @@ configuration section in your `.ko.yaml`.
builds: builds:
- id: foo - id: foo
main: ./foobar/foo main: ./foobar/foo
env:
- GOPRIVATE=git.internal.example.com,source.developers.google.com
flags: flags:
- -tags - -tags
- netgo - netgo
@ -144,6 +146,8 @@ builds:
- -X main.version={{.Env.VERSION}} - -X main.version={{.Env.VERSION}}
- id: bar - id: bar
main: ./foobar/bar/main.go main: ./foobar/bar/main.go
env:
- GOCACHE=/workspace/.gocache
ldflags: ldflags:
- -s - -s
- -w - -w
@ -156,7 +160,7 @@ with the intended import path.
_Please note:_ Even though the configuration section is similar to the _Please note:_ Even though the configuration section is similar to the
[GoReleaser `builds` section](https://goreleaser.com/customization/build/), [GoReleaser `builds` section](https://goreleaser.com/customization/build/),
only the `flags` and `ldflags` fields are currently supported. Also, the only the `env`, `flags` and `ldflags` fields are currently supported. Also, the
templating support is currently limited to environment variables only. templating support is currently limited to environment variables only.
## Naming Images ## Naming Images

@ -79,6 +79,9 @@ type Config struct {
Ldflags StringArray `yaml:",omitempty"` Ldflags StringArray `yaml:",omitempty"`
Flags FlagArray `yaml:",omitempty"` Flags FlagArray `yaml:",omitempty"`
// Env allows setting environment variables for `go build`
Env []string `yaml:",omitempty"`
// Other GoReleaser fields that are not supported or do not make sense // Other GoReleaser fields that are not supported or do not make sense
// in the context of ko, for reference or for future use: // in the context of ko, for reference or for future use:
// Goos []string `yaml:",omitempty"` // Goos []string `yaml:",omitempty"`
@ -87,7 +90,6 @@ type Config struct {
// Gomips []string `yaml:",omitempty"` // Gomips []string `yaml:",omitempty"`
// Targets []string `yaml:",omitempty"` // Targets []string `yaml:",omitempty"`
// Binary string `yaml:",omitempty"` // Binary string `yaml:",omitempty"`
// Env []string `yaml:",omitempty"`
// Lang string `yaml:",omitempty"` // Lang string `yaml:",omitempty"`
// Asmflags StringArray `yaml:",omitempty"` // Asmflags StringArray `yaml:",omitempty"`
// Gcflags StringArray `yaml:",omitempty"` // Gcflags StringArray `yaml:",omitempty"`

@ -378,24 +378,11 @@ func build(ctx context.Context, ip string, dir string, platform v1.Platform, con
cmd := exec.CommandContext(ctx, "go", args...) cmd := exec.CommandContext(ctx, "go", args...)
cmd.Dir = dir cmd.Dir = dir
// Last one wins env, err := buildEnv(platform, config.Env)
defaultEnv := []string{ if err != nil {
"CGO_ENABLED=0", return "", fmt.Errorf("could not create env for %s: %v", ip, err)
"GOOS=" + platform.OS,
"GOARCH=" + platform.Architecture,
} }
cmd.Env = env
if strings.HasPrefix(platform.Architecture, "arm") && platform.Variant != "" {
goarm, err := getGoarm(platform)
if err != nil {
return "", fmt.Errorf("goarm failure for %s: %v", ip, err)
}
if goarm != "" {
defaultEnv = append(defaultEnv, "GOARM="+goarm)
}
}
cmd.Env = append(defaultEnv, os.Environ()...)
var output bytes.Buffer var output bytes.Buffer
cmd.Stderr = &output cmd.Stderr = &output
@ -410,6 +397,31 @@ func build(ctx context.Context, ip string, dir string, platform v1.Platform, con
return file, nil return file, nil
} }
// buildEnv creates the environment variables used by the `go build` command.
// From `os/exec.Cmd`: If Env contains duplicate environment keys, only the last
// value in the slice for each duplicate key is used.
func buildEnv(platform v1.Platform, configEnv []string) ([]string, error) {
defaultEnv := []string{
"CGO_ENABLED=0",
"GOOS=" + platform.OS,
"GOARCH=" + platform.Architecture,
}
if strings.HasPrefix(platform.Architecture, "arm") && platform.Variant != "" {
goarm, err := getGoarm(platform)
if err != nil {
return nil, fmt.Errorf("goarm failure: %v", err)
}
if goarm != "" {
defaultEnv = append(defaultEnv, "GOARM="+goarm)
}
}
env := append(defaultEnv, os.Environ()...)
env = append(env, configEnv...)
return env, nil
}
func appFilename(importpath string) string { func appFilename(importpath string) string {
base := filepath.Base(importpath) base := filepath.Base(importpath)

@ -232,6 +232,83 @@ func TestGoBuildIsSupportedRefWithModules(t *testing.T) {
} }
} }
func TestBuildEnv(t *testing.T) {
tests := []struct {
description string
platform v1.Platform
configEnv []string
expectedEnvs map[string]string
}{
{
description: "defaults",
platform: v1.Platform{
OS: "linux",
Architecture: "amd64",
},
expectedEnvs: map[string]string{
"GOOS": "linux",
"GOARCH": "amd64",
"CGO_ENABLED": "0",
},
},
{
description: "override a default value",
configEnv: []string{"CGO_ENABLED=1"},
expectedEnvs: map[string]string{
"CGO_ENABLED": "1",
},
},
{
description: "override an envvar and add an envvar",
configEnv: []string{"CGO_ENABLED=1", "GOPRIVATE=git.internal.example.com,source.developers.google.com"},
expectedEnvs: map[string]string{
"CGO_ENABLED": "1",
"GOPRIVATE": "git.internal.example.com,source.developers.google.com",
},
},
{
description: "arm variant",
platform: v1.Platform{
Architecture: "arm",
Variant: "v7",
},
expectedEnvs: map[string]string{
"GOARCH": "arm",
"GOARM": "7",
},
},
{
description: "arm64 variant",
platform: v1.Platform{
Architecture: "arm64",
Variant: "v8",
},
expectedEnvs: map[string]string{
"GOARCH": "arm64",
"GOARM": "7",
},
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
env, err := buildEnv(test.platform, test.configEnv)
if err != nil {
t.Fatalf("unexpected error running buildEnv(): %v", err)
}
envs := map[string]string{}
for _, e := range env {
split := strings.SplitN(e, "=", 2)
envs[split[0]] = split[1]
}
for key, val := range test.expectedEnvs {
if envs[key] != val {
t.Errorf("buildEnv(): expected %s=%s, got %s=%s", key, val, key, envs[key])
}
}
})
}
}
// A helper method we use to substitute for the default "build" method. // A helper method we use to substitute for the default "build" method.
func writeTempFile(_ context.Context, s string, _ string, _ v1.Platform, _ Config) (string, error) { func writeTempFile(_ context.Context, s string, _ string, _ v1.Platform, _ Config) (string, error) {
tmpDir, err := ioutil.TempDir("", "ko") tmpDir, err := ioutil.TempDir("", "ko")