diff --git a/cmd/oras/internal/display/metadata/text/push.go b/cmd/oras/internal/display/metadata/text/push.go index c6581d786..602656344 100644 --- a/cmd/oras/internal/display/metadata/text/push.go +++ b/cmd/oras/internal/display/metadata/text/push.go @@ -44,6 +44,10 @@ func (p *PushHandler) OnCopied(opts *option.Target) error { // OnCompleted is called after the push is completed. func (p *PushHandler) OnCompleted(root ocispec.Descriptor) error { - _, err := fmt.Fprintln(p.out, "Digest:", root.Digest) + _, err := fmt.Fprintln(p.out, "ArtifactType:", root.ArtifactType) + if err != nil { + return err + } + _, err = fmt.Fprintln(p.out, "Digest:", root.Digest) return err } diff --git a/cmd/oras/internal/display/metadata/text/push_test.go b/cmd/oras/internal/display/metadata/text/push_test.go new file mode 100644 index 000000000..706f4dc75 --- /dev/null +++ b/cmd/oras/internal/display/metadata/text/push_test.go @@ -0,0 +1,74 @@ +/* +Copyright The ORAS Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package text + +import ( + "bytes" + "fmt" + "io" + "testing" + + "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +type errorWriter struct{} + +// Write implements the io.Writer interface and returns an error in Write. +func (w *errorWriter) Write(p []byte) (n int, err error) { + return 0, fmt.Errorf("got an error") +} + +func TestPushHandler_OnCompleted(t *testing.T) { + content := []byte("content") + tests := []struct { + name string + out io.Writer + root ocispec.Descriptor + wantErr bool + }{ + { + "good path", + &bytes.Buffer{}, + ocispec.Descriptor{ + MediaType: "example", + Digest: digest.FromBytes(content), + Size: int64(len(content)), + }, + false, + }, + { + "error path", + &errorWriter{}, + ocispec.Descriptor{ + MediaType: "example", + Digest: digest.FromBytes(content), + Size: int64(len(content)), + }, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &PushHandler{ + out: tt.out, + } + if err := p.OnCompleted(tt.root); (err != nil) != tt.wantErr { + t.Errorf("PushHandler.OnCompleted() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/test/e2e/suite/command/push.go b/test/e2e/suite/command/push.go index 741c70e20..c74ae0e10 100644 --- a/test/e2e/suite/command/push.go +++ b/test/e2e/suite/command/push.go @@ -371,6 +371,25 @@ var _ = Describe("Remote registry users:", func() { Expect(manifest.Config).Should(Equal(artifact.EmptyLayerJSON)) }) + It("should output artifact type when push is complete for image-spec v1.1", func() { + repo := pushTestRepo("print-artifact-type-v1-1") + tempDir := PrepareTempFiles() + + ORAS("push", RegistryRef(ZOTHost, repo, tag), foobar.FileBarName, "-v", "--image-spec", "v1.1"). + MatchKeyWords("ArtifactType: ", "application/vnd.unknown.artifact.v1"). + WithWorkDir(tempDir).Exec() + }) + + It("should output artifact type when push is complete for image-spec v1.0 when --config is used", func() { + repo := pushTestRepo("print-artifact-type-v1-0-config") + configType := "config/type" + tempDir := PrepareTempFiles() + + ORAS("push", RegistryRef(ZOTHost, repo, tag), "--config", fmt.Sprintf("%s:%s", foobar.FileConfigName, configType), foobar.FileBarName, "-v", "--image-spec", "v1.0"). + MatchKeyWords("ArtifactType: ", configType). + WithWorkDir(tempDir).Exec() + }) + It("should push v1.1-rc.4 artifact", func() { repo := pushTestRepo("v1.1-artifact") tempDir := PrepareTempFiles()