Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 029c2c1

Browse files
committed
Split build.go into smaller dedicated files
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 05cad91 commit 029c2c1

File tree

18 files changed

+195
-114
lines changed

18 files changed

+195
-114
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
version: "3.6"
22
services:
33
web:
4-
build:
5-
context: ./web
4+
build: ./web
65
port:
76
${services.web.port}:8080
87
worker:
98
build:
109
context: ./worker
10+
dockerfile: Dockerfile.worker
1111
db:
1212
image: postgres:9.3

internal/commands/build.go renamed to internal/commands/build/build.go

Lines changed: 2 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
package commands
1+
package build
22

33
import (
44
"bytes"
55
"context"
66
"encoding/json"
77
"errors"
88
"fmt"
9-
"io"
109
"io/ioutil"
1110
"os"
12-
"path"
1311
"strconv"
1412
"strings"
1513

@@ -23,13 +21,11 @@ import (
2321
"github.com/docker/buildx/util/progress"
2422
"github.com/docker/cli/cli"
2523
"github.com/docker/cli/cli/command"
26-
"github.com/docker/cli/cli/compose/loader"
2724
"github.com/docker/distribution/reference"
2825
"github.com/moby/buildkit/client"
2926
"github.com/moby/buildkit/session"
3027
"github.com/moby/buildkit/session/auth/authprovider"
3128
"github.com/moby/buildkit/util/appcontext"
32-
"github.com/opencontainers/go-digest"
3329
"github.com/sirupsen/logrus"
3430
"github.com/spf13/cobra"
3531
)
@@ -42,7 +38,7 @@ type buildOptions struct {
4238
out string
4339
}
4440

45-
func buildCmd(dockerCli command.Cli) *cobra.Command {
41+
func BuildCmd(dockerCli command.Cli) *cobra.Command {
4642
var opts buildOptions
4743
cmd := &cobra.Command{
4844
Use: "build [APPLICATION]",
@@ -176,17 +172,6 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
176172
return ref, nil
177173
}
178174

179-
func computeDigest(bundle io.WriterTo) (reference.Named, error) {
180-
b := bytes.Buffer{}
181-
_, err := bundle.WriteTo(&b)
182-
if err != nil {
183-
return nil, err
184-
}
185-
digest := digest.SHA256.FromBytes(b.Bytes())
186-
ref := sha{digest}
187-
return ref, nil
188-
}
189-
190175
func createInvocationImageBuildOptions(dockerCli command.Cli, app *types.App) (build.Options, error) {
191176
buildContext := bytes.NewBuffer(nil)
192177
if err := packager.PackInvocationImageContext(dockerCli, app, buildContext); err != nil {
@@ -233,95 +218,3 @@ func debugSolveResponses(resp map[string]*client.SolveResponse) {
233218
}
234219
}
235220
}
236-
237-
// parseCompose do parse app compose file and extract buildx Options
238-
// We don't rely on bake's ReadTargets + TargetsToBuildOpt here as we have to skip environment variable interpolation
239-
func parseCompose(app *types.App, options buildOptions) (map[string]build.Options, error) {
240-
241-
// Fixme can have > 1 composes ?
242-
parsed, err := loader.ParseYAML(app.Composes()[0])
243-
if err != nil {
244-
return nil, err
245-
}
246-
247-
services, ok := parsed["services"].(map[string]interface{})
248-
if !ok {
249-
return nil, fmt.Errorf("Invalid compose file: 'services' should be a map")
250-
}
251-
252-
opts := map[string]build.Options{}
253-
for name, cfg := range services {
254-
config, ok := cfg.(map[string]interface{})
255-
if !ok {
256-
return nil, fmt.Errorf("Invalid compose file: service %s isn't a map", name)
257-
}
258-
bc, ok := config["build"]
259-
if !ok {
260-
continue
261-
}
262-
var buildContext string
263-
dockerfilePath := "Dockerfile"
264-
var buildargs map[string]string
265-
switch bc.(type) {
266-
case string:
267-
buildContext = bc.(string)
268-
case map[string]interface{}:
269-
buildconfig := bc.(map[string]interface{})
270-
buildContext = buildconfig["context"].(string)
271-
if dockerfile, ok := buildconfig["dockerfile"]; ok {
272-
dockerfilePath = dockerfile.(string)
273-
}
274-
if a, ok := buildconfig["args"]; ok {
275-
switch a.(type) {
276-
case map[string]interface{}:
277-
buildargs = make(map[string]string)
278-
for k, v := range a.(map[string]interface{}) {
279-
buildargs[k] = v.(string)
280-
}
281-
// FIXME also support the list-style syntax
282-
default:
283-
return nil, fmt.Errorf("Invalid compose file: service %s build args is invalid", name)
284-
}
285-
}
286-
default:
287-
return nil, fmt.Errorf("Invalid compose file: service %s build is invalid", name)
288-
}
289-
290-
// FIXME the compose file we build from x.dockerapp refers to docker context in parent folder.
291-
// Maybe docker app init should update such relative paths accordingly ?
292-
buildContext = path.Join(app.Path, "..", buildContext)
293-
dockerfilePath = path.Join(buildContext, dockerfilePath)
294-
opts[name] = build.Options{
295-
Inputs: build.Inputs{
296-
ContextPath: buildContext,
297-
DockerfilePath: dockerfilePath,
298-
},
299-
BuildArgs: buildargs,
300-
NoCache: options.noCache,
301-
Pull: options.pull,
302-
}
303-
}
304-
return opts, nil
305-
}
306-
307-
type sha struct {
308-
d digest.Digest
309-
}
310-
311-
var _ reference.Named = sha{""}
312-
var _ reference.Digested = sha{""}
313-
314-
// Digest implement Digested.Digest()
315-
func (s sha) Digest() digest.Digest {
316-
return s.d
317-
}
318-
319-
// Digest implement Named.String()
320-
func (s sha) String() string {
321-
return s.d.String()
322-
}
323-
324-
// Digest implement Named.Name()
325-
func (s sha) Name() string {
326-
return s.d.String()
327-
}

internal/commands/build/compose.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package build
2+
3+
import (
4+
"fmt"
5+
"path"
6+
"reflect"
7+
8+
"github.com/docker/app/types"
9+
"github.com/docker/buildx/build"
10+
"github.com/docker/cli/cli/compose/loader"
11+
compose "github.com/docker/cli/cli/compose/types"
12+
)
13+
14+
// parseCompose do parse app compose file and extract buildx Options
15+
// We don't rely on bake's ReadTargets + TargetsToBuildOpt here as we have to skip environment variable interpolation
16+
func parseCompose(app *types.App, options buildOptions) (map[string]build.Options, error) {
17+
18+
// Fixme can have > 1 composes ?
19+
parsed, err := loader.ParseYAML(app.Composes()[0])
20+
if err != nil {
21+
return nil, err
22+
}
23+
24+
services, err := Load(parsed)
25+
if err != nil {
26+
return nil, fmt.Errorf("Failed to parse compose file: %s", err)
27+
}
28+
29+
var zeroBuildConfig BuildConfig
30+
opts := map[string]build.Options{}
31+
for _, service := range services {
32+
if reflect.DeepEqual(service.Build, zeroBuildConfig) {
33+
continue
34+
}
35+
contextPath := path.Join(app.Path, "..", service.Build.Context)
36+
if service.Build.Dockerfile == "" {
37+
service.Build.Dockerfile = "Dockerfile"
38+
}
39+
dockerfile := path.Join(contextPath, service.Build.Dockerfile)
40+
opts[service.Name] = build.Options{
41+
Inputs: build.Inputs{
42+
ContextPath: contextPath,
43+
DockerfilePath: dockerfile,
44+
},
45+
BuildArgs: flatten(service.Build.Args),
46+
NoCache: options.noCache,
47+
Pull: options.pull,
48+
}
49+
}
50+
return opts, nil
51+
}
52+
53+
func flatten(in compose.MappingWithEquals) map[string]string {
54+
if len(in) == 0 {
55+
return nil
56+
}
57+
out := make(map[string]string)
58+
for k, v := range in {
59+
if v == nil {
60+
continue
61+
}
62+
out[k] = *v
63+
}
64+
return out
65+
}

internal/commands/build_test.go renamed to internal/commands/build/compose_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package commands
1+
package build
22

33
import (
44
"reflect"
@@ -59,6 +59,10 @@ func Test_parseCompose(t *testing.T) {
5959
t.Errorf("parseCompose() error = %v, wantErr %v", err, tt.wantErr)
6060
return
6161
}
62+
if _, ok := got["dontwant"]; ok {
63+
t.Errorf("parseCompose() should have excluded 'dontwant' service")
64+
return
65+
}
6266
opt, ok := got[tt.service]
6367
if !ok {
6468
t.Errorf("parseCompose() error = %v, wantErr %v", err, tt.wantErr)

internal/commands/build/digest.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package build
2+
3+
import (
4+
"bytes"
5+
"io"
6+
7+
"github.com/docker/distribution/reference"
8+
"github.com/opencontainers/go-digest"
9+
)
10+
11+
// computeDigest takes a bundle and produce a unigue reference.Digested
12+
func computeDigest(bundle io.WriterTo) (reference.Named, error) {
13+
b := bytes.Buffer{}
14+
_, err := bundle.WriteTo(&b)
15+
if err != nil {
16+
return nil, err
17+
}
18+
digest := digest.SHA256.FromBytes(b.Bytes())
19+
ref := sha{digest}
20+
return ref, nil
21+
}
22+
23+
type sha struct {
24+
d digest.Digest
25+
}
26+
27+
var _ reference.Named = sha{""}
28+
var _ reference.Digested = sha{""}
29+
30+
// Digest implement Digested.Digest()
31+
func (s sha) Digest() digest.Digest {
32+
return s.d
33+
}
34+
35+
// Digest implement Named.String()
36+
func (s sha) String() string {
37+
return s.d.String()
38+
}
39+
40+
// Digest implement Named.Name()
41+
func (s sha) Name() string {
42+
return s.d.String()
43+
}

internal/commands/testdata/context.dockerapp/docker-compose.yml renamed to internal/commands/build/testdata/context.dockerapp/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ services:
33
web:
44
build:
55
context: ./web
6-
dockerfile: Dockerfile.custom
6+
dockerfile: Dockerfile.custom

internal/commands/testdata/simple.dockerapp/docker-compose.yml renamed to internal/commands/build/testdata/simple.dockerapp/docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ version: "3.6"
22
services:
33
web:
44
build: ./web
5+
dontwant:
6+
image: postgres:9.3

0 commit comments

Comments
 (0)