@@ -3,36 +3,43 @@ package build
33import (
44 "fmt"
55 "path"
6+ "path/filepath"
7+ "strings"
8+
9+ "github.com/docker/app/render"
610
711 "github.com/docker/app/types"
812 "github.com/docker/buildx/build"
9- "github.com/docker/cli/cli/compose/loader"
1013 compose "github.com/docker/cli/cli/compose/types"
1114)
1215
1316// parseCompose do parse app compose file and extract buildx Options
1417// We don't rely on bake's ReadTargets + TargetsToBuildOpt here as we have to skip environment variable interpolation
15- func parseCompose (app * types.App , contextPath string , options buildOptions ) (map [string ]build.Options , []ServiceConfig , error ) {
16- parsed , err := loader . ParseYAML (app . Composes ()[ 0 ] )
18+ func parseCompose (app * types.App , contextPath string , options buildOptions ) (map [string ]build.Options , []compose. ServiceConfig , error ) {
19+ comp , err := render . Render (app , nil , nil )
1720 if err != nil {
1821 return nil , nil , err
1922 }
2023
21- services , err := load (parsed , options .args )
22- if err != nil {
23- return nil , nil , fmt .Errorf ("Failed to parse compose file: %s" , err )
24- }
24+ buildArgs := buildArgsToMap (options .args )
2525
26- pulledServices := []ServiceConfig {}
26+ pulledServices := []compose. ServiceConfig {}
2727 opts := map [string ]build.Options {}
28- for _ , service := range services {
29- if service .Build == nil {
28+ for _ , service := range comp .Services {
29+ // Sanity check
30+ for _ , vol := range service .Volumes {
31+ if vol .Type == "bind" && ! filepath .IsAbs (vol .Source ) {
32+ return nil , nil , fmt .Errorf ("invalid service %q: can't use relative path as volume source" , service .Name )
33+ }
34+ }
35+
36+ if service .Build .Context == "" {
3037 pulledServices = append (pulledServices , service )
3138 continue
3239 }
3340 var tags []string
34- if service .Image != nil {
35- tags = append (tags , * service .Image )
41+ if service .Image != "" {
42+ tags = append (tags , service .Image )
3643 }
3744
3845 if service .Build .Dockerfile == "" {
@@ -43,7 +50,7 @@ func parseCompose(app *types.App, contextPath string, options buildOptions) (map
4350 ContextPath : path .Join (contextPath , service .Build .Context ),
4451 DockerfilePath : path .Join (contextPath , service .Build .Context , service .Build .Dockerfile ),
4552 },
46- BuildArgs : flatten (service .Build .Args ),
53+ BuildArgs : flatten (mergeArgs ( service .Build .Args , buildArgs ) ),
4754 NoCache : options .noCache ,
4855 Pull : options .pull ,
4956 Tags : tags ,
@@ -52,6 +59,33 @@ func parseCompose(app *types.App, contextPath string, options buildOptions) (map
5259 return opts , pulledServices , nil
5360}
5461
62+ func buildArgsToMap (array []string ) map [string ]string {
63+ result := make (map [string ]string )
64+ for _ , value := range array {
65+ parts := strings .SplitN (value , "=" , 2 )
66+ key := parts [0 ]
67+ if len (parts ) == 1 {
68+ result [key ] = ""
69+ } else {
70+ result [key ] = parts [1 ]
71+ }
72+ }
73+ return result
74+ }
75+
76+ func mergeArgs (src compose.MappingWithEquals , values map [string ]string ) compose.MappingWithEquals {
77+ for key := range src {
78+ if val , ok := values [key ]; ok {
79+ if val == "" {
80+ src [key ] = nil
81+ } else {
82+ src [key ] = & val
83+ }
84+ }
85+ }
86+ return src
87+ }
88+
5589func flatten (in compose.MappingWithEquals ) map [string ]string {
5690 if len (in ) == 0 {
5791 return nil
0 commit comments