@@ -5,30 +5,28 @@ import (
55 "context"
66 "encoding/json"
77 "fmt"
8+ "io/ioutil"
9+ "os"
10+ "path"
11+
812 "github.com/deislabs/cnab-go/bundle"
13+ cnab "github.com/deislabs/cnab-go/driver"
914 "github.com/docker/app/internal/packager"
1015 "github.com/docker/app/types"
16+ "github.com/docker/buildx/build"
1117 "github.com/docker/buildx/driver"
18+ _ "github.com/docker/buildx/driver/docker" // required to get default driver registered, see driver/docker/factory.go:14
1219 "github.com/docker/buildx/util/progress"
20+ "github.com/docker/cli/cli"
21+ "github.com/docker/cli/cli/command"
1322 "github.com/docker/cli/cli/compose/loader"
1423 "github.com/docker/distribution/reference"
1524 "github.com/moby/buildkit/client"
1625 "github.com/moby/buildkit/session"
1726 "github.com/moby/buildkit/session/auth/authprovider"
27+ "github.com/moby/buildkit/util/appcontext"
1828 "github.com/opencontainers/go-digest"
1929 "github.com/sirupsen/logrus"
20- "io/ioutil"
21- "os"
22- "path"
23- "path/filepath"
24-
25- cnab "github.com/deislabs/cnab-go/driver"
26- "github.com/docker/buildx/build"
27- _ "github.com/docker/buildx/driver/docker" // required to get default driver registered, see driver/docker/factory.go:14
28- "github.com/docker/cli/cli"
29- "github.com/docker/cli/cli/command"
30- composetypes "github.com/docker/cli/cli/compose/types"
31- "github.com/moby/buildkit/util/appcontext"
3230 "github.com/spf13/cobra"
3331)
3432
@@ -37,7 +35,7 @@ type buildOptions struct {
3735 progress string
3836 pull bool
3937 tag string
40- out string
38+ out string
4139}
4240
4341func buildCmd (dockerCli command.Cli ) * cobra.Command {
@@ -83,7 +81,7 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
8381 return nil , err
8482 }
8583
86- _ , err = createInvocationImageBuildOptions (dockerCli , app )
84+ buildopts [ "invocation-image" ] , err = createInvocationImageBuildOptions (dockerCli , app )
8785 if err != nil {
8886 return nil , err
8987 }
@@ -220,57 +218,79 @@ func debugSolveResponses(resp map[string]*client.SolveResponse) {
220218 }
221219}
222220
223- // parseCompose do parse app compose file and extract buildx targets
221+ // parseCompose do parse app compose file and extract buildx Options
222+ // We don't rely on bake's ReadTargets + TargetsToBuildOpt here as we have to skip environment variable interpolation
224223func parseCompose (app * types.App , options buildOptions ) (map [string ]build.Options , error ) {
225224
226225 // Fixme can have > 1 composes ?
227226 parsed , err := loader .ParseYAML (app .Composes ()[0 ])
228227 if err != nil {
229228 return nil , err
230229 }
231- compose , err := loader .Load (composetypes.ConfigDetails {
232- ConfigFiles : []composetypes.ConfigFile {
233- {
234- Config : parsed ,
235- },
236- },
237- })
238- if err != nil {
239- return nil , err
230+
231+ services , ok := parsed ["services" ].(map [string ]interface {})
232+ if ! ok {
233+ return nil , fmt .Errorf ("Invalid compose file: 'services' should be a map" )
240234 }
241235
242236 opts := map [string ]build.Options {}
243- for _ , service := range compose . Services {
244- b := service . Build
245- if b . Context == "" {
246- continue
237+ for name , cfg := range services {
238+ config , ok := cfg .( map [ string ] interface {})
239+ if ! ok {
240+ return nil , fmt . Errorf ( "Invalid compose file: service %s isn't a map" , name )
247241 }
248-
249- if b . Context , err = filepath . Abs ( b . Context ); err != nil {
250- return nil , err
242+ bc , ok := config [ "build" ]
243+ if ! ok {
244+ continue
251245 }
246+ var buildContext string
252247 dockerfilePath := "Dockerfile"
253- if b .Dockerfile != "" {
254- dockerfilePath = b .Dockerfile
248+ buildargs := map [string ]string {}
249+ switch bc .(type ) {
250+ case string :
251+ buildContext = bc .(string )
252+ case map [string ]interface {}:
253+ buildconfig := bc .(map [string ]interface {})
254+ buildContext = buildconfig ["context" ].(string )
255+ if dockerfile , ok := buildconfig ["dockerfile" ]; ok {
256+ dockerfilePath = dockerfile .(string )
257+ }
258+ if a , ok := buildconfig ["args" ]; ok {
259+ switch a .(type ) {
260+ case map [string ]interface {}:
261+ for k , v := range a .(map [string ]interface {}) {
262+ buildargs [k ] = v .(string )
263+ }
264+ // FIXME also support the list-style syntax
265+ default :
266+ return nil , fmt .Errorf ("Invalid compose file: service %s build args is invalid" , name )
267+ }
268+ }
269+ default :
270+ return nil , fmt .Errorf ("Invalid compose file: service %s build is invalid" , name )
255271 }
256- dockerfilePath = path .Join (b .Context , dockerfilePath )
257- opts [service .Name ] = build.Options {
272+
273+ // FIXME the compose file we build from x.dockerapp refers to docker context in parent folder.
274+ // Maybe docker app init should update such relative paths accordingly ?
275+ buildContext = path .Join (app .Path , ".." , buildContext )
276+ dockerfilePath = path .Join (buildContext , dockerfilePath )
277+ opts [name ] = build.Options {
258278 Inputs : build.Inputs {
259- ContextPath : b . Context ,
279+ ContextPath : buildContext ,
260280 DockerfilePath : dockerfilePath ,
261281 },
262- // BuildArgs: t.Args, //FIXME introduce build args support in docker app build
282+ BuildArgs : buildargs ,
263283 NoCache : options .noCache ,
264284 Pull : options .pull ,
265285 }
266286 }
267287 return opts , nil
268288}
269289
270-
271290type sha struct {
272291 d digest.Digest
273292}
293+
274294var _ reference.Named = sha {"" }
275295var _ reference.Digested = sha {"" }
276296
@@ -288,4 +308,3 @@ func (s sha) String() string {
288308func (s sha ) Name () string {
289309 return s .d .String ()
290310}
291-
0 commit comments