diff --git a/Dockerfile b/Dockerfile index 91601323..215891fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,13 +2,12 @@ ARG GO_VERSION=1.20 ARG XX_VERSION=1.2.1 -ARG DOCKERD_VERSION=20.10.14 + +ARG DOCKER_VERSION=24.0.2 ARG GOTESTSUM_VERSION=v1.9.0 ARG REGISTRY_VERSION=2.8.0 ARG BUILDKIT_VERSION=v0.11.6 -FROM docker:$DOCKERD_VERSION AS dockerd-release - # xx is a helper for cross-compilation FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx @@ -25,6 +24,22 @@ FROM registry:$REGISTRY_VERSION AS registry FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit +FROM gobase AS docker +ARG TARGETPLATFORM +ARG DOCKER_VERSION +WORKDIR /opt/docker +RUN DOCKER_ARCH=$(case ${TARGETPLATFORM:-linux/amd64} in \ + "linux/amd64") echo "x86_64" ;; \ + "linux/arm/v6") echo "armel" ;; \ + "linux/arm/v7") echo "armhf" ;; \ + "linux/arm64") echo "aarch64" ;; \ + "linux/ppc64le") echo "ppc64le" ;; \ + "linux/s390x") echo "s390x" ;; \ + *) echo "" ;; esac) \ + && echo "DOCKER_ARCH=$DOCKER_ARCH" \ + && wget -qO- "https://download.docker.com/linux/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz" | tar xvz --strip 1 +RUN ./dockerd --version && ./containerd --version && ./ctr --version && ./runc --version + FROM gobase AS gotestsum ARG GOTESTSUM_VERSION ENV GOFLAGS= @@ -77,9 +92,20 @@ FROM binaries-$TARGETOS AS binaries ARG BUILDKIT_SBOM_SCAN_STAGE=true FROM gobase AS integration-test-base -RUN apk add --no-cache docker runc containerd +# https://github.com/docker/docker/blob/master/project/PACKAGERS.md#runtime-dependencies +RUN apk add --no-cache \ + btrfs-progs \ + e2fsprogs \ + e2fsprogs-extra \ + ip6tables \ + iptables \ + openssl \ + shadow-uidmap \ + xfsprogs \ + xz COPY --link --from=gotestsum /out/gotestsum /usr/bin/ COPY --link --from=registry /bin/registry /usr/bin/ +COPY --link --from=docker /opt/docker/* /usr/bin/ COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/ COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/ COPY --link --from=binaries /buildx /usr/bin/ @@ -102,7 +128,7 @@ FROM scratch AS release COPY --from=releaser /out/ / # Shell -FROM docker:$DOCKERD_VERSION AS dockerd-release +FROM docker:$DOCKER_VERSION AS dockerd-release FROM alpine AS shell RUN apk add --no-cache iptables tmux git vim less openssh RUN mkdir -p /usr/local/lib/docker/cli-plugins && ln -s /usr/local/bin/buildx /usr/local/lib/docker/cli-plugins/docker-buildx diff --git a/bake/compose.go b/bake/compose.go index 457fe2c1..6d207eda 100644 --- a/bake/compose.go +++ b/bake/compose.go @@ -37,6 +37,7 @@ func ParseCompose(cfgs []compose.ConfigFile, envs map[string]string) (*Config, e }, func(options *loader.Options) { options.SetProjectName("bake", false) options.SkipNormalization = true + options.Profiles = []string{"*"} }) if err != nil { return nil, err diff --git a/bake/compose_test.go b/bake/compose_test.go index 5074248b..b5f9961b 100644 --- a/bake/compose_test.go +++ b/bake/compose_test.go @@ -36,6 +36,8 @@ services: - token - aws webapp2: + profiles: + - test build: context: ./dir dockerfile_inline: | diff --git a/build/build.go b/build/build.go index 21b502a0..ba6c50fe 100644 --- a/build/build.go +++ b/build/build.go @@ -642,7 +642,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op } // setup extrahosts - extraHosts, err := toBuildkitExtraHosts(opt.ExtraHosts, nodeDriver.IsMobyDriver()) + extraHosts, err := toBuildkitExtraHosts(ctx, opt.ExtraHosts, nodeDriver) if err != nil { return nil, nil, err } diff --git a/build/utils.go b/build/utils.go index 03a85ca4..ee86ff93 100644 --- a/build/utils.go +++ b/build/utils.go @@ -3,10 +3,12 @@ package build import ( "archive/tar" "bytes" + "context" "net" "os" "strings" + "github.com/docker/buildx/driver" "github.com/docker/cli/opts" "github.com/docker/docker/builder/remotecontext/urlutil" "github.com/moby/buildkit/util/gitutil" @@ -57,7 +59,7 @@ func isArchive(header []byte) bool { } // toBuildkitExtraHosts converts hosts from docker key:value format to buildkit's csv format -func toBuildkitExtraHosts(inp []string, mobyDriver bool) (string, error) { +func toBuildkitExtraHosts(ctx context.Context, inp []string, nodeDriver *driver.DriverHandle) (string, error) { if len(inp) == 0 { return "", nil } @@ -67,11 +69,16 @@ func toBuildkitExtraHosts(inp []string, mobyDriver bool) (string, error) { if !ok || host == "" || ip == "" { return "", errors.Errorf("invalid host %s", h) } - // Skip IP address validation for "host-gateway" string with moby driver - if !mobyDriver || ip != mobyHostGatewayName { - if net.ParseIP(ip) == nil { - return "", errors.Errorf("invalid host %s", h) + // If the IP Address is a "host-gateway", replace this value with the + // IP address provided by the worker's label. + if ip == mobyHostGatewayName { + hgip, err := nodeDriver.HostGatewayIP(ctx) + if err != nil { + return "", errors.Wrap(err, "unable to derive the IP value for host-gateway") } + ip = hgip.String() + } else if net.ParseIP(ip) == nil { + return "", errors.Errorf("invalid host %s", h) } hosts = append(hosts, host+"="+ip) } diff --git a/commands/build.go b/commands/build.go index 34ca483f..7feee06e 100644 --- a/commands/build.go +++ b/commands/build.go @@ -487,7 +487,8 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags.StringArrayVar(&options.platforms, "platform", platformsDefault, "Set target platform for build") if isExperimental() { - flags.StringVar(&options.printFunc, "print", "", "Print result of information request (e.g., outline, targets) [experimental]") + flags.StringVar(&options.printFunc, "print", "", "Print result of information request (e.g., outline, targets)") + flags.SetAnnotation("print", "experimentalCLI", nil) } flags.BoolVar(&options.exportPush, "push", false, `Shorthand for "--output=type=registry"`) @@ -514,10 +515,14 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags.StringVar(&options.provenance, "provenance", "", `Shorthand for "--attest=type=provenance"`) if isExperimental() { - flags.StringVar(&invokeFlag, "invoke", "", "Invoke a command after the build [experimental]") - flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect [experimental]") - flags.BoolVar(&options.Detach, "detach", false, "Detach buildx server (supported only on linux) [experimental]") - flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server) [experimental]") + flags.StringVar(&invokeFlag, "invoke", "", "Invoke a command after the build") + flags.SetAnnotation("invoke", "experimentalCLI", nil) + flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect") + flags.SetAnnotation("root", "experimentalCLI", nil) + flags.BoolVar(&options.Detach, "detach", false, "Detach buildx server (supported only on linux)") + flags.SetAnnotation("detach", "experimentalCLI", nil) + flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server)") + flags.SetAnnotation("server-config", "experimentalCLI", nil) } // hidden flags @@ -540,6 +545,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags.BoolVar(&ignoreBool, "squash", false, "Squash newly built layers into a single new layer") flags.MarkHidden("squash") flags.SetAnnotation("squash", "flag-warn", []string{"experimental flag squash is removed with BuildKit. You should squash inside build using a multi-stage Dockerfile for efficiency."}) + flags.SetAnnotation("squash", "experimentalCLI", nil) flags.StringVarP(&ignore, "memory", "m", "", "Memory limit") flags.MarkHidden("memory") diff --git a/commands/debug-shell.go b/commands/debug-shell.go index 6b814094..8e255dda 100644 --- a/commands/debug-shell.go +++ b/commands/debug-shell.go @@ -24,6 +24,9 @@ func debugShellCmd(dockerCli command.Cli) *cobra.Command { cmd := &cobra.Command{ Use: "debug-shell", Short: "Start a monitor", + Annotations: map[string]string{ + "experimentalCLI": "", + }, RunE: func(cmd *cobra.Command, args []string) error { printer, err := progress.NewPrinter(context.TODO(), os.Stderr, os.Stderr, progressMode) if err != nil { @@ -55,9 +58,15 @@ func debugShellCmd(dockerCli command.Cli) *cobra.Command { flags := cmd.Flags() - flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect [experimental]") - flags.BoolVar(&options.Detach, "detach", runtime.GOOS == "linux", "Detach buildx server (supported only on linux) [experimental]") - flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server) [experimental]") + flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect") + flags.SetAnnotation("root", "experimentalCLI", nil) + + flags.BoolVar(&options.Detach, "detach", runtime.GOOS == "linux", "Detach buildx server (supported only on linux)") + flags.SetAnnotation("detach", "experimentalCLI", nil) + + flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server)") + flags.SetAnnotation("server-config", "experimentalCLI", nil) + flags.StringVar(&progressMode, "progress", "auto", `Set type of progress output ("auto", "plain", "tty"). Use plain to show container output`) return cmd diff --git a/controller/build/build.go b/controller/build/build.go index 64069d78..bdf6d8d1 100644 --- a/controller/build/build.go +++ b/controller/build/build.go @@ -54,6 +54,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build NamedContexts: contexts, }, BuildArgs: in.BuildArgs, + CgroupParent: in.CgroupParent, ExtraHosts: in.ExtraHosts, Labels: in.Labels, NetworkMode: in.NetworkMode, diff --git a/docs/reference/buildx.md b/docs/reference/buildx.md index 735912b9..324cb013 100644 --- a/docs/reference/buildx.md +++ b/docs/reference/buildx.md @@ -9,24 +9,21 @@ Extended build capabilities with BuildKit ### Subcommands -| Name | Description | -|:-----------------------------------------------|:-------------------------------------------| -| [`_INTERNAL_SERVE`](buildx__INTERNAL_SERVE.md) | | -| [`bake`](buildx_bake.md) | Build from a file | -| [`build`](buildx_build.md) | Start a build | -| [`create`](buildx_create.md) | Create a new builder instance | -| [`debug-shell`](buildx_debug-shell.md) | Start a monitor | -| [`du`](buildx_du.md) | Disk usage | -| [`imagetools`](buildx_imagetools.md) | Commands to work on images in registry | -| [`inspect`](buildx_inspect.md) | Inspect current builder instance | -| [`install`](buildx_install.md) | Install buildx as a 'docker builder' alias | -| [`ls`](buildx_ls.md) | List builder instances | -| [`prune`](buildx_prune.md) | Remove build cache | -| [`rm`](buildx_rm.md) | Remove a builder instance | -| [`stop`](buildx_stop.md) | Stop builder instance | -| [`uninstall`](buildx_uninstall.md) | Uninstall the 'docker builder' alias | -| [`use`](buildx_use.md) | Set the current builder instance | -| [`version`](buildx_version.md) | Show buildx version information | +| Name | Description | +|:---------------------------------------|:---------------------------------------| +| [`bake`](buildx_bake.md) | Build from a file | +| [`build`](buildx_build.md) | Start a build | +| [`create`](buildx_create.md) | Create a new builder instance | +| [`debug-shell`](buildx_debug-shell.md) | Start a monitor | +| [`du`](buildx_du.md) | Disk usage | +| [`imagetools`](buildx_imagetools.md) | Commands to work on images in registry | +| [`inspect`](buildx_inspect.md) | Inspect current builder instance | +| [`ls`](buildx_ls.md) | List builder instances | +| [`prune`](buildx_prune.md) | Remove build cache | +| [`rm`](buildx_rm.md) | Remove a builder instance | +| [`stop`](buildx_stop.md) | Stop builder instance | +| [`use`](buildx_use.md) | Set the current builder instance | +| [`version`](buildx_version.md) | Show buildx version information | ### Options diff --git a/docs/reference/buildx_build.md b/docs/reference/buildx_build.md index e3dd0c05..5a091b23 100644 --- a/docs/reference/buildx_build.md +++ b/docs/reference/buildx_build.md @@ -24,10 +24,10 @@ Start a build | [`--cache-from`](#cache-from) | `stringArray` | | External cache sources (e.g., `user/app:cache`, `type=local,src=path/to/dir`) | | [`--cache-to`](#cache-to) | `stringArray` | | Cache export destinations (e.g., `user/app:cache`, `type=local,dest=path/to/dir`) | | [`--cgroup-parent`](https://docs.docker.com/engine/reference/commandline/build/#cgroup-parent) | `string` | | Optional parent cgroup for the container | -| `--detach` | | | Detach buildx server (supported only on linux) [experimental] | +| `--detach` | | | Detach buildx server (supported only on linux) | | [`-f`](https://docs.docker.com/engine/reference/commandline/build/#file), [`--file`](https://docs.docker.com/engine/reference/commandline/build/#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) | | `--iidfile` | `string` | | Write the image ID to the file | -| `--invoke` | `string` | | Invoke a command after the build [experimental] | +| `--invoke` | `string` | | Invoke a command after the build | | `--label` | `stringArray` | | Set metadata for an image | | [`--load`](#load) | | | Shorthand for `--output=type=docker` | | [`--metadata-file`](#metadata-file) | `string` | | Write build result metadata to the file | @@ -36,16 +36,16 @@ Start a build | `--no-cache-filter` | `stringArray` | | Do not cache specified stages | | [`-o`](#output), [`--output`](#output) | `stringArray` | | Output destination (format: `type=local,dest=path`) | | [`--platform`](#platform) | `stringArray` | | Set target platform for build | -| `--print` | `string` | | Print result of information request (e.g., outline, targets) [experimental] | +| `--print` | `string` | | Print result of information request (e.g., outline, targets) | | [`--progress`](#progress) | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output | | [`--provenance`](#provenance) | `string` | | Shorthand for `--attest=type=provenance` | | `--pull` | | | Always attempt to pull all referenced images | | [`--push`](#push) | | | Shorthand for `--output=type=registry` | | `-q`, `--quiet` | | | Suppress the build output and print image ID on success | -| `--root` | `string` | | Specify root directory of server to connect [experimental] | +| `--root` | `string` | | Specify root directory of server to connect | | [`--sbom`](#sbom) | `string` | | Shorthand for `--attest=type=sbom` | | [`--secret`](#secret) | `stringArray` | | Secret to expose to the build (format: `id=mysecret[,src=/local/secret]`) | -| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) [experimental] | +| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) | | [`--shm-size`](#shm-size) | `bytes` | `0` | Size of `/dev/shm` | | [`--ssh`](#ssh) | `stringArray` | | SSH agent socket or keys to expose to the build (format: `default\|[=\|[,]]`) | | [`-t`](https://docs.docker.com/engine/reference/commandline/build/#tag), [`--tag`](https://docs.docker.com/engine/reference/commandline/build/#tag) | `stringArray` | | Name and optionally a tag (format: `name:tag`) | diff --git a/docs/reference/buildx_debug-shell.md b/docs/reference/buildx_debug-shell.md index 35a1f26e..c06885ae 100644 --- a/docs/reference/buildx_debug-shell.md +++ b/docs/reference/buildx_debug-shell.md @@ -8,10 +8,10 @@ Start a monitor | Name | Type | Default | Description | |:------------------|:---------|:--------|:-----------------------------------------------------------------------------------------| | `--builder` | `string` | | Override the configured builder instance | -| `--detach` | | | Detach buildx server (supported only on linux) [experimental] | +| `--detach` | | | Detach buildx server (supported only on linux) | | `--progress` | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output | -| `--root` | `string` | | Specify root directory of server to connect [experimental] | -| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) [experimental] | +| `--root` | `string` | | Specify root directory of server to connect | +| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) | diff --git a/docs/reference/buildx_install.md b/docs/reference/buildx_install.md deleted file mode 100644 index 4f8f370d..00000000 --- a/docs/reference/buildx_install.md +++ /dev/null @@ -1,11 +0,0 @@ -# buildx install - -``` -docker buildx install -``` - - -Install buildx as a 'docker builder' alias - - - diff --git a/docs/reference/buildx_uninstall.md b/docs/reference/buildx_uninstall.md deleted file mode 100644 index 524762e3..00000000 --- a/docs/reference/buildx_uninstall.md +++ /dev/null @@ -1,11 +0,0 @@ -# buildx uninstall - -``` -docker buildx uninstall -``` - - -Uninstall the 'docker builder' alias - - - diff --git a/driver/manager.go b/driver/manager.go index 657e5094..b4ec318f 100644 --- a/driver/manager.go +++ b/driver/manager.go @@ -2,17 +2,17 @@ package driver import ( "context" + "net" "os" "sort" "strings" "sync" - "k8s.io/client-go/rest" - dockerclient "github.com/docker/docker/client" "github.com/moby/buildkit/client" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + "k8s.io/client-go/rest" ) type Factory interface { @@ -154,6 +154,9 @@ type DriverHandle struct { features map[Feature]bool historyAPISupportedOnce sync.Once historyAPISupported bool + hostGatewayIPOnce sync.Once + hostGatewayIP net.IP + hostGatewayIPErr error } func (d *DriverHandle) Client(ctx context.Context) (*client.Client, error) { @@ -178,3 +181,36 @@ func (d *DriverHandle) HistoryAPISupported(ctx context.Context) bool { }) return d.historyAPISupported } + +func (d *DriverHandle) HostGatewayIP(ctx context.Context) (net.IP, error) { + d.hostGatewayIPOnce.Do(func() { + if !d.Driver.IsMobyDriver() { + d.hostGatewayIPErr = errors.New("host-gateway is only supported with the docker driver") + return + } + c, err := d.Client(ctx) + if err != nil { + d.hostGatewayIPErr = err + return + } + workers, err := c.ListWorkers(ctx) + if err != nil { + d.hostGatewayIPErr = errors.Wrap(err, "listing workers") + return + } + for _, w := range workers { + // should match github.com/docker/docker/builder/builder-next/worker/label.HostGatewayIP const + if v, ok := w.Labels["org.mobyproject.buildkit.worker.moby.host-gateway-ip"]; ok && v != "" { + ip := net.ParseIP(v) + if ip == nil { + d.hostGatewayIPErr = errors.Errorf("failed to parse host-gateway IP: %s", v) + return + } + d.hostGatewayIP = ip + return + } + } + d.hostGatewayIPErr = errors.New("host-gateway IP not found") + }) + return d.hostGatewayIP, d.hostGatewayIPErr +} diff --git a/go.mod b/go.mod index 3a535ad4..1ec5c771 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/continuity v0.4.1 github.com/containerd/typeurl/v2 v2.1.1 github.com/docker/cli v24.0.2+incompatible - github.com/docker/cli-docs-tool v0.5.1 + github.com/docker/cli-docs-tool v0.6.0 github.com/docker/distribution v2.8.2+incompatible github.com/docker/docker v24.0.2+incompatible github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 3d37832a..11298e7c 100644 --- a/go.sum +++ b/go.sum @@ -151,8 +151,8 @@ github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa h1:L9 github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM= github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli-docs-tool v0.5.1 h1:jIk/cCZurZERhALPVKhqlNxTQGxn2kcI+56gE57PQXg= -github.com/docker/cli-docs-tool v0.5.1/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o= +github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA= +github.com/docker/cli-docs-tool v0.6.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg= diff --git a/tests/build.go b/tests/build.go index f82c80b3..2d49c066 100644 --- a/tests/build.go +++ b/tests/build.go @@ -3,10 +3,11 @@ package tests import ( "bytes" "encoding/json" - "errors" "fmt" "os" + "path" "path/filepath" + "regexp" "strings" "testing" @@ -16,6 +17,7 @@ import ( "github.com/moby/buildkit/util/testutil" "github.com/moby/buildkit/util/testutil/integration" "github.com/opencontainers/go-digest" + "github.com/pkg/errors" "github.com/stretchr/testify/require" ) @@ -32,6 +34,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){ testBuildLocalExport, testBuildRegistryExport, testBuildTarExport, + testBuildDetailsLink, } func testBuild(t *testing.T, sb integration.Sandbox) { @@ -139,6 +142,48 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) { require.Equal(t, dgst, digest.Digest(md.ConfigDigest)) } +func testBuildDetailsLink(t *testing.T, sb integration.Sandbox) { + buildDetailsPattern := regexp.MustCompile(`(?m)^View build details: docker-desktop://dashboard/build/[^/]+/[^/]+/[^/]+\n$`) + + // build simple dockerfile + dockerfile := []byte(`FROM busybox:latest +RUN echo foo > /bar`) + dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) + cmd := buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) + out, err := cmd.CombinedOutput() + require.NoError(t, err, string(out)) + require.False(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("build details link not expected in output, got %q", out)) + + // create desktop-build .lastaccess file + home, err := os.UserHomeDir() // TODO: sandbox should create a temp home dir and expose it through its interface + require.NoError(t, err) + dbDir := path.Join(home, ".docker", "desktop-build") + require.NoError(t, os.MkdirAll(dbDir, 0755)) + dblaFile, err := os.Create(path.Join(dbDir, ".lastaccess")) + require.NoError(t, err) + defer func() { + dblaFile.Close() + if err := os.Remove(dblaFile.Name()); err != nil { + t.Fatal(err) + } + }() + + // build again + cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) + out, err = cmd.CombinedOutput() + require.NoError(t, err, string(out)) + require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out)) + + // build erroneous dockerfile + dockerfile = []byte(`FROM busybox:latest +RUN exit 1`) + dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) + cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir)) + out, err = cmd.CombinedOutput() + require.Error(t, err, string(out)) + require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out)) +} + func createTestProject(t *testing.T) string { dockerfile := []byte(` FROM busybox:latest AS base diff --git a/util/desktop/desktop.go b/util/desktop/desktop.go index 6ddf74a5..7fa4ee6d 100644 --- a/util/desktop/desktop.go +++ b/util/desktop/desktop.go @@ -81,6 +81,6 @@ func (e *ErrorWithBuildRef) Print(w io.Writer) error { if _, err := console.ConsoleFromFile(os.Stderr); err == nil { term = true } - fmt.Fprintf(w, "\n%s", BuildDetailsOutput(map[string]string{"default": e.Ref}, term)) + fmt.Fprintf(w, "\n%s\n", BuildDetailsOutput(map[string]string{"default": e.Ref}, term)) return nil } diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go b/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go index 73d05c8a..1dee58c0 100644 --- a/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go +++ b/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go @@ -53,6 +53,12 @@ func (c *Client) GenMarkdownTree(cmd *cobra.Command) error { return nil } + // Skip hidden command + if cmd.Hidden { + log.Printf("INFO: Skipping Markdown for %q (hidden command)", cmd.CommandPath()) + return nil + } + log.Printf("INFO: Generating Markdown for %q", cmd.CommandPath()) mdFile := mdFilename(cmd) sourcePath := filepath.Join(c.source, mdFile) @@ -208,6 +214,9 @@ func mdCmdOutput(cmd *cobra.Command, old string) (string, error) { b.WriteString("### Subcommands\n\n") table := newMdTable("Name", "Description") for _, c := range cmd.Commands() { + if c.Hidden { + continue + } table.AddRow(fmt.Sprintf("[`%s`](%s)", c.Name(), mdFilename(c)), c.Short) } b.WriteString(table.String() + "\n") diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go index f6ae6b85..52352429 100644 --- a/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go +++ b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go @@ -62,6 +62,7 @@ type cmdDoc struct { InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` Example string `yaml:"examples,omitempty"` Deprecated bool + Hidden bool MinAPIVersion string `yaml:"min_api_version,omitempty"` Experimental bool ExperimentalCLI bool @@ -155,6 +156,7 @@ func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error { Long: forceMultiLine(cmd.Long, longMaxWidth), Example: cmd.Example, Deprecated: len(cmd.Deprecated) > 0, + Hidden: cmd.Hidden, } if len(cliDoc.Long) == 0 { diff --git a/vendor/modules.txt b/vendor/modules.txt index 373e7f00..095cbc6a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -231,7 +231,7 @@ github.com/docker/cli/cli/streams github.com/docker/cli/cli/trust github.com/docker/cli/cli/version github.com/docker/cli/opts -# github.com/docker/cli-docs-tool v0.5.1 +# github.com/docker/cli-docs-tool v0.6.0 ## explicit; go 1.18 github.com/docker/cli-docs-tool github.com/docker/cli-docs-tool/annotation