Skip to content

Commit c1eef29

Browse files
committed
cli/push: Print aux notes
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
1 parent cdd35e5 commit c1eef29

3 files changed

Lines changed: 85 additions & 6 deletions

File tree

cli/command/image/push.go

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package image
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
"io"
78
"os"
@@ -12,6 +13,7 @@ import (
1213
"github.com/docker/cli/cli/command"
1314
"github.com/docker/cli/cli/command/completion"
1415
"github.com/docker/cli/cli/streams"
16+
"github.com/docker/docker/api/types/auxprogress"
1517
"github.com/docker/docker/api/types/image"
1618
registrytypes "github.com/docker/docker/api/types/registry"
1719
"github.com/docker/docker/pkg/jsonmessage"
@@ -73,9 +75,8 @@ func RunPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error
7375

7476
printNote(dockerCli, `Selecting a single platform will only push one matching image manifest from a multi-platform image index.
7577
This means that any other components attached to the multi-platform image index (like Buildkit attestations) won't be pushed.
76-
If you want to only push a single platform image while preserving the attestations, please build an image with only that platform and push it instead.
77-
Example: echo "FROM %s" | docker build - --platform %s -t <NEW-TAG>
78-
`, opts.remote, opts.platform)
78+
If you want to only push a single platform image while preserving the attestations, please use 'docker convert\n'
79+
`)
7980
}
8081

8182
ref, err := reference.ParseNormalizedNamed(opts.remote)
@@ -116,20 +117,71 @@ Example: echo "FROM %s" | docker build - --platform %s -t <NEW-TAG>
116117
return err
117118
}
118119

120+
defer func() {
121+
for _, note := range notes {
122+
fmt.Fprintln(dockerCli.Err(), "")
123+
printNote(dockerCli, note)
124+
}
125+
}()
126+
119127
defer responseBody.Close()
120128
if !opts.untrusted {
121129
// TODO PushTrustedReference currently doesn't respect `--quiet`
122130
return PushTrustedReference(dockerCli, repoInfo, ref, authConfig, responseBody)
123131
}
124132

125133
if opts.quiet {
126-
err = jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(io.Discard), nil)
134+
err = jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(io.Discard), handleAux(dockerCli))
127135
if err == nil {
128136
fmt.Fprintln(dockerCli.Out(), ref.String())
129137
}
130138
return err
131139
}
132-
return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil)
140+
return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), handleAux(dockerCli))
141+
}
142+
143+
var notes []string
144+
145+
func handleAux(dockerCli command.Cli) func(jm jsonmessage.JSONMessage) {
146+
return func(jm jsonmessage.JSONMessage) {
147+
b := []byte(*jm.Aux)
148+
149+
var stripped auxprogress.ManifestPushedInsteadOfIndex
150+
err := json.Unmarshal(b, &stripped)
151+
if err == nil {
152+
if stripped.ManifestPushedInsteadOfIndex {
153+
note := fmt.Sprintf("Not all multiplatform-content is present and only the available single-platform image was pushed\n%s -> %s",
154+
red(stripped.OriginalIndex.Digest.String()),
155+
green(stripped.SelectedManifest.Digest.String()))
156+
notes = append(notes, note)
157+
}
158+
}
159+
160+
var missing auxprogress.ContentMissing
161+
err = json.Unmarshal(b, &missing)
162+
if missing.ContentMissing {
163+
note := `You're trying to push a manifest list/index which
164+
references multiple platform specific manifests, but not all of them are available locally
165+
or available to the remote repository.
166+
167+
Make sure you have all the referenced content and try again.
168+
169+
You can also push only a single platform specific manifest directly by specifying the platform you want to push with the --platform flag.`
170+
notes = append(notes, note)
171+
}
172+
}
173+
}
174+
175+
func red(text string) string {
176+
return fmt.Sprintf("\033[31m%s\033[0m", text)
177+
}
178+
179+
func green(text string) string {
180+
return fmt.Sprintf("\033[32m%s\033[0m", text)
181+
}
182+
183+
func bold(text string) string {
184+
return fmt.Sprintf("\033[1m%s\033[0m", text)
133185
}
134186

135187
func printNote(dockerCli command.Cli, format string, args ...any) {
@@ -138,5 +190,5 @@ func printNote(dockerCli command.Cli, format string, args ...any) {
138190
} else {
139191
_, _ = fmt.Fprint(dockerCli.Err(), "[ NOTE ] ")
140192
}
141-
_, _ = fmt.Fprintf(dockerCli.Err(), format+"\n\n", args...)
193+
_, _ = fmt.Fprintf(dockerCli.Err(), bold(format)+"\n", args...)
142194
}

vendor/github.com/docker/docker/api/types/auxprogress/push.go

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/modules.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ github.com/docker/distribution/uuid
6060
## explicit
6161
github.com/docker/docker/api
6262
github.com/docker/docker/api/types
63+
github.com/docker/docker/api/types/auxprogress
6364
github.com/docker/docker/api/types/blkiodev
6465
github.com/docker/docker/api/types/checkpoint
6566
github.com/docker/docker/api/types/container

0 commit comments

Comments
 (0)