@@ -2,6 +2,7 @@ package image
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
67 "io"
78 "os"
@@ -73,9 +74,8 @@ func RunPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error
7374
7475 printNote (dockerCli , `Selecting a single platform will only push one matching image manifest from a multi-platform image index.
7576This 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 )
77+ If you want to only push a single platform image while preserving the attestations, please use 'docker convert\n'
78+ ` )
7979 }
8080
8181 ref , err := reference .ParseNormalizedNamed (opts .remote )
@@ -116,20 +116,64 @@ Example: echo "FROM %s" | docker build - --platform %s -t <NEW-TAG>
116116 return err
117117 }
118118
119+ defer func () {
120+ if strippedNote != "" {
121+ fmt .Fprintln (dockerCli .Err (), "" )
122+ printNote (dockerCli , strippedNote )
123+ }
124+ }()
125+
119126 defer responseBody .Close ()
120127 if ! opts .untrusted {
121128 // TODO PushTrustedReference currently doesn't respect `--quiet`
122129 return PushTrustedReference (dockerCli , repoInfo , ref , authConfig , responseBody )
123130 }
124131
125132 if opts .quiet {
126- err = jsonmessage .DisplayJSONMessagesToStream (responseBody , streams .NewOut (io .Discard ), nil )
133+ err = jsonmessage .DisplayJSONMessagesToStream (responseBody , streams .NewOut (io .Discard ), handleAux ( dockerCli ) )
127134 if err == nil {
128135 fmt .Fprintln (dockerCli .Out (), ref .String ())
129136 }
130137 return err
131138 }
132- return jsonmessage .DisplayJSONMessagesToStream (responseBody , dockerCli .Out (), nil )
139+ return jsonmessage .DisplayJSONMessagesToStream (responseBody , dockerCli .Out (), handleAux (dockerCli ))
140+ }
141+
142+ var strippedNote = ""
143+
144+ func handleAux (dockerCli command.Cli ) func (jm jsonmessage.JSONMessage ) {
145+ return func (jm jsonmessage.JSONMessage ) {
146+ b := []byte (* jm .Aux )
147+
148+ aux := map [string ]string {}
149+ err := json .Unmarshal (b , & aux )
150+ if err != nil {
151+ return
152+ }
153+
154+ strippedNote = string (b )
155+
156+ _ , stripped := aux ["Stripped" ]
157+ if stripped {
158+ index := aux ["Index" ]
159+ mfst := aux ["Manifest" ]
160+
161+ strippedNote = fmt .Sprintf (`Not all multiplatform-content is present and only the available single-platform image was pushed
162+ %s -> %s` , red (index ), green (mfst ))
163+ }
164+ }
165+ }
166+
167+ func red (text string ) string {
168+ return fmt .Sprintf ("\033 [31m%s\033 [0m" , text )
169+ }
170+
171+ func green (text string ) string {
172+ return fmt .Sprintf ("\033 [32m%s\033 [0m" , text )
173+ }
174+
175+ func bold (text string ) string {
176+ return fmt .Sprintf ("\033 [1m%s\033 [0m" , text )
133177}
134178
135179func printNote (dockerCli command.Cli , format string , args ... any ) {
@@ -138,5 +182,5 @@ func printNote(dockerCli command.Cli, format string, args ...any) {
138182 } else {
139183 _ , _ = fmt .Fprint (dockerCli .Err (), "[ NOTE ] " )
140184 }
141- _ , _ = fmt .Fprintf (dockerCli .Err (), format + " \n \n " , args ... )
185+ _ , _ = fmt .Fprintf (dockerCli .Err (), bold ( format ) + " \n " , args ... )
142186}
0 commit comments