Skip to content

Commit

Permalink
Merge pull request #1261 from crazy-max/bake-env
Browse files Browse the repository at this point in the history
bake: load .env file from working dir for compose files
  • Loading branch information
tonistiigi authored Aug 10, 2022
2 parents 005bc00 + 7d8a6bc commit 5b2e1d3
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 63 deletions.
26 changes: 24 additions & 2 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,21 @@ func dedupMap(ms ...map[string]string) map[string]string {
return res
}

func sliceToMap(env []string) (res map[string]string) {
res = make(map[string]string)
for _, s := range env {
kv := strings.SplitN(s, "=", 2)
key := kv[0]
switch {
case len(kv) == 1:
res[key] = ""
default:
res[key] = kv[1]
}
}
return
}

func ParseFiles(files []File, defaults map[string]string) (_ *Config, err error) {
defer func() {
err = formatHCLError(err, files)
Expand Down Expand Up @@ -242,15 +257,22 @@ func ParseFile(dt []byte, fn string) (*Config, error) {
}

func ParseComposeFile(dt []byte, fn string) (*Config, bool, error) {
envs := sliceToMap(os.Environ())
if wd, err := os.Getwd(); err == nil {
envs, err = loadDotEnv(envs, wd)
if err != nil {
return nil, true, err
}
}
fnl := strings.ToLower(fn)
if strings.HasSuffix(fnl, ".yml") || strings.HasSuffix(fnl, ".yaml") {
cfg, err := ParseCompose(dt)
cfg, err := ParseCompose(dt, envs)
return cfg, true, err
}
if strings.HasSuffix(fnl, ".json") || strings.HasSuffix(fnl, ".hcl") {
return nil, false, nil
}
cfg, err := ParseCompose(dt)
cfg, err := ParseCompose(dt, envs)
return cfg, err == nil, err
}

Expand Down
60 changes: 41 additions & 19 deletions bake/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package bake
import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/compose-spec/compose-go/dotenv"
"github.com/compose-spec/compose-go/loader"
compose "github.com/compose-spec/compose-go/types"
"github.com/pkg/errors"
Expand All @@ -14,34 +16,18 @@ import (
// errComposeInvalid is returned when a compose file is invalid
var errComposeInvalid = errors.New("invalid compose file")

func parseCompose(dt []byte) (*compose.Project, error) {
return loader.Load(compose.ConfigDetails{
func ParseCompose(dt []byte, envs map[string]string) (*Config, error) {
cfg, err := loader.Load(compose.ConfigDetails{
ConfigFiles: []compose.ConfigFile{
{
Content: dt,
},
},
Environment: envMap(os.Environ()),
Environment: envs,
}, func(options *loader.Options) {
options.SkipNormalization = true
options.SkipConsistencyCheck = true
})
}

func envMap(env []string) map[string]string {
result := make(map[string]string, len(env))
for _, s := range env {
kv := strings.SplitN(s, "=", 2)
if len(kv) != 2 {
continue
}
result[kv[0]] = kv[1]
}
return result
}

func ParseCompose(dt []byte) (*Config, error) {
cfg, err := parseCompose(dt)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -124,6 +110,42 @@ func ParseCompose(dt []byte) (*Config, error) {
return &c, nil
}

func loadDotEnv(curenv map[string]string, workingDir string) (map[string]string, error) {
if curenv == nil {
curenv = make(map[string]string)
}

ef, err := filepath.Abs(filepath.Join(workingDir, ".env"))
if err != nil {
return nil, err
}

if _, err = os.Stat(ef); os.IsNotExist(err) {
return curenv, nil
} else if err != nil {
return nil, err
}

dt, err := os.ReadFile(ef)
if err != nil {
return nil, err
}

envs, err := dotenv.UnmarshalBytes(dt)
if err != nil {
return nil, err
}

for k, v := range envs {
if _, set := curenv[k]; set {
continue
}
curenv[k] = v
}

return curenv, nil
}

func flatten(in compose.MappingWithEquals) compose.Mapping {
if len(in) == 0 {
return nil
Expand Down
Loading

0 comments on commit 5b2e1d3

Please sign in to comment.