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

Commit 4557d51

Browse files
committed
Hide --output command, require a tag
Also apply recommendations from code review Signed-off-by: Nicolas De Loof <[email protected]>
1 parent a5b3f56 commit 4557d51

File tree

10 files changed

+39
-48
lines changed

10 files changed

+39
-48
lines changed

e2e/build_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func TestBuild(t *testing.T) {
2121
dir := fs.NewDir(t, "test-name")
2222
defer dir.Remove()
2323
f := dir.Join("bundle.json")
24-
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"), "--output", f)
24+
cmd.Command = dockerCli.Command("app", "build", path.Join(testDir, "single"), "a-simple-tag", "--output", f)
2525
icmd.RunCmd(cmd).Assert(t, icmd.Success)
2626

2727
data, err := ioutil.ReadFile(f)

e2e/commands_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestRenderFormatters(t *testing.T) {
7575
cmd := info.configuredCmd
7676

7777
appPath := filepath.Join("testdata", "simple", "simple.dockerapp")
78-
cmd.Command = dockerCli.Command("app", "build", appPath)
78+
cmd.Command = dockerCli.Command("app", "build", appPath, "a-simple-tag")
7979
icmd.RunCmd(cmd).Assert(t, icmd.Success)
8080

8181
cmd.Command = dockerCli.Command("app", "render", "--formatter", "json", appPath)

e2e/images_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import (
1212

1313
func insertBundles(t *testing.T, cmd icmd.Cmd, info dindSwarmAndRegistryInfo) {
1414
// Push an application so that we can later pull it by digest
15-
cmd.Command = dockerCli.Command("app", "build", "--tag", info.registryAddress+"/c-myapp", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"))
15+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), info.registryAddress+"/c-myapp")
1616
icmd.RunCmd(cmd).Assert(t, icmd.Success)
17-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "b-simple-app")
17+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "b-simple-app")
1818
icmd.RunCmd(cmd).Assert(t, icmd.Success)
19-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "a-simple-app")
19+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "a-simple-app")
2020
icmd.RunCmd(cmd).Assert(t, icmd.Success)
2121
}
2222

@@ -86,7 +86,7 @@ func TestImageTag(t *testing.T) {
8686
}
8787

8888
// given a first available image
89-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "a-simple-app")
89+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "simple", "simple.dockerapp"), "a-simple-app")
9090
icmd.RunCmd(cmd).Assert(t, icmd.Success)
9191

9292
singleImageExpectation := `APP IMAGE APP NAME
@@ -175,7 +175,7 @@ c-simple-app:latest simple
175175
`)
176176

