From 90c884a2b53965bcf577ed1c2151705f859cb52e Mon Sep 17 00:00:00 2001 From: Dean Chen <862469039@qq.com> Date: Thu, 29 Oct 2026 21:45:30 +0500 Subject: [PATCH] manifest: allow an empty --variant to clear it annotate only wrote the variant when the string was non-empty, so `--variant ""` left the previous value in place. Fixes #4352 Signed-off-by: Dean Chen <862469039@qq.com> --- cli/command/manifest/annotate.go | 8 ++++--- cli/command/manifest/annotate_test.go | 32 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/cli/command/manifest/annotate.go b/cli/command/manifest/annotate.go index a9507deb73f0..7231d161e1de 100644 --- a/cli/command/manifest/annotate.go +++ b/cli/command/manifest/annotate.go @@ -84,7 +84,7 @@ func newAnnotateCommand(dockerCLI command.Cli) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { opts.target = args[0] opts.image = args[1] - return runManifestAnnotate(dockerCLI, opts) + return runManifestAnnotate(dockerCLI, cmd, opts) }, DisableFlagsInUseLine: true, } @@ -100,7 +100,7 @@ func newAnnotateCommand(dockerCLI command.Cli) *cobra.Command { return cmd } -func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error { +func runManifestAnnotate(dockerCLI command.Cli, cmd *cobra.Command, opts annotateOptions) error { targetRef, err := normalizeReference(opts.target) if err != nil { return fmt.Errorf("annotate: error parsing name for manifest list %s: %w", opts.target, err) @@ -132,7 +132,9 @@ func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error { for _, osFeature := range opts.osFeatures { imageManifest.Descriptor.Platform.OSFeatures = appendIfUnique(imageManifest.Descriptor.Platform.OSFeatures, osFeature) } - if opts.variant != "" { + // An empty --variant is how you clear one. The zero value is also the + // default when the flag is omitted, so only write it when it was set. + if cmd.Flags().Changed("variant") { imageManifest.Descriptor.Platform.Variant = opts.variant } if opts.osVersion != "" { diff --git a/cli/command/manifest/annotate_test.go b/cli/command/manifest/annotate_test.go index f2c924e45ffc..5a7527e2259e 100644 --- a/cli/command/manifest/annotate_test.go +++ b/cli/command/manifest/annotate_test.go @@ -11,6 +11,38 @@ import ( "gotest.tools/v3/golden" ) +func TestManifestAnnotateClearsVariant(t *testing.T) { + manifestStore := store.NewStore(t.TempDir()) + + cli := test.NewFakeCli(nil) + cli.SetManifestStore(manifestStore) + namedRef := ref(t, "alpine:3.0") + imageManifest := fullImageManifest(t, namedRef) + imageManifest.Descriptor.Platform.Variant = "v7" + err := manifestStore.Save(ref(t, "list:v1"), namedRef, imageManifest) + assert.NilError(t, err) + + cmd := newAnnotateCommand(cli) + cmd.SetArgs([]string{"--os", "linux", "example.com/list:v1", "example.com/alpine:3.0"}) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + assert.NilError(t, cmd.Execute()) + + got, err := manifestStore.Get(ref(t, "list:v1"), namedRef) + assert.NilError(t, err) + assert.Check(t, is.Equal("v7", got.Descriptor.Platform.Variant)) + + cmd = newAnnotateCommand(cli) + cmd.SetArgs([]string{"--variant", "", "example.com/list:v1", "example.com/alpine:3.0"}) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + assert.NilError(t, cmd.Execute()) + + got, err = manifestStore.Get(ref(t, "list:v1"), namedRef) + assert.NilError(t, err) + assert.Check(t, is.Equal("", got.Descriptor.Platform.Variant)) +} + func TestManifestAnnotateError(t *testing.T) { testCases := []struct { args []string