177177
// given a new application
178-
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "--tag", "push-pull")
178+
cmd.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "push-pull")
179179
icmd.RunCmd(cmd).Assert(t, icmd.Success)
180180
expectImageListOutput(t, cmd, `APP IMAGE APP NAME
181181
a-simple-app:0.1 simple

e2e/pushpull_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func TestPushInstallBundle(t *testing.T) {
194194
bundleFile := tmpDir.Join("bundle.json")
195195

196196
// render the app to a bundle, we use the app from the push pull test above.
197-
cmd.Command = dockerCli.Command("app", "build", "-o", bundleFile, filepath.Join("testdata", "push-pull", "push-pull.dockerapp"))
197+
cmd.Command = dockerCli.Command("app", "build", "-o", bundleFile, filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), "a-simple-app")
198198
icmd.RunCmd(cmd).Assert(t, icmd.Success)
199199

200200
// push it and install to check it is available
@@ -242,7 +242,7 @@ func TestPushInstallBundle(t *testing.T) {
242242
cmdIsolatedStore.Env = append(cmdIsolatedStore.Env, "DOCKER_CONTEXT=swarm-context")
243243

244244
// bundle the app again but this time with a tag to store it into the bundle store
245-
cmdIsolatedStore.Command = dockerCli.Command("app", "build", "--tag", ref2, filepath.Join("testdata", "push-pull", "push-pull.dockerapp"))
245+
cmdIsolatedStore.Command = dockerCli.Command("app", "build", filepath.Join("testdata", "push-pull", "push-pull.dockerapp"), ref2)
246246
icmd.RunCmd(cmdIsolatedStore).Assert(t, icmd.Success)
247247
// Push the app without tagging it explicitly
248248
cmdIsolatedStore.Command = dockerCli.Command("app", "push", ref2)

internal/commands/build/build.go

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ type buildOptions struct {
4141
func Cmd(dockerCli command.Cli) *cobra.Command {
4242
var opts buildOptions
4343
cmd := &cobra.Command{
44-
Use: "build [APPLICATION]",
44+
Use: "build [APPLICATION] [TAG]",
4545
Short: "Build service images for the application",
4646
Example: `$ docker app build myapp.dockerapp`,
47-
Args: cli.ExactArgs(1),
47+
Args: cli.ExactArgs(2),
4848
RunE: func(cmd *cobra.Command, args []string) error {
49+
opts.tag = args[1]
4950
tag, err := runBuild(dockerCli, args[0], opts)
5051
if err == nil {
5152
fmt.Printf("Successfully build %s\n", tag.String())
@@ -58,8 +59,10 @@ func Cmd(dockerCli command.Cli) *cobra.Command {
5859
flags.BoolVar(&opts.noCache, "no-cache", false, "Do not use cache when building the image")
5960
flags.StringVar(&opts.progress, "progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output")
6061
flags.BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image")
62+
63+
// For diagnostic and testing only
6164
flags.StringVarP(&opts.out, "output", "o", "", "Dump generated bundle into a file")
62-
flags.StringVarP(&opts.tag, "tag", "t", "", "Name and optionally a tag in the 'name:tag' format")
65+
flags.MarkHidden("output") //nolint:errcheck
6366

6467
return cmd
6568
}
@@ -70,6 +73,11 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
7073
return nil, err
7174
}
7275

76+
if opt.tag == "" {
77+
// FIXME temporary, until we get support for Digest in bundleStore and other commands
78+
return nil, fmt.Errorf("A tag is required to run docker app build")
79+
}
80+
7381
var ref reference.Named
7482
ref, err = packager.GetNamedTagged(opt.tag)
7583
if err != nil {
@@ -82,17 +90,12 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
8290
}
8391
defer app.Cleanup()
8492

85-
bundle, err := packager.MakeBundleFromApp(dockerCli, app, nil)
86-
if err != nil {
87-
return nil, err
88-
}
89-
9093
buildopts, err := parseCompose(app, opt)
9194
if err != nil {
9295
return nil, err
9396
}
9497

95-
buildopts["invocation-image"], err = createInvocationImageBuildOptions(dockerCli, app)
98+
buildopts["com.docker.app.invocation-image"], err = createInvocationImageBuildOptions(dockerCli, app)
9699
if err != nil {
97100
return nil, err
98101
}
@@ -114,13 +117,17 @@ func runBuild(dockerCli command.Cli, application string, opt buildOptions) (refe
114117

115118
pw := progress.NewPrinter(ctx, os.Stderr, opt.progress)
116119

117-
// We rely on buildx "docker" builder integrated in docker engine, so don't nee a DockerAPI here
120+
// We rely on buildx "docker" builder integrated in docker engine, so don't need a DockerAPI here
118121
resp, err := build.Build(ctx, driverInfo, buildopts, nil, dockerCli.ConfigFile(), pw)
119122
if err != nil {
120123
return nil, err
121124
}
125+
fmt.Fprintln(dockerCli.Out(), "Successfully built service images") //nolint:errcheck
122126

123-
fmt.Println("Successfully built service images")
127+
bundle, err := packager.MakeBundleFromApp(dockerCli, app, nil)
128+
if err != nil {
129+
return nil, err
130+
}
124131
updateBundle(bundle, resp)
125132

126133
if ref == nil {
@@ -140,7 +147,7 @@ func checkMinimalEngineVersion(dockerCli command.Cli) error {
140147
if err != nil {
141148
return err
142149
}
143-
majorVersion, err := strconv.Atoi(info.ServerVersion[:strings.IndexRune(info.ServerVersion, '.')])
150+
majorVersion, err := strconv.Atoi(strings.SplitN(info.ServerVersion, ".", 2)[0])
144151
if err != nil {
145152
return err
146153
}
@@ -154,7 +161,7 @@ func updateBundle(bundle *bundle.Bundle, resp map[string]*client.SolveResponse)
154161
debugSolveResponses(resp)
155162
for service, r := range resp {
156163
digest := r.ExporterResponse["containerimage.digest"]
157-
if service == "invocation-image" {
164+
if service == "com.docker.app.invocation-image" {
158165
bundle.InvocationImages[0].Digest = digest
159166
} else {
160167
image := bundle.Images[service]
@@ -175,21 +182,11 @@ func persistBundle(opt buildOptions, bndl *bundle.Bundle, ref reference.Named) e
175182
}
176183
if opt.out == "-" {
177184
_, err = os.Stdout.Write(b)
178-
if err != nil {
179-
return err
180-
}
181-
} else {
182-
err = ioutil.WriteFile(opt.out, b, 0644)
183-
if err != nil {
184-
return err
185-
}
186-
}
187-
} else {
188-
if err := packager.PersistInBundleStore(ref, bndl); err != nil {
189185
return err
190186
}
187+
return ioutil.WriteFile(opt.out, b, 0644)
191188
}
192-
return nil
189+
return packager.PersistInBundleStore(ref, bndl)
193190
}
194191

195192
func createInvocationImageBuildOptions(dockerCli command.Cli, app *types.App) (build.Options, error) {

internal/commands/build/compose.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package build
33
import (
44
"fmt"
55
"path"
6-
"reflect"
76

87
"github.com/docker/app/types"
98
"github.com/docker/buildx/build"
@@ -14,7 +13,6 @@ import (
1413
// parseCompose do parse app compose file and extract buildx Options
1514
// We don't rely on bake's ReadTargets + TargetsToBuildOpt here as we have to skip environment variable interpolation
1615
func parseCompose(app *types.App, options buildOptions) (map[string]build.Options, error) {
17-
// Fixme can have > 1 composes ?
1816
parsed, err := loader.ParseYAML(app.Composes()[0])
1917
if err != nil {
2018
return nil, err
@@ -25,12 +23,13 @@ func parseCompose(app *types.App, options buildOptions) (map[string]build.Option
2523
return nil, fmt.Errorf("Failed to parse compose file: %s", err)
2624
}
2725

28-
var zeroBuildConfig ImageBuildConfig
2926
opts := map[string]build.Options{}
3027
for _, service := range services {
31-
if reflect.DeepEqual(service.Build, zeroBuildConfig) {
28+
if service.Build == nil {
3229
continue
3330
}
31+
// FIXME docker app init should update relative paths
32+
// compose file has been copied to x.dockerapp, so the relative path to build context get broken
3433
contextPath := path.Join(app.Path, "..", service.Build.Context)
3534
if service.Build.Dockerfile == "" {
3635
service.Build.Dockerfile = "Dockerfile"

internal/commands/build/compose_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ func Test_parseCompose(t *testing.T) {
1414
name string
1515
service string
1616
want build.Options
17-
wantErr bool
1817
}{
1918
{
2019
name: "simple",
@@ -58,17 +57,14 @@ func Test_parseCompose(t *testing.T) {
5857
assert.NilError(t, err)
5958

6059
got, err := parseCompose(app, buildOptions{})
61-
if (err != nil) != tt.wantErr {
62-
t.Errorf("parseCompose() error = %v, wantErr %v", err, tt.wantErr)
63-
return
64-
}
60+
assert.NilError(t, err)
6561
if _, ok := got["dontwant"]; ok {
6662
t.Errorf("parseCompose() should have excluded 'dontwant' service")
6763
return
6864
}
6965
opt, ok := got[tt.service]
7066
if !ok {
71-
t.Errorf("parseCompose() error = %v, wantErr %v", err, tt.wantErr)
67+
t.Errorf("parseCompose() error = %s not converted into a build.Options", tt.service)
7268
return
7369
}
7470
if !reflect.DeepEqual(opt, tt.want) {

internal/commands/build/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
type ServiceConfig struct {
1515
Name string `yaml:"-" json:"-"`
1616

17-
Build ImageBuildConfig
17+
Build *ImageBuildConfig
1818
}
1919

2020
type ImageBuildConfig struct {

internal/commands/root.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import (
66
"io/ioutil"
77
"os"
88

9-
"github.com/docker/app/internal/commands/build"
10-
119
"github.com/docker/app/internal"
10+
"github.com/docker/app/internal/commands/build"
1211
"github.com/docker/app/internal/commands/image"
1312
"github.com/docker/app/internal/store"
1413
"github.com/docker/cli/cli/command"

internal/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
var (
1111
// Version is the git tag that this was built from.
12-
Version = "unknown"
12+
Version = "v0.8.0-169-gbcdf883109"
1313
// GitCommit is the commit that this was built from.
1414
GitCommit = "unknown"
1515
// BuildTime is the time at which the binary was built.

0 commit comments

Comments
 (0)